That is because std::array is an aggregate and therefore aggregate initialization is performed this is covered in the draft C++11 standard section 8.5.4
[dcl.init.list] which says:
List-initialization of an object or reference of type T is defined as follows:
If the initializer list has no elements and T is a class type with a default constructor, the object is
value-initialized.
Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).
double ad[] = { 1, 2.0 }; // OK
int ai[] = { 1, 2.0 }; // error: narrowing
struct S2 {
int m1;
double m2, m3;
};
S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0
and we can see if it is not an aggregate then the list goes on and says:
- Otherwise, if T is a specialization of std::initializer_list, an initializer_list object is
constructed as described below and used to initialize the object according to the rules for initialization
of an object from a class of the same type (8.5).
- Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated
and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see
below) is required to convert any of the arguments, the program is ill-formed.
We can confirm std::array
is an aggregate from section 23.3.2.1
[array.overview]:
An array is an aggregate (8.5.1) that can be initialized with the
syntax
array<T, N> a = { initializer-list };
where initializer-list is a comma-separated list of up to N elements
whose types are convertible to T.
section 8.5.1
referenced is 8.5.1
Aggregates [dcl.init.aggr] and says:
When an aggregate is initialized by an initializer list, as specified
in 8.5.4, the elements of the initializer list are taken as
initializers for the members of the aggregate, in increasing subscript
or member order [...]
and we come full-circle back to section 8.5.4
which is where we started.