Forwarding to an Aggregate Initializer?
For what it's worth, P0960 "Allow initializing aggregates from a parenthesized list of values" does exactly what it says. It seems to have passed EWG and is on its way into C++20.
aggregate types by definition have no other constructor to make the resolution ambiguous
That is incorrect. All classes have default constructors, as well as copy/move constructors. Even if you = delete
them or they are implicitly deleted, they still technically have such constructors (you just can't call them).
C++ being C++, there are naturally corner cases where even P0960 does the "wrong thing", as outlined in the paper:
struct A;
struct C
{
operator A(); //Implicitly convertible to `A`
};
struct A { C c; }; //First member is a `C`
C c2;
A a(c2);
The initialization of a
is a case of ambiguity. Two things could happen. You could perform implicit conversion of c2
to an A
, then initialize a
from the resulting prvalue. Or you could perform aggregate initialization of a
by a single value of type C
.
P0960 takes the backwards compatible route: if a constructor could be called (under existing rules), then it always takes priority. Parentheses only invoke aggregate initialization if there is no constructor that could have been called.