使用aligned_storage时如何避免严格的别名错误

时间:2013-10-07 04:59:22

标签: c++ c++11 strict-aliasing

我正在使用std::aligned_storage作为变体模板的后备存储。问题是,一旦我在gcc上启用-O2,我就会开始收到“取消引用类型 - 惩罚指针将会打破严格别名”的警告。

真实模板要复杂得多(在运行时检查类型),但生成警告的最小示例是:

struct foo
{
  std::aligned_storage<1024> data;

  // ... set() uses placement new, stores type information etc ...

  template <class T>
  T& get()
  {
    return reinterpret_cast<T&>(data); // warning: breaks strict aliasing rules
  }
};

我很确定boost::variant与此基本上是一样的,但我似乎无法找到他们如何避免这个问题。

我的问题是:

  • 如果以这种方式使用aligned_storage违反严格别名,我应该如何使用它?
  • 假设在函数中没有其他基于指针的操作,get()中是否存在严格别名问题?
    • 内联get()怎么办?
    • get() = 4; get() = 3.2怎么样?由于intfloat是不同的类型,该序列是否可以重新排序?

1 个答案:

答案 0 :(得分:5)

std::aligned_storage<type_traits>的一部分;与该头文件的大多数其他居民一样,它只是某些typedef的持有者,并不打算用作数据类型。它的工作是采用尺寸和对齐方式,并使你成为具有这些特征的POD类型。

您无法直接使用std::aligned_storage<Len, Align>。您必须使用转换类型std::aligned_storage<Len, Align>::type,这是一种POD类型,适合用作任何大小最多为Len的对象的未初始化存储,其对齐方式为{{1}的除数}“。 (Align默认为大于或等于Align的最大有用对齐。)

正如C ++标准所指出的那样,Len返回的类型通常是std::aligned_storage的数组(具有指定大小)和对齐说明符。这避免了“无严格别名”规则,因为字符类型可以为任何其他类型添加别名。

所以你可以这样做:

unsigned char