指向成员,类型描述符和引用

时间:2011-12-03 17:13:57

标签: c++ pointer-to-member typedescriptor offsetof

我正在使用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。除了我的其他可怕的建议之外,还有关于我接下来可以尝试的任何建议吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

根据标准,

  
      
  1.      

    6 ...   一个简单的类是一个具有普通默认构造函数(12.1)和...的类。   ...

         

    10 POD结构是一个既简单的类又...   ...

  2.         

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

应明确界定其行为。