Skip to content

Instantly share code, notes, and snippets.

@Garciat
Created October 2, 2016 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Garciat/3ab490a20f528259976ce2864fd722ae to your computer and use it in GitHub Desktop.
Save Garciat/3ab490a20f528259976ce2864fd722ae to your computer and use it in GitHub Desktop.
#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