6

经过一番调查,我发现 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 在内存方面获得正确排序的元组?

4

2 回答 2

8

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

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

于 2011-03-05T21:34:10.253 回答
6

为什么你关心元组的实现是什么?编程到接口,而不是实现

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

于 2011-03-05T21:18:35.180 回答