On Fri, Nov 01, 2019 at 04:37:15PM -0400, Jason Merrill wrote:
> On 10/22/19 10:53 AM, Marek Polacek wrote:
> > This patch implements C++20 P0960R3: Parenthesized initialization of
> > aggregates
> > (<wg21.link/p0960>; see R0 for more background info). Essentially, if you
> > have
> > an aggregate, you can now initialize it by (x, y), similarly to {x, y}.
> > E.g.
> >
> > struct A {
> > int x, y;
> > // no A(int, int) ctor (see paren-init14.C for = delete; case)
> > };
> > A a(1, 2);
> >
> > The difference between ()-init and {}-init is that narrowing conversions are
> > permitted, designators are not permitted, a temporary object bound to
> > a reference does not have its lifetime extended, and there is no brace
> > elision.
> > Further, things like
> >
> > int a[](1, 2, 3); // will deduce the array size
> > const A& r(1, 2.3, 3); // narrowing is OK
> > int (&&rr)[](1, 2, 3);
> > int b[3](1, 2); // b[2] will be value-initialized
> >
> > now work as expected. Note that
> >
> > char f[]("fluff");
> >
> > has always worked and this patch keeps it that way. Also note that A a((1,
> > 2))
> > is not the same as A a{{1,2}}; the inner (1, 2) remains a COMPOUND_EXPR.
> >
> > The approach I took was to handle (1, 2) similarly to {1, 2} -- conjure up
> > a CONSTRUCTOR, and introduce LOOKUP_AGGREGATE_PAREN_INIT to distinguish
> > between the two. This kind of initialization is only supported in C++20;
> > I've made no attempt to support it in earlier standards, like we don't
> > support CTAD pre-C++17, for instance.
>
> Could we use a flag on the CONSTRUCTOR to distinguish between them instead,
> rather than a LOOKUP flag and a flag in the conversion?
I think I tried and it didn't play well with digest_init and narrowing.
If we have { 2.0 } then when recursing on the CONSTRUCTOR element we
don't know it came from a paren-init, so a LOOKUP flag was necessary.
Marek