I'm wondering whether there is a way to find out whether a class is a direct base of another class i.e. in Boost type trait terms a is_direct_base_of
function. As far as I can see, Boost doesn't seem to support this kind of functionality, which leads me to think that it's impossible with the current C++ standard.
The reason I want it is to do some validation checking on two macros that are used for a reflection system to specify that one class is derived from another, as in the example code below.
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;
Although the macros seem unnecessary in this simple example, in my real world scenario rtti.h
is a lot more complex.
One possible avenue would be to compare the size of the this pointer with the size of a this pointer cast to the base type and somehow trying to figure out whether it's the size of the base class itself away or something. (Yeah, you're right, I don't know how that would work either!)
I asked myself, "What C++ constructs do differentiate between direct inheritance vs. indirect?" It comes to mind that C++ constructors of derived types directly call constructors for their direct base(s) only. So code like this:
Derived::Derived() : Base() {}
Is only valid if Base
is is a direct base of Derived
. And since you are injecting the code of rtti.h
into the body of Derived
, you can tolerate the restriction that this technique is only directly visible within the derived class itself (i.e. it is not as general as a hypothetical type_traits::is_direct_base_of
, but does not need to be).
So since we probably don't want to mess around with the default constructors per se, how about adding some special-purpose ones?
#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
This code compiles for me with g++ 4.2; if I insert a new class in the inheritance hierarchy, the assertion breaks and compilation fails with what I think is a reasonably descriptive diagnostic:
In constructor ‘B::B(rtti_tag)’:
error: type ‘A’ is not a direct base of ‘B’
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With