C++ operator overloading synthetic conversion - c++

This example is from "Thinking in C++", I have one question regarding compiler synthesizing the operator conversion function.
Question
When object of class Four is passed (in the function call f()), the overload operation () is called. But I am not able to make out the logic used (compiler synthesizes the operation call) by compiler to achieve this conversion.
At max, I can expect explicit conversion behavior, like
1. obj3 = (Three)obj4;
2. obj3 = Three(obj4);
3. obj3 = static_cast<Three> (obj4);
Now for any one of the above conversion - how does the compiler synthesize,
(Three) obj4.operator()?
May be I am missing some major point.
Example
//: C12:Opconv.cpp
// Op overloading conversion
class Three {
int i;
public:
Three(int ii = 0, int = 0) : i(ii) {}
};
class Four {
int x;
public:
Four(int xx) : x(xx) {}
operator Three() const { return Three(x); }
};
void g(Three) {}
int main() {
Four four(1);
g(four);
g(1); // Calls Three(1,0)
} ///:~

First of all it is not operator() which you have provided, it is operator Three. This operator tells the compiler how to convert an object of class Four to an object of class Three. In g(four) call compiler is using this operator since the function g is expecting an argument of type Three. Since there is an conversion available compiler is using it. In the second case, since the constructor of Three is not declared as explicit and it is possible to construct a object of class Three using a single integer (using Three constructor) compiler is using that constuctor to create an object of the class Three so that function g can be called.

First of all, class Four does not contain an operator(), but it does have an operator Three(), which is a conversion operator.
In the line
g(four);
the compiler needs to convert four to an object of class Three and synthesises a call to operator Three() to perform that conversion.
The synthesised conversion is equivalent to
g(four.operator Three());

Related

C++ literal passed to const reference leads to automatic construction

If I call the "func(const generic& ref)" with an integer as argument (instead of a 'generic' object), the constructor generic(int _a) will be called to create a new object.
class generic {
public:
int a;
generic() {}
generic(int _a) : a(_a) {
std::cout << "int constructor was called!";
}
generic(const generic& in) : a(in.a) {
std::cout << "copy constructor was called!";
}
};
void func(const generic& ref) {
std::cout << ref.a;
}
int main() {
generic g(2);
func(g); // this is good.
func(generic(4)); // this is good.
func(8); // this is good...... ?
return 0;
}
The last "func(8)" call creates a new object using the constructor generic(int _a). Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument? Like this:
func(generic(8));
Is there any benefit in passing the integer alone (other than saving time)?
This behavior is part of overload resolution process - specifically.
When you call func(), the compiler constructs a list of candidates. There's only one candidate, func(const generic& ref), so the compiler tries to figure out how to make a call.
It sees that there is no func(int) defined, so it tries to find a conversion path from int to generic. Since there is a constructor of generic that takes an int, and there are no other conversions allowing to perform the same call, the compiler takes the construction+call path.
The compiler checks three things, in the order from higher to lower priority:
Exact match
Promotion
Conversion
This means that an exact match of the signature trumps a match that requires a promotion, and a match that requires a promotion trumps a match that needs a conversion.
See "Ranking of implicit conversion sequences" of the document linked above for information on how implicit conversions are applied.
Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument?
If you don't want this to happen, you can add the explicit specifier to your constructor:
explicit generic(int _a) : a(_a)
{
std::cout << "int constructor was called!";
}
An excerpt from the cppreference page:
A constructor that is declared without the function specifier explicit is called a converting constructor.
By default, implicit constructor calls are allowed in this circumstance.
Is there any benefit in passing the integer alone (other than saving time)?
Whether you call the method with func(8) or func(generic(8)) isn't going to change what code executes given the code you have written. If you were to add an overload of func that takes an int instead of a generic, then the calls would suddenly become different. So, although it is ultimately a matter of opinion, I think you are better off being explicit by using func(generic(8)).

Is it called "implicit casting" or "implicit conversion"?

Even though I see the term implicit casting used widely in C++ tutorials to denote the fact that when you assign some type to another type the conversion of types will be done automatically (implicitly), but I often hear that it should be called implicit conversion and not implicit casting. Can anyone tell me the difference between the two?
It should normally be called implicit conversion.
Just about the only time you might see somebody reasonably talk about an "implicit cast" would be when talking about a cast operator in a class. For example:
class T {
int x;
public:
T (int x) : x(x) {}
operator int() { return x; }
};
Some people call this a cast operator, and this is one that can be implicitly invoked. As of C++11, you can add explicit to it:
class T {
int x;
public:
T (int x) : x(x) {}
explicit operator int() { return x; }
};
...to prevent implicit invocation. For example, this means:
T t(10);
int x = t; // works with the first version, not the second
int y = static_cast<int>(t); // works with either version
So, if somebody were comparing/contrasting these two, it could sort of make sense for them to refer to the first one as an "implicit cast operator" (or something like that) to differentiate it from the second one.

About conversion constructor and assignment operator

How it comes that operation like foo = int can be done by both foo(int) (conversion constructor) and foo::operator=(int) (overloaded assignment operator)? When one be called instead of other (maybe one is rudimentary)?
#include <iostream>
class foo
{
public:
foo(){}
foo(int r_value)
{
std::cout << "\nfoo::foo(int)\n";
}
void operator=(int r_value)
{
std::cout << "\nfoo::operator=(int)\n";
}
};
int main()
{
foo f;
f = 57;
return 0;
}
Code above makes operator=(int) to run when both exist and foo(int) if operator=(int) is commented (or opposite).
This is basic overload resolution. Both overloads are viable:
Binding 57 to foo::operator=(int) (exact match)
Implicitly converting 57 to foo via the converting constructor, and binding the temporary foo object to the implicitly defined foo::operator=(foo const &).
Since the latter requires more conversions than the former, it is a less-good match, and the former overload is chosen.
You can still achieve the second call by making it explicit:
f = foo(57); // binds perfectly to foo::operator=(foo const &)
The full set of rules for overload resolution are rather long and involved, but in individual cases like this the answer is straight-forward. See 13.3 ([over.match]) for the full, gory details, though.
There is a difference:
foo a = 10;
Calls foo::foo(int)
foo a;
a = 10;
Calls foo::operator=(int) in a
Both of the implementations are different. The first is a Constructor and the second is an assignment. The Use cases varies, and each of them would be called accordingly based on the use case.
Use Case
The Constructor is called foo::foo(int)
foo f = 57;
The Assignment is called foo::operator=(int)
foo f;
f = 57;
Note
Using assignment in the above use case and in your example has more overhead, as it called the default constructor along with the assignment.
For this statement
f = 57;
the compiler at first considers all functions operator =. There are two such functions: the explicitly defined by you and the copy assignment operator implicitly defined by the compiler. The first one is the best suitable function. So it is called.
If you will comment this assignment operator then the compiler has only one function operator =. It is the implicitly defined copy assignment operator. But it can not be applied directly. So the compiler seeks a way to convert supplied argument to type foo. And it can do this by calling the conversion construuctor.

How does constructor conversion work in C++?

How does constructor conversion work?
#include <iostream>
using namespace::std;
class One {
public:
One() { cout<<"One"<<endl;}
};
class Two {
public:
Two(const One&) {cout<<"Two(const One&)"<<endl;}
};
void f(Two) {cout<<"f(Two)"<<endl;}
int main() {
One one;
f(one);
}
produces the output
One
Two(const One&)
f(Two)
Any constructor that can be called with a single argument is considered an implicit conversion constructor. This includes simple 1-argument cases, and usage of default arguments.
This conversion is considered in any context that wants X and provided Y, and Y has such implicit conversion possibility. Note that a plenty of other, built-in conversions also play as a mix (like adjusting const-ness, integral and fp promotions, conversions, etc.) The rule is that at most one "user defined" implicit conversion is allowed in the mix.
In some cases it may be quite surprising, so the general advice is to make any such ctors explicit. That keyword makes the conversion possible but not implicitly: you must use T() syntax to force it.
As an example consider std::vector that has a ctor taking size_t, setting the initial size. It is explicit -- otherwise your foo(vector<double> const& ) function could be mistakenly called with foo(42).
It's right result. Since constructor is not explicit - implicit conversion works (here One is implicitly converted to Two).
one is created, then when passed to f converted to Two.
What the Two(const One&) {cout<<"Two(const One&)"<<endl;} constructor means is that you're allowed to construct a Two value at any time - implicitly - from a One. When you call f(one) it wants a Two parameter, it's given a One, so the compiler puts 2 and 2 together and says "I'll make a temporary Two from the One and complete the call to f()"... everyone will be happy. Hurray!
Compiler has to create copy of Two instance on stack. When you call f() with argument which is object of class One (or any other) compiler looks to definition of class Two and tries to find constructor which takes One(or any other) object(or reference) as an argument. When such constructor has been found it constructs object using it. It's called implicit because compiler do it without your interference.
class Foo {
public:
Foo(int number) {cout<<"Foo(int number)"<<endl;}
};
void f(Foo) {cout<<"f(Foo)"<<endl;}
int main() {
f(24);
} ///:~
Output will be:
Foo(int number)
f(Foo)

Conversion Operators in C++

Please help me understand how exactly the conversion operators in C++ work.
I have a simple example here which I am trying to understand, though it is not very clear how the conversion actually happens by the compiler.
class Example{
public:
Example();
Example(int val);
operator unsigned int();
~Example(){}
private:
int itsVal;
};
Example::Example():itsVal(0){}
Example::Example(int val):itsVal(val){}
Example::operator unsigned int (){
return (itsVal);
}
int main(){
int theInt = 5;
Example exObject = theInt; // here
Example ctr(5);
int theInt1 = ctr; // here
return 0;
}
You can walk through that code with a debugger (and/or put a breakpoint on each of your constructors and operators) to see which of your constructors and operators is being invoked by which lines.
Because you didn't define them explicitly, the compiler also created a hidden/default copy constructor and assignment operator for your class. You can define these explicitly (as follows) if you want to use a debugger to see where/when they are being called.
Example::Example(const Example& rhs)
: itsVal(rhs.itsVal)
{}
Example& operator=(const Example& rhs)
{
if (this != &rhs)
{
this->itsVal = rhs.itsVal;
}
return *this;
}
int main() {
int theInt = 5;
/**
* Constructor "Example(int val)" in effect at the statement below.
* Same as "Example exObject(theInt);" or "Example exObject = Example(theInt);"
*/
Example exObject = theInt; // 1
Example ctr(5);
/**
* "operator unsigned int()" in effect at the statement below.
* What gets assigned is the value returned by "operator unsigned int()".
*/
int theInt1 = ctr; // 2
return 0;
}
At statement 1 the constructor Example(int val) is called. Declare it as explicit Example(int val) and you will get a compile time error i.e. no implicit conversion will then be allowed for this constructor.
All single argument constructors are called implicitly if the assigned value is of their respective argument type. Using the explicit keyword before single argument constructors disables implicit constructor calling and hence implicit conversion.
If the constructor was declared as explicit i.e. explicit Example(int val) then the following would happen for each statement.
Example exObject(theInt); // Compile time error.
Example exObject = theInt; // Compile time error.
Example exObject(Example(theInt)); // Okay!
Example exObject = Example(theInt); // Okay!
Also note that in case of implicit constructor call and hence implicit conversion the assigned value is an rvalue i.e. an un-named object implicitly created using an lvalue (theInt) which tells us that in case of implicit conversion the compiler converts
Example exObject = theInt;
to
Example exObject = Example(theInt);
So (in C++11) don't expect the lvalue constructor to be called seeing that you are using an lvalue i.e. a named value theInt for assignment. What gets called is the rvalue constructor since the assigned value is actually the un-named object created using the lvalue. However, this applies if you have both lvalue and rvalue versions of the constructor.
At statement 2 operator unsigned int() is called. Simply consider it as a normal function call with a weird name and the fact that it can get called automagically when an implicit conversion happens. The value returned by that function is the value assigned in the expression. And since in you implementation the value returned is an int it correctly gets assigned to int theInt1.
To be precise operator unsigned int() overloads () operator which is the cast operator. In your case it's overloaded for int hence whenever an object of Example class is assigned to an int the implicit type casting from Example to int takes place and hence operator unsigned int() gets called. Therefore,
int theInt1 = ctr;
is equivalent to
int theInt1 = (int)ctr;
Example exObject = theInt; // implicitly created copy constructor takes place
// object implicitly created from int and then copied
// it is like
Example exObject = Example(theInt);
// so it uses sequence
// Example(int) -> Example(const Example&)
int theInt1 = ctr; // operator int()
If you compiler supports copy constructor optimization and return value optimization you won't notice
Example(const Example&)
execution, but you can declare copy constructor to be private to understand what I am talking about.
Example exObject = theInt; // here
This uses implicit conversion of int to Example, effected by the non-explicit constructor which accepts an int.
This also requires the availability of copy constructor for Example, even though the compiler is allowed to omit copying the instance.
int theInt1 = ctr; // here
This uses implicit conversion of Example to unsigned int, provided by the cast operator.
Cast operators are normally avoided, since they tend to lead to confusing code, and you can mark single-argument constructors explicit, to disable implicit conversions to your class type. C++0x should add also the possibility to mark conversion operators explicit (so you'd need a static_cast to invoke them? - my compiler doesn't support them and all web resources seem to be concentrating on explicit conversion to bool).