In the following program, I tried to initialise my 2x2-element std::array
using the line which has nested list initialisation (currently commented out). MSVC2017 gave me a compiler error with "too many initializers". Why?
I then gave the non-nested list initialisation a go which worked. Why?
This appears to be inconsistent with initialisation of a nested std::vector
. See third line of main()
. What is going on here please?
#include <array>
#include <iostream>
#include <vector>
int main()
{
//std::array<std::array<int,2>,2> x = {{0,1},{2,3}}; // ERROR: TOO MANY INITIALIZERS
std::array<std::array<int,2>,2> x = {0,1,2,3}; // OK
std::vector<std::vector<int>> y = {{0,1},{2,3}}; // ALSO OK: NOT TOO MANY INITIALIZERS IF A std::vector?
}
In this declaration
std::array<std::array<int,2>,2> x = {{0,1},{2,3}};
you have three nested aggregates. The first pair of values enclosed in braces
{0,1}
is considered by the compiler as an initializer of the second aggregate that is present in the declaration as one sub-aggregate. So the second pair of values in braces
{2,3}
are considered by the compiler as redundant that has no corresponding object.
You could declare the array for example like
std::array<std::array<int, 2>, 2> x = { { {0,1},{2,3} } };
The braces may be elided when an aggregate is initialized. (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.
So in this declaration
std::array<std::array<int,2>,2> x = {0,1,2,3};
the braces are elided and the aggregate is initialized as it is described in the quote..
In this declaration
std::vector<std::vector<int>> y = {{0,1},{2,3}};
there is used the constructor of the class std::vector that accepts std::initializer_list as an argument. In this case the constructor builds as many elements of the vector as there are elements in the initializer list.