Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++0x Tuples Store Elements Backwards

After a bit of investigation, I found that C++0x stores the elements in a tuple backwards in memory.

For example, take this code:

std::tuple<char, char, char> x('\0', 'b', 'a');
char* y = (char*)&x;
std::cout << sizeof(x) << std::endl;
std::cout << y << std::endl;

When compiled with the GCC 4.5.2, I get the following output:

3
ab

This initially puzzled me. Why is the data stored backwards? After hunting through GNU's unintentionally obfuscated headers, I noticed that the implementation was similar to this:

template<typename head, typename... tail> class tuple<head, tail...> : public tuple<tail...>
{
  head value;
  ...
};

Because the base class contains the last element, then the next derived class contains the second to last, etc., the actual order of the template arguments is reversed.

When I first got into tuples, I thought that I could use them for a function like glInterleavedArrays(), which sets an array of vertex data as tuples of colors, texture coordinates, normals, and points. Of course, if I make an array of tuples, this data will have to be inputted in reverse, which can result in really weird bugs if you happen to forget to put the arguments in the right order.

What about something like this, then?

template<typename... head, typename tail> class tuple<head..., tail> : public tuple<head...>
{
  tail value;
  ...
};

Under the GCC 4.5.2:

error: parameter pack argument ‘head ...’ must be at the end of the template argument list

Unless this becomes available in the future, I'm pretty much stuck on finding another way to implement this. Is there another way? Some way to trick the GCC into getting a properly-ordered tuple memory-wise?

like image 212
RétroX Avatar asked Mar 05 '11 21:03

RétroX


2 Answers

The tuple layout that you are exploring is an unspecified implementation detail of tuple. Other implementations will have other layouts. If you write to this one, depending on gcc's layout, your code may not be portable to other std::libs.

The libc++ tuple implementation (for example) has the opposite (in-order) layout.

like image 83
Howard Hinnant Avatar answered Sep 21 '22 00:09

Howard Hinnant


Why do you care what the implementation of tuple is? Program to an interface, not an implementation.

If you only use tuple via its advertised interface, then you will get your objects out in the same order you put them in. If you instead break encapsulation by accessing its contents directly, for example by the dodgy pointer cast in your example, then all bets are off.

like image 25
Philip Potter Avatar answered Sep 19 '22 00:09

Philip Potter