std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
-std=c++17
– Oriflamme-std=c++17
– Oriflammeg++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Monkhood