I am trying to understand the changes that happened from C 14 to C 17 regarding aggregate initialization. From §9.4.2[dcl.init.aggr]/2:
The elements of an aggregate are:
- (2.1) for an array, the array elements in increasing subscript order, or
- (2.2) for a class, the direct base classes in declaration order, followed by the direct non-static data members ([class.mem]) that are not members of an anonymous union, in declaration order.
This paragraph defines what the elements of an aggregate class are. In particular, I can't get what the bold sentence means. I have this example to demonstrate my confusion:
struct Base { int mem1, mem2; };
struct Derived : Base { int mem3, mem4; };
Derived obj = { 1, 2, 3, 4 };
The object obj
is an aggregate since it satisfies the criteria defined in [dcl.init.aggr]/1. My problem, however, is what are the elements of this aggregate. It seems that the elements are Base::mem1
initialized with 1, Base::mem2
initialized with 2, Derived::mem3
initialized with 3, and Dervied::mem4
initialized with 4.
But [dcl.init.aggr]/2 states the opposite. It is said that the elements are the data members of the direct base classes, which is Base
in this case, followed by the direct non-static data members of the Derived
class (Am I parsed the wording correctly?).
The effect of the word "followed by" makes me confused; So I thought it means that the data members of Derived
are the first elements of the aggregate obj
, hence they're initialized first, then the data members of Base
are the rest elements of the aggregate, hence they are initialized next. Therefore, Derived::mem3
will be 1 and Derived::mem4
will be 2, then Base::mem1
will be 3 and Base::mem2
will be 4.
I really don't know whether or not I understood the quote correctly, but I think I don't. So any explanation regarding this point will help me alot.
CodePudding user response:
Your understanding of the concept "elements of an aggregate" is correct. However, that's not the end of aggregate initialization. There is brace elision:
Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the elements of a subaggregate; it is erroneous for there to be more initializer-clauses than elements. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the elements of the subaggregate; any remaining initializer-clauses are left to initialize the next element of the aggregate of which the current subaggregate is an element.
All implicit type conversions ([conv]) are considered when initializing the element with an assignment-expression. If the assignment-expression can initialize an element, the element is initialized. Otherwise, if the element is itself a subaggregate, brace elision is assumed and the assignment-expression is considered for the initialization of the first element of the subaggregate.
Since Base b = 1;
is not a valid initialization statement, brace elision is assumed, as defined in the first paragraph.