Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Initializing std::array

Reply
Thread Tools

Initializing std::array

 
 
Juha Nieminen
Guest
Posts: n/a
 
      09-11-2012
How to properly initialize a std::array<std::array<float, 2>, 2> using
an initializer list?
 
Reply With Quote
 
 
 
 
Casey Carter
Guest
Posts: n/a
 
      09-11-2012
On 2012-09-11 11:03, Juha Nieminen wrote:
> How to properly initialize a std::array<std::array<float, 2>, 2> using
> an initializer list?
>


According to the standard (23.3.2.1/2): 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.

In practice, implementations of array<T, N> contain a single data
member: a C-style array of N Ts. The initialization specified above only
works because of rules allowing for elision of some curly braces in
initializers. Some compilers will warn about missing braces.

The fully-braced form of initializer would then be

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

Which, despite being non-standard, is in fact _more_ correct for all
reasonable implementations of std::array. It will also work correctly in
the presence of nesting:

array<array<float, 2>, 2> foo = {{ {{ 1.0, 2.0 }}, {{ 3.0, 4.0 }} }};

 
Reply With Quote
 
 
 
 
Juha Nieminen
Guest
Posts: n/a
 
      09-11-2012
Casey Carter <(E-Mail Removed)> wrote:
> According to the standard (23.3.2.1/2): An array is an aggregate (8.5.1)
> that can be initialized with the syntax
>
> array<T, N> a = { initializer-list };


If that's the case, then neither gcc nor clang implement it properly
because both give a warnings when I try it, rather than just working
as intended.

> The fully-braced form of initializer would then be
>
> array<T, N> a = {{ initializer-list }};
>
> Which, despite being non-standard


So what would be the standard way?
 
Reply With Quote
 
Casey Carter
Guest
Posts: n/a
 
      09-11-2012
On 2012-09-11 11:45, Juha Nieminen wrote:
> Casey Carter <(E-Mail Removed)> wrote:
>> According to the standard (23.3.2.1/2): An array is an aggregate (8.5.1)
>> that can be initialized with the syntax
>>
>> array<T, N> a = { initializer-list };

>
> If that's the case, then neither gcc nor clang implement it properly
> because both give a warnings when I try it, rather than just working
> as intended.
>
>> The fully-braced form of initializer would then be
>>
>> array<T, N> a = {{ initializer-list }};
>>
>> Which, despite being non-standard

>
> So what would be the standard way?


The single-braced version is blessed by the standard, presumably because
it looks like

T a[N] = { initializer-list };

and makes it easy to directly replace "T a[N]" with "array<T, N> a" in
typical code. GCC and clang both implement it correctly, they just
happen to also emit a very annoying diagnostic.

Considering how that initialization style depends on dropping braces,
there's no way it can possibly work in the presence of nested arrays.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      09-12-2012
Casey Carter <(E-Mail Removed)> wrote:
> Considering how that initialization style depends on dropping braces,
> there's no way it can possibly work in the presence of nested arrays.


I think that's the most relevant point relating to my original question.
If I understand correctly, this should work according to the C++ standard:

std::array<std::array<int, 2>, 2> table = { { 1, 2 }, { 3, 4 } };

However, both gcc and clang give an outright error.

Now I wonder why neither has implemented it properly. Initializing an
array from an initializer list is quite a trivial thing to do, requiring
just a few lines of code.

(Although there's one problem with that: std::initializer_list::size()
is defined as const, not constexpr. This ought to mean that it's not
possible to detect at compile time if there are too many elements in
the initializer list, eg. with a static_assert... I suppose the compilers
would have to do some trickery about that.)
 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      09-12-2012
On Tue, 11 Sep 2012 16:45:01 +0000, Juha Nieminen wrote:

>> According to the standard (23.3.2.1/2): An array is an aggregate (8.5.1)
>> that can be initialized with the syntax
>>
>> array<T, N> a = { initializer-list };

>
> If that's the case, then neither gcc nor clang implement it properly
> because both give a warnings when I try it,


The implementation is allowed to emit warnings about anything it likes,
including perfectly valid code.

The standard only requires the implementation to accept the above syntax;
it doesn't require it to do so quietly.

 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      09-12-2012
Nobody <(E-Mail Removed)> wrote:
> On Tue, 11 Sep 2012 16:45:01 +0000, Juha Nieminen wrote:
>
>>> According to the standard (23.3.2.1/2): An array is an aggregate (8.5.1)
>>> that can be initialized with the syntax
>>>
>>> array<T, N> a = { initializer-list };

>>
>> If that's the case, then neither gcc nor clang implement it properly
>> because both give a warnings when I try it,

>
> The implementation is allowed to emit warnings about anything it likes,
> including perfectly valid code.
>
> The standard only requires the implementation to accept the above syntax;
> it doesn't require it to do so quietly.


But as noted, they do not accept things like

std::array<std::array<int, 2>, 2> a = { { 1, 2 }, { 3, 4 } };

even though they should.
 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      09-13-2012
On Wed, 12 Sep 2012 19:43:57 +0000, Juha Nieminen wrote:

> But as noted, they do not accept things like
>
> std::array<std::array<int, 2>, 2> a = { { 1, 2 }, { 3, 4 } };
>
> even though they should.


You can't omit that particular set of braces.

A std::array<T,N> is typically a structure containing a single data
member, an N-element array. On that basis, the initialiser list for a
std::array<T,N> should have the same structure as the initialiser list as
a 1xN C array, i.e.:

std::array<int, 2> a = { { 1, 2 } };

One set of brackets can be omitted, allowing:

std::array<int, 2> a = { 1, 2 };

In the 2D case, the initialiser list for a std::array<std::array<T,N>,M>
should have the same structure as that for a 1xMx1xN C array, i.e.:

// compiles without warning
std::array<std::array<int, 2>, 2> c = { { { { 1, 2 } }, { { 3, 4 } } } };

You can use either of:

// compiles, with warnings
std::array<std::array<int, 2>, 2> d = { { { 1, 2 }, { 3, 4 } } };
std::array<std::array<int, 2>, 2> e = { 1, 2, 3, 4 };

but not:

// does not compile
std::array<std::array<int, 2>, 2> g = { { 1, 2 }, { 3, 4 } };

because that would try to use {1,2} to initialise the first (and only)
data member of the outer array then {3,4} to initialise the second data
member, which doesn't exist.

However, while this implementation is typical, it isn't required. AFAICT,
the standard only requires that the implementation is such that a
one-dimensional array of scalars can be initialised like a C array. E.g.
the implementation could actually have the underlying array nested within
multiple levels of single-element structures.

The rules on brace elision mean that the 1D case can be initialised like a
1D C array, but the initialiser list for a nested array requires braces
which match the implementation.

It isn't possible to specify the syntax for higher dimensions without
either specifying the implementation or changing the base language syntax.

 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      09-13-2012
Nobody <(E-Mail Removed)> wrote:
> It isn't possible to specify the syntax for higher dimensions without
> either specifying the implementation or changing the base language syntax.


But std::vector<std::vector<int>> v = { { 1, 2 }, { 3, 4 } }; works just
fine. What's so different about std::array?
 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      09-13-2012
On Thu, 13 Sep 2012 10:49:20 +0000, Juha Nieminen wrote:

> Nobody <(E-Mail Removed)> wrote:
>> It isn't possible to specify the syntax for higher dimensions without
>> either specifying the implementation or changing the base language syntax.

>
> But std::vector<std::vector<int>> v = { { 1, 2 }, { 3, 4 } }; works just
> fine.


Only for C++11. Previously, you couldn't use any form of initialiser list.

> What's so different about std::array?


std::array doesn't have a constructor, so it can only be initialised by
aggregate initialisation.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Initializing memory from a testbench rickman VHDL 12 08-29-2007 01:25 PM
ATM0 is initializing, line protocol is down Tirenque Cisco 5 03-21-2006 10:31 AM
Cisco VPN client stuck on "Initializing the IPSec link" Sandeep Gupta Cisco 4 02-24-2004 08:23 PM
Initializing offline cache - delay mg ASP .Net 0 12-16-2003 12:53 PM
Error occurred while initializing MAPI in Outlook Express 6 Michael MCSE 5 09-17-2003 05:39 PM



Advertisments