fork download
  1. #include <array>
  2. #include <iostream>
  3. #include <functional>
  4. #include <tuple>
  5. #include <type_traits>
  6.  
  7. /* C++17 std::apply */
  8.  
  9. template <typename Fn, typename Tuple, size_t... Is>
  10. decltype(auto) apply_impl(Fn &&fn, Tuple &&tuple, std::index_sequence<Is...>) {
  11. return std::forward<Fn>(fn)(std::get<Is>(std::forward<Tuple>(tuple))...);
  12. }
  13.  
  14. template <typename Fn, typename Tuple>
  15. decltype(auto) apply(Fn &&fn, Tuple &&tuple) {
  16. return apply_impl(
  17. std::forward<Fn>(fn),
  18. std::forward<Tuple>(tuple),
  19. std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
  20. }
  21.  
  22. /* function_arity */
  23.  
  24. template <typename F>
  25. struct function_arity;
  26.  
  27. template <typename R, typename... Args>
  28. struct function_arity<R (Args...)>
  29. : std::integral_constant<std::size_t, sizeof...(Args)> {};
  30.  
  31. template <typename R, typename... Args>
  32. struct function_arity<R (*)(Args...)> : function_arity<R (Args...)> {};
  33.  
  34. template <typename R, typename... Args>
  35. struct function_arity<R (&)(Args...)> : function_arity<R (Args...)> {};
  36.  
  37. template <typename R, typename C, typename... Args>
  38. struct function_arity<R (C::*)(Args...) const> : function_arity<R (Args...)> {};
  39.  
  40. template <typename R, typename C, typename... Args>
  41. struct function_arity<R (C::*)(Args...)> : function_arity<R (Args...)> {};
  42.  
  43. template <typename C>
  44. struct function_arity : function_arity<decltype(&C::operator())> {};
  45.  
  46. /* make_integer_range */
  47.  
  48. template <typename T, typename U, T Begin>
  49. struct make_integer_range_impl;
  50.  
  51. template <typename T, T... Ints, T Begin>
  52. struct make_integer_range_impl<T, std::integer_sequence<T, Ints...>, Begin> {
  53. using type = std::integer_sequence<T, Begin + Ints...>;
  54. };
  55.  
  56. template <class T, T Begin, T End>
  57. using make_integer_range =
  58. typename make_integer_range_impl<T,
  59. std::make_integer_sequence<T, End - Begin>,
  60. Begin>::type;
  61.  
  62. template <std::size_t Begin, std::size_t End>
  63. using make_index_range = make_integer_range<std::size_t, Begin, End>;
  64.  
  65. /* slice */
  66.  
  67. template <std::size_t... Is, std::size_t... Js>
  68. constexpr decltype(auto) slice_impl(std::index_sequence<Is...>,
  69. std::index_sequence<Js...>) {
  70. using array_t = std::array<std::size_t, sizeof...(Is)>;
  71. return std::index_sequence<std::get<Js>(array_t{{Is...}})...>();
  72. }
  73.  
  74. template <std::size_t Begin, std::size_t End, std::size_t... Is>
  75. constexpr decltype(auto) slice(std::index_sequence<Is...> is) {
  76. return slice_impl(is, make_index_range<Begin, End>());
  77. }
  78.  
  79. /* partial_sum */
  80.  
  81. template <std::size_t... Is>
  82. struct partial_sum;
  83.  
  84. template <std::size_t... Is>
  85. using partial_sum_t = typename partial_sum<Is...>::type;
  86.  
  87. template <>
  88. struct partial_sum<> { using type = std::index_sequence<>; };
  89.  
  90. template <std::size_t I, std::size_t... Is>
  91. struct partial_sum<I, Is...> {
  92.  
  93. template <typename Js>
  94. struct impl;
  95.  
  96. template <std::size_t... Js>
  97. struct impl<std::index_sequence<Js...>> {
  98. using type = std::index_sequence<I, Js + I...>;
  99. };
  100.  
  101. using type = typename impl<partial_sum_t<Is...>>::type;
  102. };
  103.  
  104. /* split_and_call */
  105.  
  106. template <typename... Fns, typename Args, std::size_t... Is, std::size_t... Js>
  107. void split_and_call_impl(Args &&args,
  108. std::index_sequence<Is...>,
  109. std::index_sequence<Js...>) {
  110. int dummy[] = {
  111. (apply_impl(Fns{}, std::forward<Args>(args), make_index_range<Is, Js>{}),
  112. 0)...};
  113. (void)dummy;
  114. }
  115.  
  116. template <typename... Fns, typename... Args>
  117. void split_and_call(Args &&... args) {
  118. auto partial_sums = partial_sum_t<0, function_arity<Fns>{}...>{};
  119. auto is = slice<0, sizeof...(Fns)>(partial_sums);
  120. auto js = slice<1, sizeof...(Fns) + 1>(partial_sums);
  121. split_and_call_impl<Fns...>(
  122. std::forward_as_tuple(std::forward<Args>(args)...), is, js);
  123. }
  124.  
  125. int main() {
  126. struct F { void operator()(int x, int y) {
  127. std::cout << "F(" << x << ", " << y << ')' << std::endl;
  128. }
  129. };
  130. struct G {
  131. void operator()(int x) { std::cout << "G(" << x << ')' << std::endl; }
  132. };
  133. split_and_call<F, G>(1, 2, 3);
  134. }
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
F(1, 2)
G(3)