#include #include #include #include using namespace std; class TDirectoryEntryPtrBase { public: virtual ~TDirectoryEntryPtrBase() {} virtual void* GetObjectAddr() const = 0; virtual const std::type_info& GetTypeInfo() const = 0; template U* Cast() const; private: virtual void CastImpl() const = 0; }; template U* TDirectoryEntryPtrBase::Cast() const { try{ CastImpl(); } catch (U* ptr) { return static_cast(ptr); } catch (...) {} return nullptr; } template class TDirectoryEntryPtr: public TDirectoryEntryPtrBase { public: TDirectoryEntryPtr(T* obj): fObj(obj) {} TDirectoryEntryPtr(const shared_ptr& ptr): fObj(ptr) {} void* GetObjectAddr() const final { return fObj.get(); } const std::type_info& GetTypeInfo() const final { return typeid(T); } private: std::shared_ptr fObj; void CastImpl() const final { throw fObj.get(); } }; template string Find(const TDirectoryEntryPtrBase* ptr) { if (ptr->GetTypeInfo() == typeid(T)) return "kValidValue"; if (ptr->Cast()) return "kValidValueBase"; return "kTypeMismatch"; } class U/*nrelated*/ {}; /* non-virtual */ class B {}; class D: public B {}; /* virtual */ class B_v {public: virtual ~B_v() {}}; class D_v: public B_v {}; /* deep hierarchy, non-virtual */ class Top {}; class Mid: public Top {}; class Bot: public Mid {}; /* deep hierarchy, virtual */ class Top_v {public: virtual ~Top_v() {}}; class Mid_v: public Top_v {}; class Bot_v: public Mid_v {}; /* multiple inheritance */ class B1 {}; class B2 {}; class Dm: public B1, public B2 {}; /* virtual base */ class Bv1: public virtual B_v {}; class Bv2: public virtual B_v {}; class Dvm: public Bv1, public Bv2 {}; int main() { TDirectoryEntryPtr d(new D); TDirectoryEntryPtr b(new B); TDirectoryEntryPtr d_v(new D_v); TDirectoryEntryPtr b_v(new B_v); TDirectoryEntryPtr top(new Top); TDirectoryEntryPtr mid(new Mid); TDirectoryEntryPtr bot(new Bot); TDirectoryEntryPtr top_v(new Top_v); TDirectoryEntryPtr mid_v(new Mid_v); TDirectoryEntryPtr bot_v(new Bot_v); TDirectoryEntryPtr b1(new B1); TDirectoryEntryPtr b2(new B2); TDirectoryEntryPtr dm(new Dm); TDirectoryEntryPtr bv1(new Bv1); TDirectoryEntryPtr bv2(new Bv2); TDirectoryEntryPtr dvm(new Dvm); cout << "Non-virtual:\n"; cout << "Find(d) [exact] " << Find(&d) << endl; cout << "Find(d) [upcast] " << Find(&d) << endl; cout << "Find(b) [downcast] " << Find(&b) << endl; cout << "Find(b) [exact] " << Find(&b) << endl; cout << endl; cout << "Virtual:\n"; cout << "Find(d_v) [exact] " << Find(&d_v) << endl; cout << "Find(d_v) [upcast] " << Find(&d_v) << endl; cout << "Find(b_v) [downcast] " << Find(&b_v) << endl; cout << "Find(b_v) [exact] " << Find(&b_v) << endl; cout << endl; cout << "Unrelated class:\n"; cout << "Find(d) " << Find(&d) << endl; cout << "Find(b) " << Find(&b) << endl; cout << "Find(d_v) " << Find(&d_v) << endl; cout << "Find(b_v) " << Find(&b_v) << endl; cout << endl; cout << "Deep hierarchy, non-virtual:\n"; cout << "Find(top) [ 0 cast(s)] " << Find(&top) << endl; cout << "Find(mid) [ 1 cast(s)] " << Find(&mid) << endl; cout << "Find(bot) [ 2 cast(s)] " << Find(&bot) << endl; cout << "Find(top) [-1 cast(s)] " << Find(&top) << endl; cout << "Find(mid) [ 0 cast(s)] " << Find(&mid) << endl; cout << "Find(bot) [ 1 cast(s)] " << Find(&bot) << endl; cout << "Find(top) [-2 cast(s)] " << Find(&top) << endl; cout << "Find(mid) [-1 cast(s)] " << Find(&mid) << endl; cout << "Find(bot) [ 0 cast(s)] " << Find(&bot) << endl; cout << endl; cout << "Deep hierarchy, virtual:\n"; cout << "Find(top_v) [ 0 cast(s)] " << Find(&top_v) << endl; cout << "Find(mid_v) [ 1 cast(s)] " << Find(&mid_v) << endl; cout << "Find(bot_v) [ 2 cast(s)] " << Find(&bot_v) << endl; cout << "Find(top_v) [-1 cast(s)] " << Find(&top_v) << endl; cout << "Find(mid_v) [ 0 cast(s)] " << Find(&mid_v) << endl; cout << "Find(bot_v) [ 1 cast(s)] " << Find(&bot_v) << endl; cout << "Find(top_v) [-2 cast(s)] " << Find(&top_v) << endl; cout << "Find(mid_v) [-1 cast(s)] " << Find(&mid_v) << endl; cout << "Find(bot_v) [ 0 cast(s)] " << Find(&bot_v) << endl; cout << endl; cout << "Multiple inheritance:\n"; cout << "Find(dm) [upcast] " << Find(&dm) << endl; cout << "Find(dm) [upcast] " << Find(&dm) << endl; cout << "Find(b2) [sidecast] " << Find(&b2) << endl; cout << "Find(b1) [sidecast] " << Find(&b1) << endl; cout << endl; cout << "Virtual base:\n"; cout << "FInd(dvm) [virtual base upcast] " << Find(&dvm) << endl; cout << "FInd(bv1) [virtual base upcast] " << Find(&bv1) << endl; cout << "Find(bv2) [virtual base upcast] " << Find(&bv2) << endl; cout << "Find(bv1) [exact] " << Find(&bv1) << endl; cout << "Find(bv2) [exact] " << Find(&bv2) << endl; cout << "Find(dvm) [upcast] " << Find(&dvm) << endl; cout << "Find(dvm) [upcast] " << Find(&dvm) << endl; cout << "Find(bv2) [sidecast] " << Find(&bv2) << endl; cout << "Find(bv1) [sidecast] " << Find(&bv1) << endl; cout << endl; }