Humam Helfawi Humam Helfawi - 1 month ago 11
C++ Question

Why std::array does not contain an initializer-list constructor

In order to initialize a

std::array
with some values, you need to use this approach:

std::array<int,3> an_array{{3,4,5}};


I am aware of the reason that we need two curly braces (one for
std::array
and the the other for the inner
c-style array
).

My question: Why, by standard,
std::array
does not contain an initializer-list constructor that directly initialize the inner
c-style array
? Is not more eyes-friendly to be initialized as:

std::array<int,3> an_array{3,4,5};


Edit:

This information is from http://en.cppreference.com/w/cpp/container/array. I thought my compiler is allowing the second version directly as non-standard extension. Now, I am not even sure what is the standard exactly about this case.


// construction uses aggregate initialization

std::array<int, 3> a1{ {1, 2, 3} };
// double-braces required in C++11 (not in C++14)

Answer

The standard defines std::array as follows (N3337 for C++11, but the quoted parts are identical in N4140):

§23.3.2.1 [array.overview]/2

An array is an aggregate that can be initialized with the syntax

array<T, N> a = { initializer-list };

and an aggregate is defined as:

§8.5.1 [dcl.init.aggr]/1

An aggregate is an array or a class with no user-provided constructors, no private or protected non-static data members, no base classes, and no virtual functions.

So it cannot have a user-defined constructor, which an initializer_list one would be.


Additionally, C++11 defines brace elision only for the T x = { a } syntax:

§8.5.1 [dcl.init.aggr]/11

In a declaration of the form

T x = { a };

braces can be elided in an initializer-list as follows. [...]

whereas C++14 (N4140) lifts this requirement:

§8.5.1 [dcl.init.aggr]/11

Braces can be elided in an initializer-list as follows. [...]

So the following is perfectly valid C++14 and above:

std::array<int,3> an_array{3,4,5}