fork(1) download
  1. #include <cstdio>
  2. #include <tuple>
  3. #include <utility>
  4. #include <type_traits>
  5.  
  6. template<int ...I> struct index_tuple_type {
  7. template<int N> using append = index_tuple_type<I..., N>;
  8. };
  9. template<int N> struct make_index_impl {
  10. using type = typename make_index_impl<N-1>::type::template append<N-1>;
  11. };
  12. template<> struct make_index_impl<0> { using type = index_tuple_type<>; };
  13. template<int N> using index_tuple = typename make_index_impl<N>::type;
  14.  
  15. template <typename I, typename ...Args>
  16. struct func_traits;
  17.  
  18. template <typename R, int ...I, typename ...Args>
  19. struct func_traits<R, index_tuple_type<I...>, Args...> {
  20. template <typename TT, typename FT>
  21. static inline R call(TT &&t, FT &&f) {
  22. return f(std::get<I>(std::forward<TT>(t))...);
  23. }
  24. };
  25.  
  26. #define _explode_variant(_T) \
  27. template <typename FT, typename ...Args, typename R = typename std::result_of<FT(Args&&...)>::type> \
  28. inline R explode(_T t, FT &&f) { \
  29. return func_traits<R, index_tuple<sizeof...(Args)>, Args...> \
  30. ::call(std::forward<_T>(t), std::forward<FT>(f)); \
  31. }
  32.  
  33. _explode_variant(const std::tuple<Args...>&)
  34. _explode_variant( std::tuple<Args...>&)
  35. _explode_variant( std::tuple<Args...>&&)
  36.  
  37. #undef _explode_variant
  38.  
  39. //----------------------------------------------------------------------
  40.  
  41. void test1(int i, char c) {
  42. printf("%d %c\n", i, c);
  43. }
  44.  
  45. struct S {
  46. int operator()(int, int) { return 5; }
  47. double operator()(int) { return 3.14; }
  48. };
  49.  
  50. struct Object {
  51. Object() = default;
  52. Object(const Object&) { printf("copying\n"); }
  53. Object(Object&&) { printf("moving\n"); }
  54. };
  55.  
  56. void test5(Object a, Object b, Object c) {
  57. printf("in test5, moving\n");
  58. }
  59.  
  60. void test6(Object a, Object b, Object c) {
  61. printf("in test6, copying\n");
  62. }
  63.  
  64. int main() {
  65. std::tuple<int, char> t1{57, 'a'};
  66. explode(t1, test1);
  67.  
  68. S s;
  69. // test correct return value deduction, based on implicit type conversion
  70. std::tuple<float> t2{5};
  71. printf("%f\n", explode(t2, s));
  72.  
  73. std::tuple<int, int> t3{1, 7};
  74. printf("%d\n", explode(t3, s));
  75.  
  76. // lambdas
  77. auto t4 = std::make_tuple("value: ", 10);
  78. explode(std::move(t4), [](const char *prompt, int value) { printf("%s%d\n", prompt, value); });
  79.  
  80. // move!
  81. printf("starting test 5\n");
  82. auto t5 = std::make_tuple(Object{}, Object{}, Object{});
  83. printf("exploding, moving!\n");
  84. explode(std::move(t5), test5);
  85.  
  86. // copy
  87. printf("starting test 6\n");
  88. auto t6 = std::make_tuple(Object{}, Object{}, Object{});
  89. printf("exploding, copying!\n");
  90. explode(t6, test6);
  91. }
  92.  
  93.  
  94.  
Success #stdin #stdout 0s 3340KB
stdin
Standard input is empty
stdout
57 a
3.140000
5
value: 10
starting test 5
moving
moving
moving
exploding, moving!
moving
moving
moving
in test5, moving
starting test 6
moving
moving
moving
exploding, copying!
copying
copying
copying
in test6, copying