Check if class is derived from a specific class (compile, runtime both answers available)

c++, c++11, class, encapsulation

Solution

I have some remarks on the proposed compile-time x runtime solutions. In addition to when they are evaluated, `is_base_of` and `dynamic_cast` have different requirements and their answers can be different.

(1) First of all (as pointed out by others) to use `dynamic_cast`, base and derived classes must be polymorphic (must have at least one `virtual` method). `is_base_of` doesn't require the types to be polymorphic.

(2) The operands of `is_base_of` are both types whereas `dynamic_cast` needs a type (inside `< >`) and an object (inside `( )`).

(3) `dynamic_cast` and `is_base_of` can give different answers (or one can compile while the other doesn't) depending on the type of inheritance (`public` vs `protected` or `private`). For instance consider:

struct B { virtual ~B() {} }; // polymorphic, so it can be used in a dynamic_cast
struct D1 : public B {};      // polymorphic by (public)  inheritance
struct D2 : private B {};     // polymorphic by (private) inheritance

D1 d1;
D2 d2;

We have

static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");

assert(dynamic_cast<B*>(&d1));
assert(!dynamic_cast<B*>(&d2)); // Notice the negation.

Actually the last line yields a compiler error in GCC (`error: 'B' is an inaccessible base of 'D2'`). VS2010 does compile it (yielding just a warning similar to GCC's error message).

(4) The requirements on the classes being polymorphic can be relaxed through an exception handling trick. Consider:

struct B { };             // not polymorphic
struct D1 : public B {};  // not polymorphic
struct D2 : private B {}; // not polymorphic

D1 d1;
D2 d2;

template <typename B, typename D>
const B* is_unambiguous_public_base_of(const D* obj) {
    try {
        throw obj;
    }
    catch (const B* pb) {
        return pb;
    }
    catch (...) {
    }
    return nullptr;
}

Then we have

static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");

assert((is_unambiguous_public_base_of<B>(&d1)));
assert(!(is_unambiguous_public_base_of<B>(&d2))); // Notice the negation.

It's worth mentionning that `is_unambiguous_public_base_of` is far slower than `dynamic_cast` and (this became more obvious after the renaming mentioned in the update below) always returns a `nullptr` for downcasts:

B* b1 = &d1;
assert(dynamic_cast<D1*>(b1));        // Requires D1 and B to be polymorphic.
assert(!(is_unambiguous_public_base_of<D1>(b1))); // Notice the negation.

A bit outdated reference on this trick is available in the following links:

Part 1, Part 2 and code

Disclaimer: the implementation of `is_unambiguous_public_base_of` above is just a draft to make the point and it doesn't handle `const` and `volatile` qualifications properly.

Update: In a previous version of this post `is_unambiguous_public_base_of` was named `my_dynamic_cast` and this was a source of confusion. So I renamed it to a more meaningful name. (Thanks to Jan Herrmann.)

Problem

It is easier to explain on an example so, ``` class base { //.... } class derived1 : public base { //... } ``` In my library, there is a pointer of base class. The user of the library have to make classes derived from either base or derived1 and assign pointer to that class. How can I check what class is user-defined class derived from?

Original source

Related problems