#include <iostream>
class Base {
public:
template <typename To>
bool isa() const {
return this->match(To::GetID());
}
protected:
typedef size_t ID;
static ID NextID() { static ID id = 0; return id++; }
virtual bool match(ID) const { return false; }
};
class Derived: public Base {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Base::match(id); }
};
class MostDerived: public Derived {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Derived::match(id); }
};
template <typename To, typename From>
To const* dyn_cast(From const* f) {
if (f and f->template isa<To>()) { return static_cast<To const*>(f); }
return 0;
}
template <typename To, typename From>
To* dyn_cast(From* f) { return const_cast<To*>(dyn_cast<To>((From const*)f)); }
int main() {
Derived derived; MostDerived mostDerived;
Base* d = &derived, * md = &mostDerived;
if (dyn_cast<Derived>(d)) { std::cout << "Derived -> Derived: ok\n"; }
else { std::cout << "Derived -> Derived: ko\n"; }
if (dyn_cast<MostDerived>(md)) { std::cout << "MostDerived -> MostDerived : ok\n"; }
else { std::cout << "MostDerived -> MostDerived : ko\n"; }
if (dyn_cast<Derived>(md)) { std::cout << "MostDerived -> Derived : ok\n"; }
else { std::cout << "MostDerived -> Derived : ko\n"; }
if (dyn_cast<MostDerived>(d)) { std::cout << "Derived -> MostDerived: ko\n"; }
else { std::cout << "Derived -> MostDerived: ok\n"; }
}