Martí Serra
Martí Serra

Reputation: 105

I don't know why I can't initialize an array of an array in C++

I have this piece of code in C++:

std::array<std::array<int, 2>, 4> elements = {{1,2},{1,2},{1,2},{1,2}};

and it says: error: excess elements in struct initializer

I don't know why that happens. If I write that it works:

std::array<std::array<int, 2>, 4> elements = {{1,2}};

Upvotes: 1

Views: 115

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 310930

Here are some examples how you can initialize an object of the type you are using.

#include <iostream>
#include <array>

int main() 
{
    std::array<std::array<int, 2>, 4> elements1 = { 1, 2, 1, 2, 1, 2, 1, 2 };
    std::array<std::array<int, 2>, 4> elements2 = { { 1, 2, 1, 2, 1, 2, 1, 2 } };
    std::array<std::array<int, 2>, 4> elements3 = 
    { 
        { 
            { 1, 2 }, { 1, 2 }, { 1, 2 }, { 1, 2 }
        }           
    };
    
    std::array<std::array<int, 2>, 4> elements4 = 
    { 
        { 
            { { 1, 2 } }, { { 1, 2 } }, { { 1, 2 } }, { { 1, 2 } }
        }           
    };
    
    std::array<std::array<int, 2>, 4> elements5 = 
    { 
        {
            { 1, 2 }, 1, 2, 1, 2, { 1, 2 }
        }           
    };

    return 0;
}

Pay attention to the following quote from the C++ 17 Standard (11.6.1 Aggregates)

12 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.

std::array is defined as an aggregate that contains another aggregate.

Here is a demonstrative program to make the quote more clear that shows an initialization of a two-dimensional array

#include <iostream>

int main() 
{
    const size_t M = 4, N = 4;
    int a[M][N] =
    {
        { 1, 2, 3, 4 },
        5, 6, 7, 8,
        { 8, 7, 6, 5 },
        4, 3, 2, 1,
    };
    
    return 0;
}

You may imagine the representation of the type std::array<std::array<int, 2>, 4 > as a declaration of the structure B in the following demonstrative porgram.

#include <iostream>

struct A
{
    int a[2];
};

struct B
{
    A b[4];
};

int main() 
{
    B b1 = 
    {
        
    };
    
    B b2 =
    {
        {
        }
    };      

    B b3 =
    {
        {
            {
            }
        }
    };      

    B b4 =
    {
        {
            {
                { {}, {} }
            }
        }
    };      

    return 0;
}

Investigate the program.

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172864

std::array is subtle in aggregate initialization; it expects on more braces for the subobject (underlying array).

std::array<std::array<int, 2>, 4> elements = {{{1,2},{1,2},{1,2},{1,2}}};
//                                           ^                         ^ <- for std::array
//                                            ^                       ^  <- for underlying array

You got the error for the initializer {{1,2},{1,2},{1,2},{1,2}} because there're 4 {1,2}s to initialize the subobject (underlying array) but std::array has only one, i.e. excess elements.

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409136

To initialize an std::array object you need two curly-brace pairs: The outer curly-braces is for the object itself, and the inner is for the array.

That means your initialization needs to look like

std::array<std::array<int, 2>, 4> elements = {{{1,2},{1,2},{1,2},{1,2}}};

Upvotes: 2

Related Questions