Consider the following code snippet:
#include <iostream> struct A { A() {} A(const A&) {} }; struct B { B(const A&) {} }; void f(const A&) { std::cout << "A" << std::endl; } void f(const B&) { std::cout << "B" << std::endl; } int main() { A a; f( {a} ); // A f( {{a}} ); // ambiguous f( {{{a}}} ); // B f({{{{a}}}}); // no matching function }
Why does each call fabricate the corresponding output? How does the number of braces affect uniform initialization? And how does brace elision affect all this?
Uniform Initialization in C++ The uniform initialization is a feature that permits the usage of a consistent syntax to initialize variables and objects which are ranging from primitive type to aggregates. In other words, it introduces brace-initialization that applies braces ({}) to enclose initializer values.
Initialization of a variable provides its initial value at the time of construction. The initial value may be provided in the initializer section of a declarator or a new expression. It also takes place during function calls: function parameters and the function return values are also initialized.
Overload resolution is fun like this.
{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.
const A&
parameter (as above) to the constructor for either A
or B
, so the call is ambiguous.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.)No brace elision is involved—we don’t know the outermost target type to allow it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With