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