I am using Visual Studio 2013, and this is what I'm trying to figure out:
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
int x = 1;
bool y = true;
A(int _x, bool _y) : x(_x), y(_y)
{
cout << "Constructor #1" << endl;
}
A(std::initializer_list<int> init_list)
{
cout << "Constructor #2" << endl;
}
};
int main(int argc, char** argv)
{
A Aobj1(10, false);
A Aobj2(20, "false");
A Aobj3{30, false};
A Aobj4{40, "false"};
return 0;
}
The output is:
Constructor #1 Constructor #1 Constructor #2 Constructor #1
The first call to constructor #1 is fine
Now the second construction of Aobj2(int, string)
calling constructor #1 is strange. How is the compiler calling the (int, bool)
constructor with a string argument? The "false" bool
is not even converted to an int.
Aobj3
is also OK. Although the initializer_list
is of type int, the compiler calls this because of brace-initialization and converts the bool to an int.
This one again baffles me. I would have expected this to be an error because a string cannot be converted to an int (as it was with the bool), and also expected the compiler to be calling the initializer_list
constructor because it is a braced initialization. But the compiler chooses the (int, bool) constructor.
What is some background on the logic of the compiler?
Now the second construction of
Aobj2(int, string)
calling constructor #1 is strange. How is the compiler calling the(int, bool)
constructor with a string argument?
More precisely, "false"
is of type const char[6]
and could decay to const char*
, i.e. a pointer, and then could implicitly convert to bool
.
A prvalue of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type
bool
.The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become
false
. All other values becometrue
.
For the 4th case, the parameter std::initializer_list<int>
can't match the argument 40, "false"
, because there're no implicit conversion converting pointer to int
. Then the constructor taking int, bool
is selected, because "false"
could be converted to bool
implicitly as the above explained.
"false"
is a const char[6]
which decays to const char*
and pointers are implicitly convertible to bool
. That's why the compiler can call your constructor taking a int
and a bool
, since the compiler is allowed to perform one implicit conversion to make a function argument match.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With