fork download
  1. #include <array> // for std::array
  2. #include <tuple> // for std::tuple, std::get
  3. #include <type_traits> // for std::remove_cv, std::remove_reference
  4. #include <utility> // for std::forward
  5.  
  6. template<typename T>
  7. using Invoke = typename T::type;
  8.  
  9. template<typename T>
  10. using RemoveCv = Invoke<std::remove_cv<T>>;
  11.  
  12. template<typename T>
  13. using RemoveReference = Invoke<std::remove_reference<T>>;
  14.  
  15. template<typename T>
  16. using Unqualified = RemoveCv<RemoveReference<T>>;
  17.  
  18.  
  19. namespace impl {
  20.  
  21. template<typename T>
  22. struct result_of {
  23. using type = Invoke<T>;
  24. };
  25.  
  26. template<typename TRet, typename... TArg>
  27. struct result_of<TRet(*)(TArg...) > {
  28. using type = TRet;
  29. };
  30.  
  31. template<typename TClass, typename TRet, typename... TArg>
  32. struct result_of<TRet(TClass::*)(TArg...)> {
  33. using type = TRet;
  34. };
  35.  
  36. template<typename Fn, typename... Arg>
  37. struct result_of<Fn(Arg...)> {
  38. using type = Invoke<std::result_of<Fn(Arg...)>>;
  39. };
  40. }
  41.  
  42. template<typename T>
  43. using ResultOf = Invoke<impl::result_of<T>>;
  44.  
  45. template<int...>
  46. struct indices { };
  47.  
  48. namespace impl {
  49.  
  50. template<int N, int... Is>
  51. struct build_indices : build_indices<(N - 1), (N - 1), Is...> { };
  52. template<int... Is>
  53. struct build_indices < 0, Is...> : indices<Is...> { };
  54. }
  55.  
  56. template<int N>
  57. struct build_indices : impl::build_indices<N> { };
  58.  
  59. namespace detail {
  60.  
  61. struct tuplelike_tag { };
  62. struct arraylike_tag { };
  63.  
  64. template<typename>
  65. struct call_with_traits;
  66.  
  67. template<typename... Ts>
  68. struct call_with_traits<std::tuple<Ts...>> {
  69. using tag = tuplelike_tag;
  70.  
  71. enum { size = sizeof...(Ts) };
  72. };
  73.  
  74. template<typename T, std::size_t Sz>
  75. struct call_with_traits<std::array<T, Sz>> {
  76. using tag = arraylike_tag;
  77.  
  78. enum { size = Sz };
  79. };
  80.  
  81. template<typename T, std::size_t Sz>
  82. struct call_with_traits<T[Sz]> {
  83. using tag = arraylike_tag;
  84.  
  85. enum { size = Sz };
  86. };
  87.  
  88. template<typename F, typename T, int... Is>
  89. auto call_with(F && f, T && tup, indices<Is...>, tuplelike_tag) -> ResultOf<Unqualified<F>> {
  90. return (std::forward<F>(f))(std::get<Is>(std::forward<T>(tup))...);
  91. }
  92.  
  93. template<typename F, typename A, int... Is>
  94. auto call_with(F && f, A && arr, indices<Is...>, arraylike_tag) -> ResultOf<Unqualified<F>> {
  95. return (std::forward<F>(f))(std::forward<A>(arr)[Is]...);
  96. }
  97. }
  98.  
  99. template<typename F, typename Cont>
  100. inline auto call_with(F && f, Cont && cont) -> ResultOf<Unqualified<F>> {
  101. using unqualified = Unqualified<Cont>;
  102. using traits = typename detail::call_with_traits<unqualified>;
  103. using tag = typename detail::call_with_traits<unqualified>::tag;
  104. using no_tag = typename traits::tag;
  105. return detail::call_with(std::forward<F>(f), std::forward<Cont>(cont), build_indices<traits::size>(), tag());
  106. }
  107.  
  108. int add(int a, int b, int c) {
  109. return (a + b + c);
  110. }
  111.  
  112. int main(int argc, char ** argv) {
  113. std::tuple<int, int, int> tup { 1, 2, 3 };
  114. int res = call_with(&add, tup);
  115.  
  116. return 0;
  117. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:114:13: warning: unused variable ‘res’ [-Wunused-variable]
prog.cpp: In instantiation of ‘ResultOf<typename std::remove_cv<typename std::remove_reference<_From>::type>::type> call_with(F&&, Cont&&) [with F = int (*)(int, int, int); Cont = std::tuple<int, int, int>&; ResultOf<typename std::remove_cv<typename std::remove_reference<_From>::type>::type> = int]’:
prog.cpp:114:38:   required from here
prog.cpp:104:45: error: no type named ‘tag’ in ‘using traits = struct detail::call_with_traits<typename std::remove_cv<typename std::remove_reference<_To>::type>::type>’
stdout
Standard output is empty