6

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

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

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.2int由于类型不同,该序列是否可以重新排序float
4

1 回答 1

5

std::aligned_storage is part of <type_traits>; like most of the rest of the inhabitants of that header file, it is just a holder for some typedefs and is not meant to be used as a datatype. Its job is to take a size and alignment, and make you a POD type with those characteristics.

You cannot use std::aligned_storage<Len, Align> directly. You must use std::aligned_storage<Len, Align>::type, the transformed type, which is "a POD type suitable for for use as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align." (Align defaults to the largest useful alignment greater than or equal to Len.)

As the C++ standard notes, normally the type returned by std::aligned_storage will be an array (of the specified size) of unsigned char with an alignment specifier. That avoids the "no strict aliasing" rule because a character type may alias any other type.

So you might do something like:

template<typename T>
using raw_memory = typename std::aligned_storage<sizeof(T),
                                                 std::alignment_of<T>::value>::type;

template<typename T>
void* allocate() { return static_cast<void*>(new raw_memory<T>); }

template<typename T, typename ...Arg>
T* maker(Arg&&...arg) {
   return new(allocate<T>()) T(std::forward<Arg>(arg)...);
}
于 2013-10-07T05:46:58.083 回答