fork download
  1. #include <iostream>
  2.  
  3. template<unsigned> struct size {};
  4.  
  5. template<unsigned...Is> struct indexes {typedef indexes<Is...> type;};
  6. template<class lhs, class rhs> struct concat_indexes;
  7. template<unsigned...Is, unsigned...Ys> struct concat_indexes<indexes<Is...>, indexes<Ys...>>{
  8. typedef indexes<Is...,Ys...> type;
  9. };
  10. template<class lhs, class rhs>
  11. using ConcatIndexes = typename concat_indexes<lhs, rhs>::type;
  12.  
  13. template<unsigned min, unsigned count> struct make_indexes:
  14. ConcatIndexes<
  15. typename make_indexes<min, count/2>::type,
  16. typename make_indexes<min+count/2, (count+1)/2>::type
  17. >
  18. {};
  19. template<unsigned min> struct make_indexes<min, 0>:
  20. indexes<>
  21. {};
  22. template<unsigned min> struct make_indexes<min, 1>:
  23. indexes<min>
  24. {};
  25. template<unsigned max, unsigned min=0>
  26. using MakeIndexes = typename make_indexes<min, max-min>::type;
  27.  
  28. template< typename L, typename R, unsigned I >
  29. struct helper_helper {
  30. static R func( L&& l ) { return std::forward<L>(l)(size<I>()); }
  31. };
  32. template<typename L, unsigned... Is>
  33. auto
  34. dispatch_helper(indexes<Is...>, L&& l, unsigned i)
  35. -> decltype( std::declval<L>()(size<0>()) )
  36. {
  37. typedef decltype( std::declval<L>()(size<0>()) ) R;
  38. // some compilers have problems with this line.
  39. // you can write a helper class replace the lambda below if so:
  40. typedef R(*F)(L&&);
  41. static const F table[] = {
  42. helper_helper<L, R, Is>::func...
  43. };
  44. return table[i]( std::forward<L>(l) );
  45. };
  46. template<unsigned Max, typename L>
  47. auto
  48. dispatch(L&& l, unsigned i)
  49. -> decltype( std::declval<L>()(size<0>()) )
  50. {
  51. return dispatch_helper( MakeIndexes<Max>(), std::forward<L>(l), i );
  52. };
  53.  
  54.  
  55. struct test {
  56. template<unsigned I>
  57. int operator()( size<I> ) { std::cout << I << "\n"; return I; }
  58. };
  59.  
  60. int main() {
  61. int x = dispatch<1<<14>( test{}, 3 );
  62. std::cout << x << "\n";
  63. // your code goes here
  64. return 0;
  65. }
Success #stdin #stdout 0s 3340KB
stdin
Standard input is empty
stdout
3
3