I came from Java, so when need to call a function like this:
struct A {
int a;
A(int a) : a(a){ }
};
A foo(A a){
return A(a);
}
I tend to write something like
A a = foo(A(10));
and it works perfectly fine. But I learnt that it can also be done in this way::
A a = foo(static_cast<A>(10));
I.e. it enforces the implicit conversion. So, as a rule of thumb should we alsways use static_cast-style when we need to exploit implicit conversion? Or there are some cases where function/C-style casts may be necessary?
You never need C-style casts in C++. As for your examples, the most common way to write it would be this one:
A a = foo(A(10));
There are two separate aspects worth (re)consideration here: should A::A(int) be left implicit, and how best to construct an A to pass to foo.
For the former, there's no way of deciding without knowing the usage A should support, but it's generally recommended to err on the side of having explicit constructors if unsure.
For construction, use A(10) (with C++11, A{10} works too), or just 10 to rely on the implicit conversion. Note that A(10) is a constructor call not a cast: there's no need to consider static_cast<>() as a preferred casting notation. The old C-style cast notation is actually (T)
cast-expression, per 5.4 [expr.cast] in the C++ Standard.
When you want to do a conversion from type A to B, you have two syntaxes to define the conversion:
class B
{
public:
B(A); # Conversion constructor.
};
or
class A
{
public:
operator B(); # Conversion operator.
};
For a case like:
void f(B b);
int main()
{
A a;
f(a);
}
If the first version exists, it creates a temporary object of class B, using a as parameter. If the second version exists (and you implement it, of course), it calls the operator B() of class A to create an object of type B from a. If both exists, the compiler throws you a message of ambiguity error.
About down/up-casting, implicit conversions allow upcasting (if source and target types are references/pointers), even if the target base is an innacesible (private) base class of the source. Implicit conversions also allow conversion from a non-const source type to a const target type, or also conversion from rvalue to lvalue and so on.
These are, in short, the rules of implicit conversions. A more complete guide (considering built-in versus user-defined types and built-in conversions) is here.
If you use the C++-casting:
f(static_cast<B>(a));
its nearly the same but with some differences: if B is an innaccesible (private) base of a, the cast isn't allowed. The other difference is that downcasting is allowed without runtime check (if B is a derived class of A it allows the casting, even if a isn't actually an object of type B). That is allowed because runtime check is slow, so, if you KNOW a is actually of type B, you can safely apply the casting without runtime check.
Other castings are:
const_cast<B>(a)
Only to change from const to non-const and viceversa.
reinterpret_cast<B>(a);
Cast everything. Nearly no rules involved. If a conversion from a to B doesn't exists, it just takes the memory region of a and returns it as an object of type B. Its the fastest cast alive.
dynamic_cast<B>(a);
Downcasting with runtime check (both types must be references or pointers). If the real type of a isn't B (not even a base class of the real type of a), an exception or null pointer is thrown/returned (according to if a or B are references or pointers).
Lastly, the C-casting:
f((B)a);
What the C-casting does is to try different castings (except dynamic_cast, and also allowing casting to innacesible base classes) and use the first which works. I would say the C-casting is as powerful as the implicit cast.
The explicit casting with syntax of funcion call:
f(B(a));
is equivalent to the C-casting in behaviour.
Related
Considering the following function template func declared within MyClass class template:
template < T >
class MyClass {
public:
MyClass() = default;
// ...
template < typename oT >
oT func() {
return static_cast< oT >(_m); // alternative, return oT(_m);
}
// ...
protected:
T _m;
};
Is there any advantage in calling static_cast< oT >(_m) over explicit instantiation i.e. oT(_m)?
oT(_m) will allow many more conversions than is probably intended. If static_cast<oT>(_m) wouldn't be possible, then oT(_m) will also try a const_cast, static_cast followed by const_cast, reinterpret_cast and reinterpret_cast followed by const_cast.
For example if T is const int* and oT is double*, then oT(_m) will succeed, while static_cast<oT>(_m) will fail. But using the result from oT(_m) as if it was a pointer to a double will result in undefined behavior.
If T and oT are pointers to classes that is maybe even more dangerous, since oT(_m) will always compile, whether or not there is an inheritance relation between the two classes.
Even static_cast allows for some conversions that may not be intended. For example it can downcast pointers to classes.
Another alternative is simply return _m;. This is weaker than both variants above. It will only allow for copy-initialization. However that might be too weak depending on your use case. For example it will not use explicit constructors and conversion functions. On the other hand before C++17 it doesn't require oT to be move-constructible, which the first two variants do require before C++17.
So you will need to decide what casts are supposed to be allowed and which ones are supposed to fail.
However, nothing prevents a user from calling func<T>() to obtain the original type anyway and the user can then simply cast it however they like, so I am not sure what is gained here over a simple getter.
Even more so, the user can in either case call func<T&>() and will get a reference to the member, thereby making the protected somewhat pointless. Maybe the allowed types T need to be constrained via SFINAE/requires-clause.
This is for an application that is written in C++. Under what circumstances would this line make sense to any of you, in the context of a struct definition (stream is a member variable of type FILE*):
operator FILE*(){return stream;}
I have been going through with a debugger, trying to make sense of it, but I can't seem to make that line of code activate. I have never encountered the operator overload keyword in such a fashion. What can this line of code do?
This is an implicit conversion operator.
Implicit conversion operators allow a type that would not otherwise implicitly convert to a destination type, the ability to do so. They have the following syntax, where Foo is the class of the object to be implicitly converted, and Bar is the destination class:
class Foo{
public:
operator Bar(); // allow implicit conversion of Foo objects to Bar
};
The more common instance of this operator is in converting an object to a boolean value as a validity check. This can be seen with the standard library's streams, and smart pointers.
You should note the presence of a variation on the syntax, which prevents the existing conversion, and makes the conversion explicit instead:
class Foo{
public:
explicit operator Bar(); // allow explicit conversion of Foo objects to Bar
};
This prevents getting bitten by a compiling program when you accidentally feed a type A that can convert into a type B into a function that accepts only B. Sure, that can be what you're going for, but it isn't always, and they decided to add this to the language to help people with a need for an explicit conversion.
With the explicit conversion operator, you can create an object from the origin object either via construction(using it in the construction of an object of the target type) or by explicit casting: B{A}
I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.
So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?
I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".
In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.
So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.
However, this doesn't actually work, at least not using GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
This results in :
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?
"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.
If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.
Lets concider following code:
class A{
public:
A(int x){}
};
class B{
public:
B(A a){};
};
int main() {
B b = 5;
return 0;
}
And while compiling the compiler complains that:
/home/test/main.cpp:80: candidate constructor not viable: no known conversion from 'int' to 'A' for 1st argument
I don't want to create B(int) constructor - I would love the compiler to implicit convert this int to A object.
EDIT:
Direct initialisation works like this:
B b(5);
Is it possible to use the assigment operator instead?
Just to be clear:
B b = 5;
is "copy initialisation" not assignment. (See http://www.gotw.ca/gotw/036.htm).
In this case, you are asking the compiler to perform two implicit user-defined conversions first, i.e. int -> A, A -> B before a temporary B object is passed to the copy constructor for B b. The compiler is allowed to elide the temporary object but semantically you are still asking the language to make two jumps across types.
All implicit behaviour in programming languages is inherently scary. For the sake of a little syntactic sugar, we are asking c++ to "do some magic to make it just work". Unexpected type conversions can wreck havoc in large complex programmes. Otherwise, every time you wrote a new function or a new class, you would have to worry about all the other types and functions it could affect, with the side -effects rippling across your code.
Would you really want implicit conversions from int -> apple -> horse -> horse_power -> aeroplane?
For that reason, c++ only allows a single implicit user-defined conversion:
12.3 Conversions [class.conv]
1 Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).
4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
You are better off either with an explicit cast or "direct initialisation" both of which make it clear to the compiler and collaborators exactly what you are trying to do. Either the traditional or the new uniform initialisation syntax works:
B b(5);
B b{5};
B b = {5};
Use direct initialisation instead:
B b(5);
You can use a converting constructor that is constrained on conversions to A.
class B {
public:
// It doesn't hurt to keep that one
B(A a){};
template<
typename T
, EnableIf<std::is_convertible<T, A>>...
>
B(T&& value)
{
// How to use the value
A a = std::forward<T>(value);
}
};
// Now B b = foo; is valid iff A a = foo; is, except for a few exceptions
Make sure you understand the purpose of the EnableIf constraint. If you do not use it, you will face gnarly compilation errors, or worse: no errors at all. You should also carefully consider if making B convertible from potentially lots of types is at all worth it. Implicit conversions tend to make a program harder to understand, and that can quickly outweigh the apparent benefits they give.
There are two classes: A and B. There are algorithms for converting from type A to type B and back. We cannot touch the source code of them. Can I write an implicit conversion between the two types?
Example code which should work:
B CalculateSomething(double x)
{
A a(x);
a.DoSomethingComplicated();
return a;
}
No, I don't think so. Implicit conversion is usually coded with an overloaded operator. It is done for base types too. As you can't modify A and B code there is no way to tell the compiler how to do that. Your snippet will get an error.
You have to do explicit conversion. Just
return helper.convertToB(a);
my2c
No, but you can write a named free function to do it.
B ToB( const A & a ) {
B b;
// process a somehow to add its data to b
return b;
}
Your code then becomes:
B CalculateSomething(double x)
{
A a(x);
a.DoSomethingComplicated();
return ToB( a );
}
which is arguably clearer than the implicit conversion would be.
There are two classes: A and B. There are algorithms for converting from type A to type B and back. We cannot touch the source code of them. Can I write an implicit conversion between the two types?
No, if A and B aren't related you can't. (And I am grateful for that. Implicit conversions give enough headaches as they are without the ability to create them for 3rd-party classes.)
Not possible without altering class definition
Even if you can't change the implementation of A or B, you could add an inline constructor to the definition of B that takes a const A&.
I would suspect however that unless the classes really are closely related it would be better to provide an explicit conversion function - implicit conversions can be a huge source of difficult-to-find bugs:
B CalculateSomething(double x)
{
A a(x);
a.DoSomethingComplicated();
return ConvertAToB( a );
}