Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial Aggregate Initialization and Non-static Data Member Initializer

Tags:

c++

c++11

c++14

struct Point {
  int x = 0;
  int y = 10;
};

Point p = {1,};
p.x == 1;  // true
p.y == 10; // is this true?

According to the standard missing elements in initializer list are value initialized, so y should be int() or 0, but it doesn't seem to say what happen in the situation of Non-static Data Member Initializer.

Edit: According to the answer, apparently this is invalid c++11, I would like to know the situation in c++1y.

like image 325
yngccc Avatar asked Jun 04 '14 17:06

yngccc


2 Answers

C++98, C++03

Non-static data member initialisers (NSDMIs) do not exist; the question is inapplicable.


C++11

Well, first of all, this initialisation is invalid because your type is not an aggregate:

[C++11: 8.5.1/1]: An aggregate is an array or a class (Clause 9) with user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

So, aggregate initialisation can't be performed here; a constructor taking an std::initializer_list would be your only way to use that initialisation syntax ([C++11: 8.5.4/3]), but you don't have one of those either.

Consequently, the entire premise of the question is flawed: it is not possible to get yourself into this state.


C++1y

In the upcoming version of the standard, the definition of aggregates has been relaxed to allow your type to be deemed an aggregate (as long as both of those members stay public!):

[n3936: 8.5.1/1] An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

Following on from this, there's a rule that guarantees the result you're looking for:

[n3936: 8.5.1/7]: If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer, from an empty initializer list (8.5.4). [ Example:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };

initializes ss.a with 1, ss.b with "asdf", ss.c with the value of an expression of the form int{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, ’s’), and in

struct X { int i, j, k = 42; };
X a[] = { 1, 2, 3, 4, 5, 6 };
X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };

a and b have the same value —end example ]

like image 199
Lightness Races in Orbit Avatar answered Oct 13 '22 19:10

Lightness Races in Orbit


(Answer valid in C++1y, only!)

According to paragraph #7 of section "8.5.1 Aggregates" (Working Draft N3691 Date: 2013-05-16)

7 If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equalinitializer, from an empty initializer list (8.5.4).

And below the quote there is an example

[ Example: struct S { int a; const char* b; int c; int d = b[a]; }; 
S  ss = { 1, "asdf" };
 initializes ss.a with 1, ss.b with "asdf", ss.c
with the value of an expression of the form int{} (that is, 0), and
ss.d with the value of ss.b[ss.a] (that is, ’s’),

So in your example p.y will be initialized by 10.

like image 25
Vlad from Moscow Avatar answered Oct 13 '22 19:10

Vlad from Moscow