#include <type_traits>
template<typename... Types>
struct TypeList {};
template<typename T, typename List, typename=void>
struct IndexOf;
template<typename T, typename First, typename... Types>
struct IndexOf<T, TypeList<First, Types...>,
typename std::enable_if<
std::is_same< T, First >::value
>::type
> {
enum {value = 0};
};
template<typename T, typename First, typename... Types>
struct IndexOf<T, TypeList<First, Types...>,
typename std::enable_if<
!std::is_same< T, First >::value
>::type
> {
enum {value = 1+IndexOf<T, TypeList<Types...>>::value};
};
template<size_t n, typename List>
struct TypeAt;
template<size_t n, typename First, typename... Types>
struct TypeAt<n, TypeList<First, Types...>> {
typedef typename TypeAt<n-1, TypeList<Types...>>::type type;
};
template<typename First, typename... Types>
struct TypeAt<0, TypeList<First, Types...>> {
typedef First type;
};
template<typename Functor, typename List>
struct TypeDispatch {
struct Helper {
Helper( Functor f_ ):f(f_) {}
Functor f;
template<size_t n>
void Call() {
typedef typename TypeAt<n, List>::type target_type;
f.template Call<target_type>();
}
};
};
template<size_t max>
struct RuntimeSwitch {
template<typename Functor>
static bool Call( size_t n, Functor f ) {
if (n == max) {
f.template Call<max>();
return true;
} else {
return RuntimeSwitch<max-1>::template Call( n, f );
}
}
};
template<>
struct RuntimeSwitch< size_t(-1) > {
template<typename Functor>
static bool Call( size_t n, Functor f ) {
return false;
}
};
template<typename List>
struct DynamicTypeDispatch;
template<typename... Types>
struct DynamicTypeDispatch<TypeList<Types...>> {
template<typename Functor>
static bool Call( size_t n, Functor f ) {
typedef TypeDispatch<Functor, TypeList<Types...>> typeDispatch;
typedef typename typeDispatch::Helper typeCaller;
return RuntimeSwitch<sizeof...(Types)-1>::Call(n, typeCaller(f));
}
};
#include <iostream>
#include <string>
struct Test {
std::string s;
Test( std::string s_ ):s(s_) {}
template<typename T>
void Call() {
std::cout << sizeof(T) << " == " << s.c_str() << " I hope\n";
}
};
int main()
{
typedef TypeList<int, double> TestList;
DynamicTypeDispatch<TestList>::Call( 0, Test("4") );
DynamicTypeDispatch<TestList>::Call( 1, Test("8") );
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHlwZXM+CnN0cnVjdCBUeXBlTGlzdCB7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIExpc3QsIHR5cGVuYW1lPXZvaWQ+CnN0cnVjdCBJbmRleE9mOwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFR5cGVzPgpzdHJ1Y3QgSW5kZXhPZjxULCBUeXBlTGlzdDxGaXJzdCwgVHlwZXMuLi4+LAogIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPAogICAgc3RkOjppc19zYW1lPCBULCBGaXJzdCA+Ojp2YWx1ZQogID46OnR5cGUKPiB7CiAgZW51bSB7dmFsdWUgPSAwfTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZS4uLiBUeXBlcz4Kc3RydWN0IEluZGV4T2Y8VCwgVHlwZUxpc3Q8Rmlyc3QsIFR5cGVzLi4uPiwKICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwKICAgICFzdGQ6OmlzX3NhbWU8IFQsIEZpcnN0ID46OnZhbHVlCiAgPjo6dHlwZQo+IHsKICBlbnVtIHt2YWx1ZSA9IDErSW5kZXhPZjxULCBUeXBlTGlzdDxUeXBlcy4uLj4+Ojp2YWx1ZX07Cn07Cgp0ZW1wbGF0ZTxzaXplX3QgbiwgdHlwZW5hbWUgTGlzdD4Kc3RydWN0IFR5cGVBdDsKCnRlbXBsYXRlPHNpemVfdCBuLCB0eXBlbmFtZSBGaXJzdCwgdHlwZW5hbWUuLi4gVHlwZXM+CnN0cnVjdCBUeXBlQXQ8biwgVHlwZUxpc3Q8Rmlyc3QsIFR5cGVzLi4uPj4gewogICAgdHlwZWRlZiB0eXBlbmFtZSBUeXBlQXQ8bi0xLCBUeXBlTGlzdDxUeXBlcy4uLj4+Ojp0eXBlIHR5cGU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGaXJzdCwgdHlwZW5hbWUuLi4gVHlwZXM+CnN0cnVjdCBUeXBlQXQ8MCwgVHlwZUxpc3Q8Rmlyc3QsIFR5cGVzLi4uPj4gewogICAgdHlwZWRlZiBGaXJzdCB0eXBlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgRnVuY3RvciwgdHlwZW5hbWUgTGlzdD4Kc3RydWN0IFR5cGVEaXNwYXRjaCB7CiAgICBzdHJ1Y3QgSGVscGVyIHsKICAgICAgICBIZWxwZXIoIEZ1bmN0b3IgZl8gKTpmKGZfKSB7fQogICAgICAgIEZ1bmN0b3IgZjsKICAgICAgICB0ZW1wbGF0ZTxzaXplX3Qgbj4KICAgICAgICB2b2lkIENhbGwoKSB7CiAgICAgICAgICAgIHR5cGVkZWYgdHlwZW5hbWUgVHlwZUF0PG4sIExpc3Q+Ojp0eXBlIHRhcmdldF90eXBlOwogICAgICAgICAgICBmLnRlbXBsYXRlIENhbGw8dGFyZ2V0X3R5cGU+KCk7CiAgICAgICAgfQogICAgfTsKfTsKCnRlbXBsYXRlPHNpemVfdCBtYXg+CnN0cnVjdCBSdW50aW1lU3dpdGNoIHsKICAgIHRlbXBsYXRlPHR5cGVuYW1lIEZ1bmN0b3I+CiAgICBzdGF0aWMgYm9vbCBDYWxsKCBzaXplX3QgbiwgRnVuY3RvciBmICkgewogICAgICAgIGlmIChuID09IG1heCkgewogICAgICAgICAgICBmLnRlbXBsYXRlIENhbGw8bWF4PigpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gUnVudGltZVN3aXRjaDxtYXgtMT46OnRlbXBsYXRlIENhbGwoIG4sIGYgKTsKICAgICAgICB9CiAgICB9Cn07Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBSdW50aW1lU3dpdGNoPCBzaXplX3QoLTEpID4gewogICAgdGVtcGxhdGU8dHlwZW5hbWUgRnVuY3Rvcj4KICAgIHN0YXRpYyBib29sIENhbGwoIHNpemVfdCBuLCBGdW5jdG9yIGYgKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgTGlzdD4Kc3RydWN0IER5bmFtaWNUeXBlRGlzcGF0Y2g7Cgp0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUeXBlcz4Kc3RydWN0IER5bmFtaWNUeXBlRGlzcGF0Y2g8VHlwZUxpc3Q8VHlwZXMuLi4+PiB7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yPgogICAgc3RhdGljIGJvb2wgQ2FsbCggc2l6ZV90IG4sIEZ1bmN0b3IgZiApIHsKICAgICAgICB0eXBlZGVmIFR5cGVEaXNwYXRjaDxGdW5jdG9yLCBUeXBlTGlzdDxUeXBlcy4uLj4+IHR5cGVEaXNwYXRjaDsKICAgICAgICB0eXBlZGVmIHR5cGVuYW1lIHR5cGVEaXNwYXRjaDo6SGVscGVyIHR5cGVDYWxsZXI7CiAgICAgICAgcmV0dXJuIFJ1bnRpbWVTd2l0Y2g8c2l6ZW9mLi4uKFR5cGVzKS0xPjo6Q2FsbChuLCB0eXBlQ2FsbGVyKGYpKTsKICAgIH0KfTsKCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4Kc3RydWN0IFRlc3QgewogICAgc3RkOjpzdHJpbmcgczsKICAgIFRlc3QoIHN0ZDo6c3RyaW5nIHNfICk6cyhzXykge30KICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+CiAgICB2b2lkIENhbGwoKSB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHNpemVvZihUKSA8PCAiID09ICIgPDwgcy5jX3N0cigpIDw8ICIgSSBob3BlXG4iOwogICAgfQp9OwppbnQgbWFpbigpCnsKICAgIHR5cGVkZWYgVHlwZUxpc3Q8aW50LCBkb3VibGU+IFRlc3RMaXN0OwogICAgRHluYW1pY1R5cGVEaXNwYXRjaDxUZXN0TGlzdD46OkNhbGwoIDAsIFRlc3QoIjQiKSApOwogICAgRHluYW1pY1R5cGVEaXNwYXRjaDxUZXN0TGlzdD46OkNhbGwoIDEsIFRlc3QoIjgiKSApOwp9Cgo=