fork download
  1. #include <iostream>
  2. #include <tuple>
  3. #include <utility>
  4. #include <type_traits>
  5.  
  6. // C++17 std::apply
  7. template <typename F, typename Tuple, size_t... Is>
  8. auto apply_impl (F&& f, Tuple&& tuple, const std::index_sequence<Is...>&) {
  9. return (std::forward<F>(f))(std::get<Is>(std::forward<Tuple>(tuple))...);
  10. }
  11.  
  12. template <typename Fn, typename Tuple>
  13. auto apply (Fn&& fn, Tuple&& tuple) { // Invoke the Callable object f with a tuple of arguments.
  14. return apply_impl(std::forward<Fn>(fn), std::forward<Tuple>(tuple), std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
  15. }
  16.  
  17. // The subtuple that skips the first 'Skip' components of 'tuple' and then takes the next 'Take' components.
  18. template <std::size_t Skip, std::size_t Take>
  19. struct GetSubtuple {
  20. template <typename Tuple>
  21. static auto get (const Tuple& tuple) {
  22. return std::tuple_cat( std::make_tuple(std::get<Skip>(tuple)), GetSubtuple<Skip+1, Take-1>::get(tuple) );
  23. }
  24. };
  25.  
  26. template <std::size_t Skip>
  27. struct GetSubtuple<Skip, 0> {
  28. template <typename Tuple>
  29. static std::tuple<> get (const Tuple&) { return std::tuple<>(); }
  30. };
  31.  
  32. // Compile-time partial sums. But here is it special. For example, PartialSums<5,10,20>::type is to be P<0,5,15>. We want it to always start with 0, and always ignore the last term in the pack.
  33. template <typename T, typename Output, T LastSum, T...> struct PartialSumsHelper;
  34.  
  35. template <typename T, template <T...> class P, T... Is, T LastSum, T First, T... Rest>
  36. struct PartialSumsHelper<T, P<Is...>, LastSum, First, Rest...> : PartialSumsHelper<T, P<Is..., LastSum + First>, LastSum + First, Rest...> {};
  37.  
  38. template <typename T, template <T...> class P, T... Is, T LastSum, T Last>
  39. struct PartialSumsHelper<T, P<Is...>, LastSum, Last> {
  40. using type = P<Is...>; // We don't want to add the last term to the partial sums in this program.
  41. };
  42.  
  43. template <typename T, T... Is>
  44. struct PartialSums {
  45. template <T...> struct P;
  46. using type = typename PartialSumsHelper<T, P<0>, 0, Is...>::type; // Here we want the first partial sum to be 0 rather than the first value in Is...
  47. };
  48.  
  49. template <typename Sums, std::size_t... Is> struct MultiFunction;
  50.  
  51. template <template <std::size_t...> class P, size_t... Sums, std::size_t... Is>
  52. struct MultiFunction<P<Sums...>, Is...> {
  53. template <typename FunctionTuple, typename ArgsTuple>
  54. static auto execute (const FunctionTuple& functionTuple, const ArgsTuple& argsTuple) {
  55. return executeHelper(functionTuple, std::make_index_sequence<std::tuple_size<FunctionTuple>::value>{}, GetSubtuple<Sums, Is>::get(argsTuple)...);
  56. }
  57. private:
  58. template <typename FunctionTuple, std::size_t... Js, typename... TupleArgs>
  59. static auto executeHelper (const FunctionTuple& functionTuple, const std::index_sequence<Js...>&, const TupleArgs&... tupleArgs) {
  60. const auto tupleOfTuples = std::make_tuple(tupleArgs...);
  61. // const int a[] = {(apply(std::get<Js>(functionTuple), std::get<Js>(tupleOfTuples)), 0)...}; ///// Just a Test. Order of function call correct.
  62. return std::make_tuple (apply(std::get<Js>(functionTuple), std::get<Js>(tupleOfTuples))...); ///// order of function call reversed. Need to define make_tuple_left_to_right which returns the same as make_tuple but calls from left to right.
  63. }
  64. };
  65.  
  66. template <std::size_t... Is, typename ArgsTuple, typename... Fs>
  67. auto multiFunction (const ArgsTuple& argsTuple, Fs... fs) {
  68. return MultiFunction<typename PartialSums<std::size_t, Is...>::type, Is...>::execute (std::make_tuple(fs...), argsTuple);
  69. }
  70.  
  71. // Testing
  72. int foo (int, char) {std::cout << "foo\n"; return 0;}
  73. double bar (bool, double, long) {std::cout << "bar\n"; return 3.5;}
  74. bool baz (char, short, float) {std::cout << "baz\n"; return true;}
  75.  
  76. int main() {
  77. const auto tuple = std::make_tuple(5, 'a', true, 3.5, 1000, 't', 2, 5.8);
  78. const auto t = multiFunction<2,3,3> (tuple, foo, bar, baz);
  79. std::cout << std::boolalpha << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << '\n';
  80. }
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
baz
bar
foo
0 3.5 true