#include <functional>
#include <iostream>
#include <cassert>
struct BaseType_t
{
virtual ~ BaseType_t () = default;
};
// es gibt viele BaseType varianten...
struct TypeA_t:BaseType_t
{
int value = 123;
};
struct TypeB_t:BaseType_t
{
double value = 123.321;
};
template <typename Base, typename... Types>
struct TypeBasedDispatch;
template <typename Base, typename T1, typename... Rest>
struct TypeBasedDispatch<Base, T1, Rest...> {
template <typename F>
static void call (F&& f, Base* base) {
T1* res = dynamic_cast<T1*> (base);
if (res)
std::forward<F> (f) (*res);
else
TypeBasedDispatch<Base, Rest...>::call (std::forward<F> (f), base);
}
};
template <typename Base>
struct TypeBasedDispatch<Base> {
template <typename F>
static void call (F&&, Base*) {
assert (false);
}
};
template <typename... Types, typename F, typename Base>
void typeBasedDispatch (Base* base, F&& f) {
TypeBasedDispatch<Base, Types...>::call (std::forward<F> (f), base);
}
struct Test_t
{
void OnType (const TypeA_t & type)
{
std::cout << "OnTypeA! value: " << type.value << std::endl;
}
void OnType (const TypeB_t & type)
{
std::cout << "OnTypeB! value: " << type.value << std::endl;
}
void OnType (BaseType_t * base_type)
{
typeBasedDispatch <TypeA_t, TypeB_t> (base_type, [&] (auto& obj) { OnType (obj); });
}
};
int main ()
{
Test_t t;
TypeA_t a;
TypeB_t b;
t.OnType(&a);
t.OnType(&b);
}