The following behavior is rather strange to me:
class Y
{
public:
Y(int) { cout << "Y\n"; }
};
class X
{
public:
X(int, const Y&) { cout << "int, const Y&\n"; }
explicit X(int) { cout << "X\n"; }
X(int, X&&) { cout << "int, X&&\n"; }
X(const X&) { cout << "copy\n"; }
X(int, int, const Y&) { cout << "int, int, const Y&\n"; }
explicit X(int, int, int) { cout << "3 ints\n"; }
};
int main()
{
X x1(1, 2); // OK
X x2({ 1,2,3 }); // error, OK if X(int, int, int) becomes, say, X(int, int, X&&)
}
In my understanding, X x1(1, 2);
is OK because when the compiler tries to make an X&&
from 2
, it finds that X(int)
is explicit
, hence the compiler treats X(int, const Y&)
as a better match (had X(int)
not been explicit
, X(int, X&&)
would be the better match). On the other hand, X x2({ 1,2,3 });
is not OK because while X(int, int, int)
is treated as the better match (since there is not restriction for initializing the 3 int
s by 1
,2
and 3
respectively), it is explicit
and thus cannot be called implicitly.
Why don't the compiler just check the explicit
ness on X(int, int, int)
and "take a step back" to prefer X(int, int, const Y&)
as the better match?
The answers mentioned that ambiguity will arise if X(int)
is not explicit
. In fact, I find that for msvc C++20/17/14 there will not be ambiguity error, while gcc and clang will report the error... why...?