Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Extra" pair of braces sometimes required when brace-initializing std::array

64 views
Skip to first unread message

K. Frank

unread,
Sep 4, 2017, 7:43:01 PM9/4/17
to
Hello Group!

The following code illustrates my question:

=== entire compilation unit ===

#include <array>
#include <vector>

std::vector<unsigned> vu0 { 1, 2, 3 };
std::vector<unsigned> vu1 { 4, 5 };

std::array<unsigned, 2> au { 1, 2 };
std::array<std::vector<unsigned>, 2> avux { vu0, vu1 };
std::array<std::vector<unsigned>, 2> avuy {{ { 1, 2, 3 }, { 4, 5 } }};

std::array<std::vector<unsigned>, 2> avuz { { 1, 2, 3 }, { 4, 5 } };

=== end ===

Everything compiles except for the last line -- the definition
and initialization of avuz.

That is, when initializing the elements of std::array with
numeric literals or already-defined variables, only a single
pair of braces is needed. But when initializing the array
elements with their own brace initializers, as in the avuy
line, an "extra' pair of braces is needed.

That is, the avuz line without the "extra" braces (line 18)
fails, giving (with g++ 4.9.2) the following error:

g++ -std=c++11 -c av_init.cpp
av_init.cpp:18:67: error: too many initializers for 'std::__array_traits<std::vector<unsigned int>, 2ull>::_Type {aka std::vector<unsigned int> [2]}'
std::array<std::vector<unsigned>, 2> avuz { { 1, 2, 3 }, { 4, 5 } };
^
av_init.cpp:18:67: error: too many initializers for 'std::array<std::vector<unsigned int>, 2ull>'
av_init.cpp:18:67: error: could not convert '1' from 'int' to 'std::vector<unsigned int>'
av_init.cpp:18:67: error: could not convert '2' from 'int' to 'std::vector<unsigned int>'

I have seen in various places the explanation that std::array
is basically just a class with a single member variable that
is a C-style built-in array. Thus, it requires a brace initializer
that contains just a single entry to match its single member
variable. This make sense (even if a bit ugly).

But why then do the initializations of au and avux succeed,
where we have brace initializers with a single pair of braces
so we would appear also to have more initializer values than
the single (array-valued) member variable of the std::array?

Is there some special-case rule in the standard that makes
this work? (And, if so, why doesn't it extend to the case
of the nested brace initializers?)


Thanks for any wisdom.


K. Frank

Ian Collins

unread,
Sep 4, 2017, 11:02:15 PM9/4/17
to
On 09/ 5/17 11:42 AM, K. Frank wrote:
> Hello Group!
>
> The following code illustrates my question:

<big snip>

> g++ -std=c++11 -c av_init.cpp

This was tidied up in C++14, so try -std=c++14.

--
Ian

K. Frank

unread,
Sep 5, 2017, 9:29:54 AM9/5/17
to
Hi Ian!

Thanks for your reply.
The g++ version I currently have installed is too old
to support c++14, so I tried it with a random online
compiler that claims to have a c++14 mode:

https://www.onlinegdb.com/online_c++_compiler

I get the same behavior / error with its c++14.
(Perhaps someone could test my example with both
c++11 and c++14.)

But more to the point, tidied up in c++14 or not, I
would like to understand what's going on -- why you
can get away without the "extra" pair of braces when
you don't have nested brace initializers.

> Ian


Best.


K. Frank

K. Frank

unread,
Sep 11, 2017, 1:19:12 PM9/11/17
to
Hi Group!

Ping?

Why can the outer braces in an std::array brace initializer
be elided when the element initializers are variables, but
not when they are themselves brace initializers?

I tried the code below with another online compiler:

https://www.jdoodle.com/online-compiler-c++14

that explicitly claims c++14 support, and I get the same
result as reported before.

Full details below, but in short:

std::array<std::vector<unsigned>, 2> avux {{ vu0, vu1 }};
-- compiles
std::array<std::vector<unsigned>, 2> avux { vu0, vu1 };
-- compiles with outer braces elided

but

std::array<std::vector<unsigned>, 2> avuy {{ { 1, 2, 3 }, { 4, 5 } }};
-- compiles
std::array<std::vector<unsigned>, 2> avuz { { 1, 2, 3 }, { 4, 5 } };
-- does not compile with outer braces elided

Explained by the language? Bug in g++?


Thanks.


K. Frank
0 new messages