Search code examples
c++c++20

Designated initialization and base classes?


In C++20 (latest draft), given the following code:

struct B { int mb; };
struct D : B { int md; };

which of these six expressions are ill-formed and which are not?

/*1*/ D{42, 43}
/*2*/ D{{42}, 43}
/*3*/ D{42, .md = 43}
/*4*/ D{{42}, .md = 43}
/*5*/ D{.mb = 42, .md = 43}
/*6*/ D{{.mb = 42}, .md = 43}

Solution

  • (2) is your standard, explicit aggregate initialization. It's fine.

    (1) is aggregate initialization with brace elision around the B subobject. This is also fine.

    (3) and (4) are mixing designated initializers with non-designated initializers, which is not allowed. The grammar for designated-initializer-list only allows a designated-initializer-clause, which is a designator (. identifier) followed by a brace-or-equal-nitializer. There is no other form.

    (5) and (6) are trying to designated-initialize a base class subobject, which is also not allowed. All the designators have to name direct non-static data members. [dcl.init.aggr]/3.1 says:

    If the initializer list is a designated-initializer-list, the aggregate shall be of class type, the identifier in each designator shall name a direct non-static data member of the class, [...]


    The proposal makes it clear that both of these are intended. It comments that:

    The base class objects will be initialized with {}. We do not have a concrete use case for somein­depth control of how to initialize the base class objects, and the proposed design is forwardcompatible, therefore we suggest to address this issue in another proposal.

    and:

    Either all designators, or none.

    with a future issue:

    Do we allow a designation list to appear in a list­-initializer as a suffix, e.g. ​A { 1, 2, .c= 3, .d = 4 }​ ?