Dukales

enum variant static dispatcher

Mar 16th, 2016
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.17 KB | None | 0 0
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. #include <cassert>
  5.  
  6. template< typename E, E first, E ...rest >
  7. struct front
  8. {
  9.    
  10.     static constexpr E value = first;
  11.    
  12. };
  13.  
  14. template< typename E, template< E > class I, E ...es >
  15. struct D
  16. {
  17.    
  18.     template< E e, typename ...Ts >
  19.     static
  20.     constexpr
  21.     decltype(auto)
  22.     call(Ts &&... ts)
  23.     {
  24.         return I< e >{}(std::forward< Ts >(ts)...);
  25.     }
  26.    
  27.     template< typename ...Ts >
  28.     using caller = decltype(&D::template call< front< E, es... >::value, Ts... >);
  29.  
  30.     template< typename ...Ts >
  31.     static constexpr caller< Ts... > callers_[sizeof...(es)] = {D::template call< es, Ts... >...};
  32.  
  33.     template< std::size_t ...indices >
  34.     constexpr
  35.     std::size_t
  36.     to_sequential_number(E e, std::index_sequence< indices... >) const
  37.     {
  38.         std::size_t i = 0;
  39.         for (E ee : {es...}) {
  40.             if (ee == e) {
  41.                 return i;
  42.             }
  43.             ++i;
  44.         }
  45.         assert(false);
  46.     }
  47.    
  48.     template< typename ...Ts >
  49.     constexpr
  50.     decltype(auto) operator () (E e, Ts &&... ts) const
  51.     {
  52.         return callers_< Ts... >[to_sequential_number(e, std::make_index_sequence< sizeof...(es) >{})](std::forward< Ts >(ts)...);
  53.     }
  54.    
  55. };
  56.  
  57. template< typename E, template< E > class I, E ...es >
  58. template< typename ...Ts >
  59. constexpr typename D< E, I, es... >::template caller< Ts... > D< E, I, es... >::callers_[sizeof...(es)];
  60.  
  61. #include <iostream>
  62.  
  63. #define PP { std::cout << __PRETTY_FUNCTION__ << std::endl; (std::cout << ... << ts) << std::endl; }
  64.  
  65. enum class E
  66. {
  67.     A,
  68.     B,
  69.     C,    
  70. };
  71.  
  72. template< E >
  73. struct I;
  74.  
  75. template<>
  76. struct I< E::A >
  77. {
  78.    
  79.     template< typename ...Ts >
  80.     decltype(auto) operator () (Ts &&... ts) PP
  81.    
  82. };
  83.  
  84. template<>
  85. struct I< E::B >
  86. {
  87.    
  88.     template< typename ...Ts >
  89.     decltype(auto) operator () (Ts &&... ts) PP
  90.    
  91. };
  92.  
  93. template<>
  94. struct I< E::C >
  95. {
  96.    
  97.     template< typename ...Ts >
  98.     decltype(auto) operator () (Ts &&... ts) PP
  99.    
  100. };
  101.  
  102. #include <cstdlib>
  103.  
  104. int
  105. main()
  106. {
  107.     D< E, I, E::C, E::A, E::B >{}(E::A, 1, -2.1f, '3');
  108.     return EXIT_SUCCESS;
  109. }
Advertisement
Add Comment
Please, Sign In to add comment