Created
October 2, 2016 14:07
-
-
Save Garciat/3ab490a20f528259976ce2864fd722ae to your computer and use it in GitHub Desktop.
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 <array> | |
#include <typeinfo> | |
extern volatile int poop; | |
struct A { | |
virtual void f() { poop += 10; } | |
}; | |
struct B : public A { | |
virtual void f() { poop += 20; } | |
}; | |
struct C : public A { | |
virtual void f() { poop += 30; } | |
}; | |
struct D final : public B { | |
virtual void f() final { poop += 40; } | |
}; | |
template<typename T> | |
struct pmf_traits; | |
template<typename C, typename R, typename A> | |
struct pmf_traits<R (C::*)(A&) const> { | |
using arg_type = A; | |
}; | |
template<typename... Fs> | |
struct devirt_help; | |
template<typename F, typename... Fs> | |
struct devirt_help<F, Fs...> { | |
template<typename K> | |
devirt_help(K &&obj, F &f, Fs... fs) { | |
using T = typename pmf_traits<decltype(&F::operator())>::arg_type; | |
if (typeid(obj) == typeid(T)) { | |
f(static_cast<T&>(obj)); | |
} else { | |
devirt_help<Fs...>(obj, fs...); | |
} | |
} | |
}; | |
template<typename F> | |
struct devirt_help<F> { | |
template<typename K> | |
devirt_help(K &&obj, F f) { | |
f(obj); | |
} | |
}; | |
template<typename T, typename... Fs> | |
void devirt(T &&obj, Fs&&... funcs) { | |
devirt_help<Fs...>(obj, funcs...); | |
} | |
void hello(A &a) { | |
devirt(a, [](D &o) { o.D::f(); } | |
, [](C &o) { o.C::f(); } | |
, [](A &o) { o.f(); }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment