The problem

Consider the following type aliasing:

template<std::size_t N>  
using square_matrix = std::array<  
                        std::array<int, N>, 

Intuitively, one may try to use brace-initialization as follows:

square_matrix<3> m = {  
    {1, 2, 3}, 
    {4, 5, 6}, 
    {7, 8, 9}

Just to find out that the above does not compile. Instead, the correct initiliazation reads:

square_matrix<3> m = {{  
    {1, 2, 3}, 
    {4, 5, 6}, 
    {7, 8, 9}

The rationale

So, what's the reason for the extra inner {...}?

The answer lies in the definition of std::array:

std::array is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member.

Remember that aggregates do not have a user-declared constructor. The only why to initialize an aggregator is to use brace-initialization. That is:

AggregateType a = { // start initializing a  
                    ... // initialize a's members  
                  }; // stop initializing a

The first (and only) data member of std::array is an array of size N, and this member is directly initialized with initializer.

The extra braces are therefore needed for the internal array which is directly being initialized.

The case of 1-dimension arrays

If this is the case, why can we omit the extra braces for 1-dimensional arrays? That is, why can we do the following?

std::array<int, 3> a = {1, 2, 3};  

The reason is in Paragraph of the C++ standard:

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 members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. 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 members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.


N3526 proposed to relax the rules for brace-initialization so as to allow the natural syntax introduced at the beginning. Unfortunately, it has been marked as NAD (not a defect).