【问题标题】:C++0x Tuples Store Elements BackwardsC++0x 元组向后存储元素
【发布时间】:2011-03-05 21:06:46
【问题描述】:

经过一番调查,我发现 C++0x 将元素向后存储在内存中的元组中。

以这段代码为例:

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

使用 GCC 4.5.2 编译时,我得到以下输出:

3
ab

这最初让我感到困惑。为什么数据是向后存储的?在搜索了 GNU 无意中混淆的标头后,我注意到实现类似于:

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

由于基类包含最后一个元素,那么下一个派生类包含倒数第二个等,模板参数的实际顺序是相反的。

当我第一次接触元组时,我认为我可以将它们用于像glInterleavedArrays() 这样的函数,它将顶点数据数组设置为颜色、纹理坐标、法线和点的元组。当然,如果我创建一个元组数组,这些数据将不得不反向输入,如果您碰巧忘记将参数按正确的顺序放置,这可能会导致非常奇怪的错误。

那么这样的事情呢?

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

在 GCC 4.5.2 下:

错误:参数包参数‘head ...’必须在模板参数列表的末尾

除非将来可以使用此功能,否则我几乎无法找到另一种实现此功能的方法。还有其他方法吗?有什么方法可以诱使 GCC 在内存方面获得正确排序的元组?

【问题讨论】:

    标签: c++ c++11 memory tuples stdtuple


    【解决方案1】:

    您正在探索的元组布局是元组的未指定实现细节。其他实现将有其他布局。如果你写这个,根据 gcc 的布局,你的代码可能无法移植到其他 std::libs。

    libc++ 元组实现(例如)具有相反的(按顺序)布局。

    【讨论】:

      【解决方案2】:

      你为什么关心元组的实现是什么? Program to an interface, not an implementation.

      如果您仅通过其广告接口使用元组,那么您将按照放入对象的相同顺序取出对象。如果您通过直接访问其内容来破坏封装,例如通过示例中的狡猾指针转换,那么所有的赌注都取消了。

      【讨论】:

      • 我已经说明了原因 - glInterleavedArrays() 是一个请求交错数据数组的函数。我的意图是创建一个元组类,该类将根据这一原则进行操作——将数据交错到一个元组数组中,以便我可以将数据传递给 GL。如果您想了解更多信息,请参阅 OpenGL 文档:opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml
      • @RetroX:那么你需要一个对象,它的接口提供了一种以已知顺序进行序列化的方法,而不是依赖于元组的实现。无论哪种方式,您都希望接口提供保证,这样您就不会被实现细节所束缚。
      • @PhilipPotter: std::array 如果类型是同质的,这里是明显的候选者,因为它与std::tuple 具有相同的基本特征(大小在编译时固定,基本上为零开销),并隐式保证值按顺序存储(因为data 返回一个原始指针,并保证范围[data(); data() + size()) 是有效范围,并且对于非空数组,指针是第一个元素的地址) .如果做不到这一点,您将使用一个简单的 POD 结构(它可以让您在大多数编译器中根据需要设置打包)。
      猜你喜欢
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      相关资源
      最近更新 更多