fork download
  1. #include <type_traits>
  2.  
  3. template<typename... Types>
  4. struct TypeList {};
  5.  
  6. template<typename T, typename List, typename=void>
  7. struct IndexOf;
  8.  
  9. template<typename T, typename First, typename... Types>
  10. struct IndexOf<T, TypeList<First, Types...>,
  11. typename std::enable_if<
  12. std::is_same< T, First >::value
  13. >::type
  14. > {
  15. enum {value = 0};
  16. };
  17.  
  18. template<typename T, typename First, typename... Types>
  19. struct IndexOf<T, TypeList<First, Types...>,
  20. typename std::enable_if<
  21. !std::is_same< T, First >::value
  22. >::type
  23. > {
  24. enum {value = 1+IndexOf<T, TypeList<Types...>>::value};
  25. };
  26.  
  27. template<size_t n, typename List>
  28. struct TypeAt;
  29.  
  30. template<size_t n, typename First, typename... Types>
  31. struct TypeAt<n, TypeList<First, Types...>> {
  32. typedef typename TypeAt<n-1, TypeList<Types...>>::type type;
  33. };
  34.  
  35. template<typename First, typename... Types>
  36. struct TypeAt<0, TypeList<First, Types...>> {
  37. typedef First type;
  38. };
  39.  
  40. template<typename Functor, typename List>
  41. struct TypeDispatch {
  42. struct Helper {
  43. Helper( Functor const& f_ ):f(f_) {}
  44. Functor const& f;
  45. template<size_t n>
  46. void Call() const {
  47. typedef typename TypeAt<n, List>::type target_type;
  48. f.template Call<target_type>();
  49. }
  50. };
  51. };
  52.  
  53. template<size_t max>
  54. struct RuntimeSwitch {
  55. template<typename Functor>
  56. static bool Call( size_t n, Functor const& f ) {
  57. if (n == max) {
  58. f.template Call<max>();
  59. return true;
  60. } else {
  61. return RuntimeSwitch<max-1>::template Call( n, f );
  62. }
  63. }
  64. };
  65.  
  66. template<>
  67. struct RuntimeSwitch< size_t(-1) > {
  68. template<typename Functor>
  69. static bool Call( size_t n, Functor const& f ) {
  70. return false;
  71. }
  72. };
  73.  
  74. template<typename List>
  75. struct DynamicTypeDispatch;
  76.  
  77. template<typename... Types>
  78. struct DynamicTypeDispatch<TypeList<Types...>> {
  79. template<typename Functor>
  80. static bool Call( size_t n, Functor const& f ) {
  81. typedef TypeDispatch<Functor, TypeList<Types...>> typeDispatch;
  82. typedef typename typeDispatch::Helper typeCaller;
  83. return RuntimeSwitch<sizeof...(Types)-1>::Call(n, typeCaller(f));
  84. }
  85. };
  86.  
  87. #include <iostream>
  88. #include <string>
  89. struct Test {
  90. std::string s;
  91. Test( std::string s_ ):s(s_) {}
  92. template<typename T>
  93. void Call() const {
  94. std::cout << sizeof(T) << " == " << s.c_str() << " I hope\n";
  95. }
  96. };
  97.  
  98. struct Test2Base {
  99. typedef TypeList<int, double, char> TestList;
  100. virtual void Dispatch( size_t n ) = 0;
  101. template<typename T>
  102. void Test(T const& unused) {
  103. Dispatch( IndexOf<T, TestList>::value );
  104. }
  105. };
  106. template<typename Child>
  107. struct Test2CRTP: Test2Base {
  108. Child* self() { return static_cast<Child*>(this);}
  109. Child const* self() const { return static_cast<Child const*>(this); }
  110.  
  111. template<typename T>
  112. void Call() const {
  113. self()->template TestImpl<T>();
  114. }
  115. virtual void Dispatch( size_t n ) {
  116. DynamicTypeDispatch<Test2Base::TestList>::Call( n, *this );
  117. }
  118. };
  119. struct Test2Impl: Test2CRTP<Test2Impl> {
  120. template<typename T>
  121. void TestImpl() const {
  122. std::cout << T(256.1) << "\n";
  123. }
  124. };
  125. int main()
  126. {
  127. typedef TypeList<int, double> TestList;
  128. DynamicTypeDispatch<TestList>::Call( 0, Test("4") );
  129. DynamicTypeDispatch<TestList>::Call( 1, Test("8") );
  130.  
  131. Test2Impl test2;
  132. test2.Test(int());
  133. test2.Test(char());
  134. test2.Test(double());
  135. }
  136.  
  137.  
Success #stdin #stdout 0s 3064KB
stdin
Standard input is empty
stdout
4 == 4 I hope
8 == 8 I hope
256

256.1