The difference can be reduced to
struct A { explicit A(int); }; struct B { B(int); }; void f(A); void f(B); int main() { f({ 1 }); }
GCC does not succeed, according to the standard (which states that explicit constructors are taken into account to initialize the list, so they can give ambiguity, but they simply cannot be selected). Klang accepts it and calls the second function.
In your case, what @Columbo says in his response to Direct List Initialization compiles successfully, but normal direct initialization fails, why? . With the difference that in your case B(const B&); it is no longer acceptable for the Clan, because the conversion {0} -> B would have to have two possibilities: an explicit constructor or recursively use the copy constructor a second time. The first option, as explained above, will not be considered by clang, and this time the @Columbo explanation is applied, and the copy constructor cannot be used a second time, because this will require a user-defined transformation, since we have one element (here, 0 ) Thus, in the summary, only the first constructor succeeds and is taken.
Since I understand that we are talking about strange rules for resolving congestion, and some may not be able to follow, here is a more intuitive explanation. Rules that are active in order
Therefore, for GCC, it can directly use an explicit constructor and, in addition, one use of the copy constructor. For clang, it takes into account directly the use of an explicit constructor and will not use it indirectly by initializing the copy list using a copy constructor such as GCC. Both will not consider using the copy constructor a second time, and that doesn't matter here.
Johannes Schaub - litb
source share