What's the canonical way to get the reference to std::array
's underlying raw (C) array?
The data()
method returns just a raw pointer, which makes it unsuitable e.g. for passing into functions which accept a reference to a raw array of a known size.
Also, is there a good reason why data()
returns a raw pointer, and not a reference to the underlying raw array, or is this just an oversight?
AFAIK, There's no direct or typesafe way to do it, but one work around if you need to pass to a function (with a signature you cannot change to
std::array
) is by usingreinterpret_cast
like this:If you wanted to make it safer:
Why not passing
std::array.begin()
? Worked in SDL2 on:My line to be drawed:
I passed like this:
There is no way of getting the underlying C array.
It's backwards: there is no good reason for the
std::array
to provide the underlying C array. As you already said, the C array would be useful (over the raw pointer) only with functions getting a reference to C arrays.When was the last time you had a function:
Me? Never. I never saw a function with a C array reference parameter with the exception of getting the size of array (and rejecting pointers):
Let's dive a little into why parameters references to arrays are not used.
For starters, from the C area pointer with a separate size parameter was the only way to pass arrays around, due to array-to-pointer decay and lack of reference type.
In C++ there are alternatives to C arrays, like
std::vector
andstd::array
. But even when you have a (legacy) C array you have 2 situations:First of all a begin + end iterators is generic, it accepts any kind of containers. But is not uncommon to see reference to
std::vector
when you want to avoid templates, so why not reference to C array if you have one? Because of a big drawback: you have to know the size of the array:which is extremely limiting.
To get around this you need to make it a template:
which beats the purpose of avoiding templates, so you better go with begin + end template iterators instead.
One of the beauties of (C and) C++ is the enormous scope of applicability. So yes, you will always find some fields that use or need a certain unique feature in an unique way. That being said, even in your example I would still shy away from arrays. When you have a fixed number of values that shouldn't be semantically separated I think a structure would be the correct choice over arrays most of the time (e.g.
glm::mat4
instead offloat[4]
).But let's not forget what
std::array
is: a modern replacement for C arrays. One thing I learned when analyzing options is that there is no absolute "better than". There is always a "depends". But not in this case:std::array
should unquestionably replace C arrays in interfaces. So in the rare case where a fixed size container is needed as a reference parameter it doesn't make sense to enable encouraging the use of C arrays when you already have anstd::array
. So the only valid case where exposing the underlying C array ofstd::array
is need is for some old libraries that have C array reference parameters. But I think that in the bigger picture adding this to the interface it is not justified. New code should use a struct (btwstd::tuple
is getting easier and easier to use by each standard) orstd::array
.There isn't one.
I can see why it would be useful, especially when working with legacy code, but since a couple of decades ago we're supposed to be moving away from code like that and towards iterator-aware algorithms. And when working with C code you'd have to use a pointer anyway. I presume these are factors in the decision not to provide this functionality.
Rewrite your code to accept
std::array<T, N>&
instead, if possible.