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 ints by 1,2 and 3 respectively), it is explicit and thus cannot be called implicitly.
Why don't the compiler just check the explicitness 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...?