我正在使用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
怎么样?由于int
和float
是不同的类型,该序列是否可以重新排序?答案 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