如何在编译时获取类中的成员数

时间:2016-03-06 21:24:36

标签: c++ c++11

我经常遇到必须实现自定义复制/移动构造函数的情况。但是一段时间之后,会发生类使用新成员进行扩展,并且不会更新此自定义复制/移动构造函数,因此我正在寻找一种方法来防止编译代码而不更新这些方法。

标题代码:

class MyClass
   {
   public:
       MyClass(const MyClass &rhs);
       // ...
   private:
       std::string                 _s;
       std::unique_ptr<OtherClass> _owned;
       bool                        _b;
   };

Cpp代码:

MyClass::MyClass(const MyClass &rhs)
    : _s(rhs._s)
    , _b(rhs._b)
    {
    if (rhs._owned)
       _owned = rhs._owned->clone();
    }

所以,如果我向MyClass添加一些成员,例如:std::size_t _size;,而不是我想要复制构造函数的编译错误。

我目前的解决方案是添加:

static_assert(sizeof(MyClass) == 32, "...");

在此复制构造函数的实现附近。所有这一切都很好,不幸的是,只有当班级的规模增加时,这才有效。因此,如果我不幸地添加bool _b2;所有编译。

因此,我想检查成员数量,而不是检查大小。不幸的是我还没有找到这个。有什么建议吗?

我已经考虑过了:

  • 禁止bool支持short,但它打破了所有意图。
  • 用bitset替换bool,但不同的值不能有不同的名称
  • 将所有默认可复制成员放在单独的结构中,这会引入复杂性
  • 将包含成员数量的static const auto添加到班级,希望在添加成员时更新

然而,所有这些想法都需要更改代码/指南,所以理想情况下我只想写static_assert(number_of_members<MyClass>::value == 3, "...");,任何想法?

2 个答案:

答案 0 :(得分:6)

Rule of Zero

  

具有自定义析构函数,复制/移动构造函数或复制/移动赋值运算符的类应专门处理所有权(遵循单一责任原则)。其他类不应该有自定义析构函数,复制/移动构造函数或复制/移动赋值运算符。

在这种情况下,如果您只是:

template <class T>
struct clone_unique_ptr {
    std::unique_ptr<T> p;

    clone_unique_ptr(const clone_unique_ptr& rhs)
    : p(rhs.p ? rhs.p->clone() : nullptr)
    { }

    // rest of special members
};

然后你不必写任何特别的东西:

class MyClass
{
public:
    MyClass(const MyClass&) = default;
private:
   std::string                  _s;
   clone_unique_ptr<OtherClass> _owned;
   bool                         _b;
};

答案 1 :(得分:-1)

C ++没有内置reflection。但是,您可以尝试使用外部库xCppRefl,它应该提供反射(以前从未使用它并且它已经很老了所以如果使用该库请告诉我适合你)。

如果你这样做,可以单步执行来源

std::vector<DataMember> dataMembers = className.getDataMembers();

然后运行assert(dataMembers.size() == expectedNumMembers)您应该能够测试一个班级中的成员数量是否符合您的预期。