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