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

How toi get array reference from std::array

50 views
Skip to first unread message

Marcel Mueller

unread,
Feb 7, 2019, 11:46:53 AM2/7/19
to
If I have a array variable

std::array<int,5> data;

and a function taking an array reference

void foo(int (&arr)[5]);

how to pass the content of data to this function without a hard cast?

All the methods of std::array return only raw pointers without the
required size in the type.


OK, I can write a template helper function to do a safe conversion from
std::array<T,N>& to T(&)[N]. But this can no longer be constexpr because
of the cast.

Why does std::array<T,N>::data not return T(&)[N] which implicitly
converts to T* if the length information is not needed? The internal
storage is of type T[N] anyway.


Marcel

Öö Tiib

unread,
Feb 8, 2019, 3:51:11 AM2/8/19
to
On Thursday, 7 February 2019 18:46:53 UTC+2, Marcel Mueller wrote:
> If I have a array variable
>
> std::array<int,5> data;
>
> and a function taking an array reference
>
> void foo(int (&arr)[5]);
>
> how to pass the content of data to this function without a hard cast?
>
> All the methods of std::array return only raw pointers without the
> required size in the type.
>
>
> OK, I can write a template helper function to do a safe conversion from
> std::array<T,N>& to T(&)[N]. But this can no longer be constexpr because
> of the cast.

Write helper function template that takes reference to
implementation-specific member (like "__elems_" in libcpp)
directly. If you target multiple platforms then choose what
it's name is with preprocessor. That member is required to
exist and to be public by standard.

There are only handful of viable standard library implementations
and these don't rename the member too often so it will take half
an hour to get majority covered. The only corner case is
when you have zero-sized std::arrays (those are allowed to lack
that member) but otherwise it is kind of piece of cake.

> Why does std::array<T,N>::data not return T(&)[N] which implicitly
> converts to T* if the length information is not needed? The internal
> storage is of type T[N] anyway.

It is issue 930 with status "not a defect".
https://cplusplus.github.io/LWG/issue930
So it won't change anytime soon and therefore I would go with what
I suggested above.

James Kuyper

unread,
Feb 8, 2019, 8:00:02 AM2/8/19
to
On 2/8/19 03:51, Öö Tiib wrote:
> On Thursday, 7 February 2019 18:46:53 UTC+2, Marcel Mueller wrote:
>> If I have a array variable
>>
>> std::array<int,5> data;
>>
>> and a function taking an array reference
>>
>> void foo(int (&arr)[5]);
>>
>> how to pass the content of data to this function without a hard cast?
>>
>> All the methods of std::array return only raw pointers without the
>> required size in the type.
>>
>>
>> OK, I can write a template helper function to do a safe conversion from
>> std::array<T,N>& to T(&)[N]. But this can no longer be constexpr because
>> of the cast.
>
> Write helper function template that takes reference to
> implementation-specific member (like "__elems_" in libcpp)
> directly. If you target multiple platforms then choose what
> it's name is with preprocessor. That member is required to
> exist and to be public by standard.

Citation, please? 26.3.7.1p3 doesn't list any public data members for
std::array<>, as far as I can see, and neither do any of the general
container requirements (tables 83, 84, 85, 86, and 87).

>> Why does std::array<T,N>::data not return T(&)[N] which implicitly
>> converts to T* if the length information is not needed? The internal
>> storage is of type T[N] anyway.
>
> It is issue 930 with status "not a defect".
> https://cplusplus.github.io/LWG/issue930
> So it won't change anytime soon and therefore I would go with what
> I suggested above.

That issue mentions std::array::elems, which was marked "for exposition
only". "for exposition only" means precisely that - it does NOT mandate
that std::array be implemented in that manner, only that it have the
same observable behavior as if it did so. The identifier "elems" is not
present anywhere in the n4659.pdf, the latest draft version of the C++
standard that I have on my desktop machine, essentially equivalent to
C++2017. Perhaps the committee decided that it was misleading to explain
the behavior of std::array in terms of elems?

Öö Tiib

unread,
Feb 8, 2019, 9:16:54 AM2/8/19
to
On Friday, 8 February 2019 15:00:02 UTC+2, James Kuyper wrote:
> On 2/8/19 03:51, Öö Tiib wrote:
> > On Thursday, 7 February 2019 18:46:53 UTC+2, Marcel Mueller wrote:
> >> If I have a array variable
> >>
> >> std::array<int,5> data;
> >>
> >> and a function taking an array reference
> >>
> >> void foo(int (&arr)[5]);
> >>
> >> how to pass the content of data to this function without a hard cast?
> >>
> >> All the methods of std::array return only raw pointers without the
> >> required size in the type.
> >>
> >>
> >> OK, I can write a template helper function to do a safe conversion from
> >> std::array<T,N>& to T(&)[N]. But this can no longer be constexpr because
> >> of the cast.
> >
> > Write helper function template that takes reference to
> > implementation-specific member (like "__elems_" in libcpp)
> > directly. If you target multiple platforms then choose what
> > it's name is with preprocessor. That member is required to
> > exist and to be public by standard.
>
> Citation, please? 26.3.7.1p3 doesn't list any public data members for
> std::array<>, as far as I can see, and neither do any of the general
> container requirements (tables 83, 84, 85, 86, and 87).

The std::array is required to be aggregate and requirements of
aggregate forbid private or protected non-static data members.
Sure, in theory it may be purely magical thing turned on by
incantation "#include <array>" but such implementations
don't exist.

> >> Why does std::array<T,N>::data not return T(&)[N] which implicitly
> >> converts to T* if the length information is not needed? The internal
> >> storage is of type T[N] anyway.
> >
> > It is issue 930 with status "not a defect".
> > https://cplusplus.github.io/LWG/issue930
> > So it won't change anytime soon and therefore I would go with what
> > I suggested above.
>
> That issue mentions std::array::elems, which was marked "for exposition
> only". "for exposition only" means precisely that - it does NOT mandate
> that std::array be implemented in that manner, only that it have the
> same observable behavior as if it did so. The identifier "elems" is not
> present anywhere in the n4659.pdf, the latest draft version of the C++
> standard that I have on my desktop machine, essentially equivalent to
> C++2017. Perhaps the committee decided that it was misleading to explain
> the behavior of std::array in terms of elems?

Yes, the name of that member is nowhere required but we can aggregate-
initialize it so only thing to do is to look what it's name is up from library
code.


Marcel Mueller

unread,
Feb 8, 2019, 11:25:30 AM2/8/19
to
Am 08.02.19 um 09:51 schrieb Öö Tiib:
>> OK, I can write a template helper function to do a safe conversion from
>> std::array<T,N>& to T(&)[N]. But this can no longer be constexpr because
>> of the cast.
>
> Write helper function template that takes reference to
> implementation-specific member (like "__elems_" in libcpp)
> directly. If you target multiple platforms then choose what
> it's name is with preprocessor. That member is required to
> exist and to be public by standard.
>
> There are only handful of viable standard library implementations
> and these don't rename the member too often so it will take half
> an hour to get majority covered. The only corner case is
> when you have zero-sized std::arrays (those are allowed to lack
> that member) but otherwise it is kind of piece of cake.

Hmm, not that pretty. Especially for open source software which may be
compiled on quite different platforms, at least ones that I cannot test.

For now I don't rely on constexpr, so I can live with the cast.


Marcel

Öö Tiib

unread,
Feb 11, 2019, 2:47:57 AM2/11/19
to
Most open source libraries go for such solutions quite frequently. The
platform vendors *love* to be as incompatible as possible and that
won't change.
0 new messages