Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treat C cstyle array as std::array

Tags:

c++

Is there any safe and standard compliant way to treat a C style array as an std::array without copying the data into a new std::array?

This clearly doesn't compile, but is the effect I would like (my real use is more complicated but this short sample should show what I'd like to do). I guess a reinterpret_cast would "work" but probably isn't safe?

#include <array>

int main()
{
    int data[] = {1, 2, 3, 4, 5};

    // This next line is the important one, treating an existing array as a std::array
    std::array<int, 5>& a = data;
}

It feels like it ought to be possible as the data should be stored identically.

edit: To be clear I don't want to clear a new std::array, I want to refer to the existing data as one.

like image 330
jcoder Avatar asked Jun 26 '12 10:06

jcoder


3 Answers

As discussed in this post Is std::array<T, S> guaranteed to be POD if T is POD?

std::array<int, N> is POD and thus standard layout. As far as I understand the standard layout requirements, this means that the pointer to the object is identical to the pointer to the first member. Since std::array has no private/ protected members (according to http://en.cppreference.com/w/cpp/container/array), this should agree with the first element in the wrapped array. Thus something like

reinterpret_cast< std::array<int, 5>* >( &data )

is in my opinion guaranteed to work by the standard. I have to admit, though, that I sometimes have difficulties interpreting the standard language, so please correct me if I am wrong.

Regards Claas

like image 196
Claas Avatar answered Sep 21 '22 21:09

Claas


You cannot do that. The std::array is an aggregate and holds its own block of data (as opposed to a pointer to a block of data that can be easily reassigned). So there's no way of avoiding a copy of all the elements. In C++11 this is particularly important because the array's data cannot be moved, so there's no efficient std::swap function, for example.

like image 35
juanchopanza Avatar answered Sep 20 '22 21:09

juanchopanza


You can use reinterpret_cast, however note that it's an ugly dirty hack and you should not do something like this in your real release code:

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data);

The problems might arise if the internal implementation of std::array changes (e.g. some additional fields will be added in the debug version of STL to do some runtime checks). Then this code will start crashing without any informative messages (as it's based on an implicit assumption that std::array object and a C array have the same memory layout).

If you decide to go for the ugly dirty hack nonetheless, at least add a compile-time size check:

    C_ASSERT(sizeof(a) == sizeof(data));

This will produce an error in case the size of std::array<> stops matching the size of your C array (due to some changes in the STL implementation).

like image 42
Ivan Shcherbakov Avatar answered Sep 19 '22 21:09

Ivan Shcherbakov