【发布时间】:2016-06-28 07:57:47
【问题描述】:
我正在研究针对std::function-like 对象的小缓冲区优化。
Boost 像这样为boost::function 实现小缓冲区:
union function_buffer
{
mutable void* obj_ptr;
struct type_t {
const detail::sp_typeinfo* type;
bool const_qualified;
bool volatile_qualified;
} type;
mutable void (*func_ptr)();
struct bound_memfunc_ptr_t {
void (X::*memfunc_ptr)(int);
void* obj_ptr;
} bound_memfunc_ptr;
struct obj_ref_t {
mutable void* obj_ptr;
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;
// To relax aliasing constraints
mutable char data;
};
并且做如下事情:
new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);
此外,C++11 提供了std::aligned_union 和std::aligned_storage which seems suitable for this。前者给出了一个类型:
适合用作任何对象的未初始化存储 size 最多为
Len,其对齐方式是Align的除数
我很想使用类似的东西:
class MyFunction {
private:
typename std::aligned_storage<something>::type buffer;
MyFunctionVtable* vtable;
public:
template<class F>
MyFunction(F f)
{
static_assert(sizeof(F) <= sizeof(buffer) &&
alignof(F) <= alignof(buffer), "Type not suitable");
new (&buffer) F(std::move(f));
vtable = ...;
}
// [...]
};
这(或 boost 实现)不会破坏类型别名规则,为什么?我倾向于认为存在会引发不自信行为的陷阱。
作为参考,C++ 标准中的注释给出了aligned_storage 的典型实现:
template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
typedef struct {
alignas(Alignment) unsigned char __data[Len];
} type;
};
在感觉上类似于 boost 版本,两者都依赖 char 来“启用”别名。
std::aligned_union<>::type 呢?使用未明确列出的类型是否安全?
【问题讨论】:
-
char*和void*可以别名为其他类型而无需调用任何类型的 UB。你正在做的有点类似于libstd++为std::function实现的SBO。所以,两者似乎都是安全的(我更愿意将void*传递给placement new)。
标签: c++ strict-aliasing