C++0x Tuples Store Elements Backwards
经过一番调查后,我发现C++0x在内存中将元组中的元素存储在后台。
例如,采用以下代码:
1 2 3 4 | std::tuple<char, char, char> x('\0', 'b 'a'); char* y = (char*)&x; std::cout << sizeof(x) << std::endl; std::cout << y << std::endl; |
当使用GCC4.5.2编译时,我得到以下输出:
1 2 | 3 ab |
这起初让我困惑。为什么数据是向后存储的?在浏览了GNU无意中混淆的头部之后,我注意到实现与此类似:
1 2 3 4 5 | template<typename head, typename... tail> class tuple<head, tail...> : public tuple<tail...> { head value; ... }; |
因为基类包含最后一个元素,那么下一个派生类包含从第二个到最后一个的元素,等等,所以模板参数的实际顺序是相反的。
当我第一次进入元组时,我认为我可以将它们用于像
那么像这样的东西呢?
1 2 3 4 5 | template<typename... head, typename tail> class tuple<head..., tail> : public tuple<head...> { tail value; ... }; |
根据GCC 4.5.2:
1 | error: parameter pack argument ‘head ...’ must be at the end of the template argument list |
除非这在将来可用,否则我会一直在寻找另一种方法来实现它。还有别的办法吗?有什么方法可以欺骗gcc获得一个正确排序的元组内存?
您正在探索的tuple布局是tuple的未指定实现细节。其他实现将具有其他布局。如果您写这个代码,根据GCC的布局,您的代码可能无法移植到其他std::libs。
libc++元组实现(例如)的布局与之相反(按顺序)。
为什么您关心tuple的实现是什么?程序到接口,而不是实现。
如果您只通过其公布的接口使用tuple,那么您将按照放入它们的相同顺序取出对象。如果您改为通过直接访问封装的内容来破坏封装,例如通过示例中的Dodgy指针来破坏封装,那么所有的赌注都是关闭的。