I’ve got error C2078 in VC2010 when compiling the code below.
struct A
{
int foo;
double bar;
};
std::array<A, 2> a1 =
// error C2078: too many initializers
{
{0, 0.1},
{2, 3.4}
};
// OK
std::array<double, 2> a2 = {0.1, 2.3};
I found out that the correct syntax for a1 is
std::array<A, 2> a1 =
{{
{0, 0.1},
{2, 3.4}
}};
The question is: why extra braces are required for a1 but not required for a2?
Update
The question seems to be not specific to std::array. Some examples:
struct B
{
int foo[2];
};
// OK
B meow1 = {1,2};
B bark1 = {{1,2}};
struct C
{
struct
{
int a, b;
} foo;
};
// OK
C meow2 = {1,2};
C bark2 = {{1,2}};
struct D
{
struct
{
int a, b;
} foo[2];
};
D meow3 = {{1,2},{3,4}}; // error C2078: too many initializers
D bark3 = {{{1,2},{3,4}}};
I still don’t see why struct D gives the error but B and C don’t.
The extra braces are needed because
std::arrayis an aggregate and Plain Old Datatype (POD), unlike other containers in the standard library.std::arraydoesn’t have a user-defined constructor. Its first data member is an array of sizeN(which you pass as a template argument), and this member is directly initialized with an initializer. The extra braces are needed for the internal array which is being directly initialized.The situation is same as:
How would you initialize this? If you do this:
it gives a compilation error:
This is the same error which you get in the case of a
std::array(if you use GCC).So the correct thing to do is to use braces as follows:
which compiles fine. Once again, the extra braces are needed because you’re initializing the internal array.
—
Now the question is why are extra braces not needed in case of
double?It is becausedoubleis not an aggregate, whileAis. In other words,std::array<double, 2>is an aggregate of aggregate, whilestd::array<A, 2>is an aggregate of aggregate of aggregate1.1. I think that extra braces are still needed in the case of double also (like this), to be completely conformant to the Standard, but the code works without them. It seems I need to dig through the spec again!.
#More on braces and extra braces
I dug through the spec. This section (§8.5.1/11 from C++11) is interesting and applies to this case:
Based on what I understood from the above quote, I can say that the following should be allowed:
In the first one, braces for the inner-aggregate are completely elided, while the second has fully-braced initialization. In your case (the case of
double), the initialization uses the first approach (braces are completely elided for the inner aggregate).But this should be disallowed:
It is neither braces-elided, nor are there enough braces to be completely-braced initialization. Therefore, it is ill-formed.