0

我正在研究 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 ,所以我不能以 &Foo::refToAndInt 为例。

至于我如何计算成员的偏移量,我没有使用宏的偏移量,因为我的类并不总是 POD。

因此,由于我不能使用指向成员的指针来计算引用的偏移量,所以我想我会尝试:

&(((Foo*)nullptr)->refToAnInt)

但是否已在另一个堆栈溢出线程中指出,这是未定义的行为,显然在 LLVM 上它会崩溃。:(

我想避免做一些事情,比如获取前一个成员的偏移量,添加它的大小,然后以某种方式计算对齐我的下一个成员所需的填充,因为它看起来很混乱并且容易出错

所以,我不能同时使用这两种技巧,并且 offsetof 仅适用于 POD。除了我的其他可怕建议之外,关于我下一步可以尝试什么的任何建议?

谢谢!

4

1 回答 1

0

根据标准,

  1. 课程

    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);

它的行为应该被很好地定义。

于 2011-12-05T04:15:13.423 回答