The braces in aggregate initialisation are largely optional, so you can write:
S c_arr[] = {1, 2, 3, 4}; // OK
std::array<S, 2> std_arr = {1, 2, 3, 4}; // OK
If you do add braces, though, then the braces are taken to apply to the next sub-object. Unfortunately, when you start nesting, this leads to silly code being valid, and sensible code like yours being invalid.
std::array<S, 2> std_arr = {{1, 2, 3, 4}}; // OK
std::array<S, 2> std_arr = {1, 2, {3, 4}}; // OK
std::array<S, 2> std_arr = {1, {2}, {3, 4}}; // OK
These are all okay. {1, 2, 3, 4}
is a valid initialiser for the S[2]
member of std_arr
. {2}
is okay because it is an attempt to initialise an int
, and {2}
is a valid initialiser for that. {3, 4}
is taken as an initialiser for S
, and it's also valid for that.
std::array<S, 2> std_arr = {{1, 2}, {3, 4}}; // error
This is not okay because {1, 2}
is taken as a valid initialiser for the S[2]
member. The remaining int
sub-objects are initialised to zero.
You then have {3, 4}
, but there are no more members to initialise.
As pointed out in the comments,
std::array<S, 2> std_arr = {{{1, 2}, {3, 4}}};
also works. The nested {{1, 2}, {3, 4}}
is an initialiser for the S[2]
member. The {1, 2}
is an initialiser for the first S
element. The {3, 4}
is an initialiser for the second S
element.
I'm assuming here that std::array<S, 2>
contains an array member of type S[2]
, which it does on current implementations, and which I believe is likely to become guaranteed, but which has been covered on SO before and is not currently guaranteed.
std::array<S, 2> std_arr{{ {1, 2}, {3, 4} }};
- outer ones surrounding constructor arguments, next pair for the initialiser list, inner pairs for eachS
element. C++14 will make it work with one less set of outer{ }
. (The=
is optional.) – Mokpo-std=c++11
and-std=c++14
: that DR resolution is applied even in C++11 mode. Aside from that, it coversstd::array<S, 2> std_arr {1, 2, 3, 4};
without the=
, so it's not relevant to this particular question anyway. :) – Dodson