How does the number of braces affect uniform initialization?

Overload resolution is fun like this.

  1. {a} has exact match rank for initializing (a temporary for) the const A& parameter, which outcompetes the user-defined conversion B(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 to a, and this interpretation can apply even for non-copyable types.

  2. It would be permissible to initialize a const A& parameter (as above) to the constructor for either A or B, so the call is ambiguous.
  3. 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 a B from the A initialized from {{a}} as (permitted) in the second case. (The middle layer of braces could initialize a B, but copying it with the outer layer would be prohibited and there’s nothing else to try to initialize.)
  4. Every interpretation involves such a disallowed extra conversion.

No brace elision is involved—we don’t know the outermost target type to allow it.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)