Last active
June 12, 2019 17:39
-
-
Save Leedehai/535a73e19c1cdb2b684279d377d2da52 to your computer and use it in GitHub Desktop.
Play with manual C++ RTTI (inspired by LLVM/Clang)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
using namespace std; // yeah I know it's better to use "ns::foo" instead of declaring "using namespace ns" at the top... | |
// but this file is just a toy, right. Live a little. | |
enum Kind_t { KA, KB, KC, KD }; | |
class A { | |
Kind_t kind; | |
public: | |
A(Kind_t kind = KA) : kind(kind) {} | |
virtual ~A() = default; | |
static bool classof(const A *p) { cout << "A::classof(A*) - "; return true; } | |
virtual Kind_t getID() const { return kind; } | |
}; | |
class B : public A { | |
public: | |
B(Kind_t kind = KB) : A(kind) {} | |
static bool classof(const B *p) { cout << "B::classof(B*) - "; return true; } | |
static bool classof(const A *p) { cout << "B::classof(A*) - "; return p->getID() == KB || p->getID() == KC; } | |
}; | |
class C : public B { | |
public: | |
C(Kind_t kind = KC) : B(kind) {} | |
static bool classof(const C *p) { cout << "C::classof(C*) - "; return true; } | |
static bool classof(const A *p) { cout << "C::classof(A*) - "; return p->getID() == KC; } | |
}; | |
class D : public A { | |
public: | |
D(Kind_t kind = KD) : A(kind) {} | |
static bool classof(const D *p) { cout << "D::classof(D*) - "; return true; } | |
static bool classof(const A *p) { cout << "D::classof(A*) - "; return p->getID() == KD; } | |
}; | |
template <typename To, typename From> | |
bool isa(From * const &p) { cout << "isa(From * const &p) "; return To::classof(p); } | |
template <typename To, typename From> | |
bool isa(const From * const &p) { cout << "isa(const From * const &p) "; return To::classof(p); } | |
template <typename To, typename From> | |
To *dyn_cast(From * const &p) { | |
cout << "dyn_cast(From * const &p) "; | |
return isa<To>(p) ? reinterpret_cast<To *>(p) : nullptr; | |
} | |
template <typename To, typename From> | |
const To *dyn_cast(const From * const &p) { | |
cout << "dyn_cast(const From * const &p) "; | |
return isa<const To>(p) ? reinterpret_cast<const To *>(p) : nullptr; | |
} | |
void testA(); void testB(); | |
int main() { | |
cout << " A <- B <- C\n" | |
<< " <- D\n" << endl; | |
testA(); | |
testB(); | |
} | |
void testA() { | |
cout << "const A *pa = new A, *const pb = new B, *pc = new C, *pd = new D;" << endl; | |
const A *pa = new A, *const pb = new B, *pc = new C, *pd = new D; | |
cout << "\nisa<A>(pa) - true : " << endl; | |
cout << (isa<A>(pa) ? "true" : "false") << "\n" << (dyn_cast<A>(pa) ? 1 : 0) << endl; | |
cout << "\nisa<A>(pb) - true : " << endl; | |
cout << (isa<A>(pb) ? "true" : "false") << "\n" << (dyn_cast<A>(pb) ? 1 : 0) << endl; | |
cout << "\nisa<A>(pc) - true : " << endl; | |
cout << (isa<A>(pc) ? "true" : "false") << "\n" << (dyn_cast<A>(pc) ? 1 : 0) << endl; | |
cout << "\nisa<A>(pd) - true : " << endl; | |
cout << (isa<A>(pd) ? "true" : "false") << "\n" << (dyn_cast<A>(pd) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pa) - false: " << endl; | |
cout << (isa<B>(pa) ? "true" : "false") << "\n" << (dyn_cast<B>(pa) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pb) - true : " << endl; | |
cout << (isa<B>(pb) ? "true" : "false") << "\n" << (dyn_cast<B>(pb) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pc) - true : " << endl; | |
cout << (isa<B>(pc) ? "true" : "false") << "\n" << (dyn_cast<B>(pc) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pd) - false: " << endl; | |
cout << (isa<B>(pd) ? "true" : "false") << "\n" << (dyn_cast<B>(pd) ? 1 : 0) << endl; | |
cout << "\nisa<C>(pd) - false: " << endl; | |
cout << (isa<C>(pd) ? "true" : "false") << "\n" << (dyn_cast<C>(pd) ? 1 : 0) << endl; | |
} | |
void testB() { | |
cout << "B *pb = new B, *const pc = new C; D *pd = new D;" << endl; | |
B *pb = new B, *const pc = new C; D *pd = new D; | |
cout << "\nisa<B>(pb) - true : " << endl; | |
cout << (isa<B>(pb) ? "true" : "false") << "\n" << (dyn_cast<B>(pb) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pc) - true : " << endl; | |
cout << (isa<B>(pc) ? "true" : "false") << "\n" << (dyn_cast<B>(pc) ? 1 : 0) << endl; | |
cout << "\nisa<B>(pd) - false: " << endl; | |
cout << (isa<B>(pd) ? "true" : "false") << "\n" << (dyn_cast<B>(pd) ? 1 : 0) << endl; | |
cout << "\nisa<C>(pd) - false: " << endl; | |
cout << (isa<C>(pd) ? "true" : "false") << "\n" << (dyn_cast<C>(pd) ? 1 : 0) << endl; | |
} | |
/* printout | |
A <- B <- C | |
<- D | |
const A *pa = new A, *const pb = new B, *pc = new C, *pd = new D; | |
isa<A>(pa) - true : | |
isa(const From * const &p) A::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) A::classof(A*) - 1 | |
isa<A>(pb) - true : | |
isa(const From * const &p) A::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) A::classof(A*) - 1 | |
isa<A>(pc) - true : | |
isa(const From * const &p) A::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) A::classof(A*) - 1 | |
isa<A>(pd) - true : | |
isa(const From * const &p) A::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) A::classof(A*) - 1 | |
isa<B>(pa) - false: | |
isa(const From * const &p) B::classof(A*) - false | |
dyn_cast(const From * const &p) isa(const From * const &p) B::classof(A*) - 0 | |
isa<B>(pb) - true : | |
isa(const From * const &p) B::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) B::classof(A*) - 1 | |
isa<B>(pc) - true : | |
isa(const From * const &p) B::classof(A*) - true | |
dyn_cast(const From * const &p) isa(const From * const &p) B::classof(A*) - 1 | |
isa<B>(pd) - false: | |
isa(const From * const &p) B::classof(A*) - false | |
dyn_cast(const From * const &p) isa(const From * const &p) B::classof(A*) - 0 | |
isa<C>(pd) - false: | |
isa(const From * const &p) C::classof(A*) - false | |
dyn_cast(const From * const &p) isa(const From * const &p) C::classof(A*) - 0 | |
B *pb = new B, *const pc = new C; D *pd = new D; | |
isa<B>(pb) - true : | |
isa(From * const &p) B::classof(B*) - true | |
dyn_cast(From * const &p) isa(From * const &p) B::classof(B*) - 1 | |
isa<B>(pc) - true : | |
isa(From * const &p) B::classof(B*) - true | |
dyn_cast(From * const &p) isa(From * const &p) B::classof(B*) - 1 | |
isa<B>(pd) - false: | |
isa(From * const &p) B::classof(A*) - false | |
dyn_cast(From * const &p) isa(From * const &p) B::classof(A*) - 0 | |
isa<C>(pd) - false: | |
isa(From * const &p) C::classof(A*) - false | |
dyn_cast(From * const &p) isa(From * const &p) C::classof(A*) - 0 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment