fork(1) download
  1. #include <tuple>
  2. #include <experimental/tuple>
  3. #include <type_traits>
  4.  
  5. #include <iostream>
  6. #include <typeinfo>
  7.  
  8. template<bool Condition,
  9. typename Then,
  10. typename Else>
  11. using if_t = typename std::conditional<
  12. Condition, Then, Else>::type;
  13.  
  14.  
  15. struct Ignore {
  16. template<typename Tuple>
  17. static std::tuple<> from(Tuple) {
  18. return {};
  19. }
  20. };
  21. template<std::size_t N>
  22. struct Use {
  23. template<typename Tuple>
  24. static auto from(Tuple t) {
  25. return std:: make_tuple(std::get<N>(t));
  26. }
  27. };
  28.  
  29.  
  30. template<
  31. std::size_t N,
  32. typename... Args,
  33. std::size_t... Is>
  34. auto tuple_remove_impl(
  35. std::tuple<Args...> const & t,
  36. std::index_sequence<Is...>) {
  37. return std::tuple_cat(if_t<N == Is, Ignore, Use<Is>>::from(t)...);
  38. }
  39. template<
  40. std::size_t N,
  41. typename... Args>
  42. auto tuple_remove (std::tuple<Args...> const & t) {
  43. return tuple_remove_impl<N>(t, std::index_sequence_for<Args...>{});
  44. }
  45.  
  46.  
  47. template<
  48. std::size_t N,
  49. typename Extractor,
  50. typename R,
  51. typename... Args>
  52. R trampoline (Args... args) {
  53. auto all = std::make_tuple(std::ref(args)...);
  54. auto arguments = tuple_remove<N>(all);
  55. return std::experimental::apply(
  56. Extractor{}.get_function(std::get<N>(all)),
  57. arguments);
  58. }
  59.  
  60. template<std::size_t Num>
  61. struct Multi {
  62. template<std::size_t I, typename R, typename... Args>
  63. struct Extract {
  64. std::function<R(Args...)> & get_function(void * ptr) {
  65. auto arr = static_cast<std::array<void *, Num> *>(ptr);
  66. return *(static_cast<std::function<R(Args...)>*>((*arr)[I]));
  67. }
  68. };
  69. template<typename... Fns>
  70. static void * wrap(Fns &... fns) {
  71. static_assert(sizeof...(fns) == Num, "Don't lie!");
  72. std::array<void *, Num> arr = { static_cast<void *>(&fns)... };
  73. return static_cast<void*>(new std::array<void *, Num>(std::move(arr)));
  74. }
  75. static void free_wrap_result(void * ptr) {
  76. delete (static_cast<std::array<void *, Num>*>(ptr));
  77. }
  78. };
  79.  
  80. struct Single {
  81. template<typename R, typename... Args>
  82. struct Extract {
  83. std::function<R(Args...)> & get_function(void * ptr) {
  84. return *(static_cast<std::function<R(Args...)>*>(ptr));
  85. }
  86. };
  87.  
  88. template<typename R, typename... Args>
  89. static void * wrap(std::function<R(Args...)> & fn) {
  90. return &fn;
  91. }
  92. };
  93.  
  94. void call_one(void (*fn)(int, void *), void * data) {
  95. fn(21, data);
  96. }
  97.  
  98. void call_two(void (*fn)(char const *, void *, double), void * data) {
  99. fn("FOO", data, 3.14);
  100. }
  101.  
  102. void call_both(void (*fn)(int, void *), void (*gn)(char const *, void*, double), void * data) {
  103. call_one(fn, data);
  104. call_two(gn, data);
  105. }
  106.  
  107. int main() {
  108. int offset = 21;
  109. std::function<void(int)> fn = [&offset] (int value) {
  110. std::cout << "FN: " << (offset + value) << std::endl; };
  111. std::function<void(char const *, double)> gn = [] (char const * msg, double value) {
  112. std::cout << "GN: " << msg << " - " << value << std::endl; };
  113.  
  114. std::cout << "Single test:" << std::endl;
  115. call_one(trampoline<1, Single::Extract<void,int>, void, int, void *>, Single::wrap(fn));
  116.  
  117. std::cout << "Multi test:" << std::endl;
  118. offset = 0;
  119. auto fns = Multi<2>::wrap(fn, gn);
  120. call_both(trampoline<1, Multi<2>::Extract<0, void, int>, void, int, void *>,
  121. trampoline<1, Multi<2>::Extract<1, void, char const *, double>, void, char const *, void *, double>,
  122. fns);
  123. Multi<2>::free_wrap_result(fns);
  124. }
Success #stdin #stdout 0s 16064KB
stdin
Standard input is empty
stdout
Single test:
FN: 42
Multi test:
FN: 21
GN: FOO - 3.14