Overload resolution is fun like this.
-
{a}has exact match rank for initializing (a temporary for) theconst A¶meter, which outcompetes the user-defined conversionB(const A&)as a realization of{a}. This rule was added in C++14 to resolve ambiguities in list-initialization (along with adjustments for aggregates).Note that the notional temporary is never created: after overload resolution picks
f(const A&), the reference is simply initialized to refer toa, and this interpretation can apply even for non-copyable types. - It would be permissible to initialize a
const A¶meter (as above) to the constructor for eitherAorB, so the call is ambiguous. - Calling a copy constructor (here,
A(const A&)) repeatedly is prohibited as multiple user-defined conversions—rather than allowing one such conversion per level of overload resolution. So the outermost braces must initialize aBfrom theAinitialized from{{a}}as (permitted) in the second case. (The middle layer of braces could initialize aB, but copying it with the outer layer would be prohibited and there’s nothing else to try to initialize.) - Every interpretation involves such a disallowed extra conversion.
No brace elision is involved—we don’t know the outermost target type to allow it.