有没有办法找出一个班级是否是另一个班级的直接基础?

时间:2010-02-14 17:36:43

标签: c++ templates boost metaprogramming

我想知道是否有办法找出一个类是否是另一个类的直接基础,即在Boost类型特征术语中是is_direct_base_of函数。据我所知,Boost似乎不支持这种功能,这使我认为使用当前的C ++标准是不可能的。

我想要它的原因是对两个用于反射系统的宏进行一些验证检查,以指定一个类是从另一个派生的,如下面的示例代码所示。

header.h:

#define BASE     A
#define DERIVED  B

class A {};
class B : public A 
{
   #include <rtti.h>
};

rtti.h:

// I want to check that the two macro's are correct with a compile time assert
Rtti<BASE, DERIVED> m_rtti;

虽然在这个简单的例子中似乎没有宏,但在我的真实场景中,rtti.h更加复杂。

一种可能的途径是将this指针的大小与转换为基类型的this指针的大小进行比较,并以某种方式试图弄清楚它是否是基类本身的大小或其他东西。 (是的,你是对的,我不知道那是怎么回事!)

1 个答案:

答案 0 :(得分:11)

我问自己,“C ++结构区分直接继承与间接继承有什么区别?”我们想到,派生类型的C ++构造函数只直接调用构造函数来获取它们的直接基数。所以这样的代码:

Derived::Derived() : Base() {}

仅在BaseDerived的直接基础时才有效。并且由于您将rtti.h的代码注入到Derived的主体中,您可以容忍这种技术仅在派生类本身内直接可见的限制(即它不像假设那样通用) type_traits::is_direct_base_of,但不一定是。)

因为我们可能不想乱用默认的构造函数本身,如何添加一些特殊的构造函数呢?

#define BASE     A
#define DERIVED  B

struct rtti_tag {}; // empty type

class A
{
protected:
    A(rtti_tag) { assert(false); } // never actually called
};

#include <rtti.h>
class B : public A
{
    IS_DIRECT_BASE_OF(DERIVED, BASE); // fails to compile if not true
};

rtti.h

#define IS_DIRECT_BASE_OF(_B_, _A_) _B_(rtti_tag tag) : _A_(tag) \
    { assert(false); } // never actually called

这段代码用g ++ 4.2为我编译;如果我在继承层次结构中插入一个新类,断言中断和编译失败,我认为这是一个合理的描述性诊断:

In constructor ‘B::B(rtti_tag)’:
error: type ‘A’ is not a direct base of ‘B’
...