what are the overload resolution rules of list-initialization
Because for #1, the copy and move constructors are disallowed by [over.best.ics]/4 (emphasized mine):
However, if the target is
- the first parameter of a constructor or
- the implicit object parameter of a user-defined conversion function
and the constructor or user-defined conversion function is a candidate by
[over.match.ctor], when the argument is the temporary in the second step of a class copy-initialization,
[over.match.copy], [over.match.conv], or [over.match.ref] (in all cases), or
the second phase of [over.match.list] when the initializer list has exactly one element that is itself an initializer list, and the target is the first parameter of a constructor of class X, and the conversion is to X or reference to cv X,
user-defined conversion sequences are not considered. [ Note: These rules prevent more than one user-defined conversion from being applied during overload resolution, thereby avoiding infinite recursion. — end note ]
So it is the language rule that distinguishes ({...})
and {{...}}
. Note the ({...})
case falls into [over.match.ctor] but the argument is NOT the temporary in the second step of a class copy-initialization, so the first bullet does not apply.
You can further read Issue 2076 to see it is intended to disallow the copy and move constructors for the inner brace in the {{...}}
case:
The resolution of issue 1467 made some plausible constructs ill-formed. For example,
struct A { A(int); }; struct B { B(A); }; B b{{0}};
This is now ambiguous, because the text disallowing user-defined conversions for B's copy and move constructors was removed from 16.3.3.1 [over.best.ics] paragraph 4...