Google Gruppi non supporta più i nuovi post o le nuove iscrizioni Usenet. I contenuti storici continuano a essere visibili.

array + return + initializer (C++0X) - is this a bug

25 visualizzazioni
Passa al primo messaggio da leggere

Helmut Jarausch

da leggere,
6 apr 2011, 15:40:2306/04/11
a

Hi,

I'm not sure if the following error message identifies a bug
in gcc-4.6 / gcc-4.6-git

#include <array>
using std::array;

/*
In function 'std::array<int, 3ul> RWTH_UTM()':
error: could not convert '{32, 293945, 5629196}' to 'std::array<int, 3ul>'
*/

array<int,3> RWTH_UTM() {
return {32,293945,5629196};
}

array<int,3> Standort {32,293945,5629196}; // OK

Many thanks for clarifying this,
Helmut.

--
Helmut Jarausch
Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Johannes Schaub

da leggere,
7 apr 2011, 04:06:4007/04/11
a
Helmut Jarausch wrote:

>
> Hi,
>
> I'm not sure if the following error message identifies a bug
> in gcc-4.6 / gcc-4.6-git
>
> #include <array>
> using std::array;
>
> /*
> In function 'std::array<int, 3ul> RWTH_UTM()':
> error: could not convert '{32, 293945, 5629196}' to 'std::array<int, 3ul>'
> */
>
> array<int,3> RWTH_UTM() {
> return {32,293945,5629196};
> }
>
> array<int,3> Standort {32,293945,5629196}; // OK
>

No, this is according to the spec, and arguably the second one is invalid
too. You are using brace-elision here: The aggregational structure of
"array<int, 3>" is "{ <array int[3]> }". The array in fully braced syntax
needs its own braces. So you need two braces: One for the struct, and one
for the array. You can elide them only in declarations "of the form T x = {
a };", with an explicit footnote that this elision is not allowed "in other
uses of list-initialization".


--

Daniel Krügler

da leggere,
7 apr 2011, 19:36:3707/04/11
a

On 2011-04-07 10:06, Johannes Schaub wrote:
> Helmut Jarausch wrote:
>
>>
>> Hi,
>>
>> I'm not sure if the following error message identifies a bug
>> in gcc-4.6 / gcc-4.6-git
>>
>> #include<array>
>> using std::array;
>>
>> /*
>> In function 'std::array<int, 3ul> RWTH_UTM()':
>> error: could not convert '{32, 293945, 5629196}' to 'std::array<int, 3ul>'
>> */
>>
>> array<int,3> RWTH_UTM() {
>> return {32,293945,5629196};
>> }
>>
>> array<int,3> Standort {32,293945,5629196}; // OK
>>
>
> No, this is according to the spec, and arguably the second one is invalid
> too. You are using brace-elision here: The aggregational structure of
> "array<int, 3>" is "{<array int[3]> }". The array in fully braced syntax
> needs its own braces. So you need two braces: One for the struct, and one
> for the array. You can elide them only in declarations "of the form T x = {
> a };", with an explicit footnote that this elision is not allowed "in other
> uses of list-initialization".

You make a very good point here, which I did not properly honor in my suggestion for a possible make_array implementation. This restriction has the unfortunate effect, that the initialization of std::array is underspecified especially for the zero-length container. According to [array.overview] p. 2 we have:

"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."

This has the unfortunate consequences, that it does not say anything about other feasible initialization forms, which influences especially the zero-length array case. It is unclear whether

std::array<int, 0> b1{};

is well-formed or whether

std::array<int, 0> b2{{}};

can or must be used instead, which obviously depends on the actual implementation. The latter form would be invalid, if the specialization would be an empty class, the first form would be invalid, if the specialization contains a single element of type T[1]. I will consider this in my next update for make_array, which will use a parenthesized form of value-initialization for the zero-length case.

As a side-aspect of this it is not clear whether a zero-length array of a non-DefaultConstructible type satisfies the DefaultConstructible requirements. Consider:

struct NoDef { NoDef() = delete; };

std::array<NoDef, 0> ad; // OK?

Personally I would appreciate if this initialization would be required to be well-formed. I'm aware that this would invalidate some currently existing implementations of std::array, but IMO a zero-length std::array should be required to be an empty class anyway.

Greetings from Bremen,

- Daniel Kr�gler

Johannes Schaub

da leggere,
8 apr 2011, 08:06:0808/04/11
a

Daniel Krügler wrote:

>
> On 2011-04-07 10:06, Johannes Schaub wrote:
>> Helmut Jarausch wrote:
>>
>>>
>>> Hi,
>>>
>>> I'm not sure if the following error message identifies a bug
>>> in gcc-4.6 / gcc-4.6-git
>>>
>>> #include<array>
>>> using std::array;
>>>
>>> /*
>>> In function 'std::array<int, 3ul> RWTH_UTM()':
>>> error: could not convert '{32, 293945, 5629196}' to 'std::array<int,
>>> 3ul>' */
>>>
>>> array<int,3> RWTH_UTM() {
>>> return {32,293945,5629196};
>>> }
>>>
>>> array<int,3> Standort {32,293945,5629196}; // OK
>>>
>>
>> No, this is according to the spec, and arguably the second one is invalid
>> too. You are using brace-elision here: The aggregational structure of
>> "array<int, 3>" is "{<array int[3]> }". The array in fully braced syntax
>> needs its own braces. So you need two braces: One for the struct, and one
>> for the array. You can elide them only in declarations "of the form T x =
>> { a };", with an explicit footnote that this elision is not allowed "in
>> other uses of list-initialization".
>
> You make a very good point here,

I was just stealing it from other people :)

> This has the unfortunate consequences, that it does not say anything about
> other feasible initialization forms, which influences especially the
> zero-length array case. It is unclear whether
>
> std::array<int, 0> b1{};
>
> is well-formed or whether
>
> std::array<int, 0> b2{{}};
>
> can or must be used instead, which obviously depends on the actual
> implementation. The latter form would be invalid, if the specialization
> would be an empty class, the first form would be invalid, if the
> specialization contains a single element of type T[1].

Why would it be invalid for a specialization that contains a single element
of type T[1] ? The syntax "{}" doesn't elide any brace. It just doesn't
initialize the array member, which means the array member is value
initialized.

In fact, for list-initialization with empty initializer lists of classes
that have a default constructor, we don't enter aggregate initialization at
all: We will do value initialization of the std::array<> object regardless,
instead.

Daniel Krügler

da leggere,
8 apr 2011, 16:42:0708/04/11
a

On 2011-04-08 14:06, Johannes Schaub wrote:

>
> Daniel Krügler wrote:
>
>> This has the unfortunate consequences, that it does not say anything about
>> other feasible initialization forms, which influences especially the
>> zero-length array case. It is unclear whether
>>
>> std::array<int, 0> b1{};
>>
>> is well-formed or whether
>>
>> std::array<int, 0> b2{{}};
>>
>> can or must be used instead, which obviously depends on the actual
>> implementation. The latter form would be invalid, if the specialization
>> would be an empty class, the first form would be invalid, if the
>> specialization contains a single element of type T[1].
>
> Why would it be invalid for a specialization that contains a single element
> of type T[1] ? The syntax "{}" doesn't elide any brace. It just doesn't
> initialize the array member, which means the array member is value
> initialized.

You are right, I think I was simply misguided here, because there is a
way of looking at

std::array<int, 0> b1{}

as the elided form of

std::array<int, 0> b2{{}};

but I agree that this is clearly described in list-initialization and
non-ambigious from the overall text in the standard.

> In fact, for list-initialization with empty initializer lists of classes
> that have a default constructor, we don't enter aggregate initialization at
> all: We will do value initialization of the std::array<> object regardless,
> instead.

You are right, I was plain wrong in regard to this point.

I still think that the zero-length specialization of std::array should
be required to be DefaultConstructible independent from the element
type, because - at least conceptually - there is no real member existing.

Thanks & Greetings from Bremen,

- Daniel Krügler

0 nuovi messaggi