我正在使用C ++ 11中的类型描述符项目。类型描述符的工作是知道类中每个成员的类型,它的大小以及它与对象基础的偏移量。我不支持多重继承以及具有虚方法的对象,所以我现在使这个更简单。目标是能够使用描述符序列化和反序列化对象。
请注意,这是一个宠物项目,其中包含可变参数模板,指向成员的指针以及我不熟悉的C ++的其他功能等功能,所以没有必要指向像boost :: archiving这样的东西。 :)
我实际注册成员的方式与boost :: python :: class_的方式非常相似。
ClassDescriptor fooDesc( "Foo" );
fooDesc.addMember( "a", &Foo:: a );
fooDesc.addMember( "b", &Foo:: b );
// (abridged for clarity) :
template< typename ClassType, typename MemberType >
ClassDescriptor& ClassDescriptor::addMember(
const char* name,
MemberType ClassType::* member
)
{
return addMember< MemberType >( name, reinterpret_cast< size_t >( &(((ClassType*)0)->*member)) );
}
不幸的是,C ++的指向成员的功能不能与C ++中的引用一起使用,正如我本周早些时候所了解到的那样:https://stackoverflow.com/a/8336479/1074536,所以我无法使用&amp; Foo: :refToAndInt例如。
至于我如何计算成员的偏移量,我没有使用宏的偏移量,因为我的类并不总是POD。
因为我不能使用指向成员来计算引用的偏移量,所以我想我会尝试:
&(((Foo*)nullptr)->refToAnInt)
但是在另一个堆栈溢出线程中已经指出它,这是未定义的行为,并且很明显在LLVM上它崩溃了。 :(
我想避免做一些事情,比如取前一个成员的偏移,添加它的大小然后以某种方式计算对齐我的下一个成员所需的填充,因为它看起来很乱并且容易出错
所以,我不能同时使用这两个技巧和offsetof只适用于POD。除了我的其他可怕的建议之外,还有关于我接下来可以尝试的任何建议吗?
谢谢!
答案 0 :(得分:0)
根据标准,
- 醇>
类
6 ... 一个简单的类是一个具有普通默认构造函数(12.1)和...的类。 ...
10 POD结构是一个既简单的类又... ...
12.1构造函数
5 ...
A default default constructor for class X is defined as deleted if: ... - any non-static data member with no brace-or-equal-initializer is of
参考类型,
... A default constructor is trivial if it is neither user-provided nor deleted
如果
... - for all the non-static data members of its class that are of class type(or
其中的数组),每个这样的类都有一个普通的默认构造函数。
当然,除非存在大括号或等号初始值,否则任何具有引用成员的类都不能是POD,例如:
class A
{
A &me=*this;
};
如果是这种情况,您可以创建特定的解决方法。
对于
的问题&(((Foo*)nullptr)->refToAnInt)
您可以尝试以下操作:
std::aligned_storage<sizeof(Foo), std::alignment_of<Foo>::value>::type storage;
&((static_cast<Foo *>(static_cast<void *>(&storage)))->refToAnInt);
应明确界定其行为。