fork(2) download
  1. #include <iostream>
  2. #include <functional>
  3.  
  4. #include <tuple>
  5. #include <iostream>
  6. using std::cout;
  7. using std::endl;
  8. using namespace std::placeholders;
  9.  
  10. // helpers for tuple unrolling
  11. template<int ...> struct seq {};
  12. template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
  13. template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
  14.  
  15. // simple function
  16. double foo_fn(int x, float y, double z)
  17. {
  18. return x + y + z;
  19. }
  20.  
  21. // structure with memner function to call
  22. struct foo_struct
  23. {
  24. // member function to be used as a delegate
  25. double foo_fn(int x, float y, double z)
  26. {
  27. return x + y + z;
  28. }
  29. // this member function has different signature - but it can be used too
  30. // please not that argument order is changed too
  31. double foo_fn_4(int x, double z, float y, long xx)
  32. {
  33. return x + y + z + xx;
  34. }
  35. };
  36.  
  37. // delegate class that holds as delegate as its params for future call
  38. template <typename Ret, typename ...Args>
  39. struct delayed_call
  40. {
  41. // tuple can be used as FunctionParamsPack type
  42. typedef std::tuple<Args...> params_type;
  43. // std::function as delegate type
  44. typedef std::function<Ret(Args...)> function_type;
  45.  
  46. // stored parameters
  47. params_type params;
  48. // stored delegate
  49. function_type func;
  50.  
  51. // invocation
  52. Ret operator()()
  53. {
  54. return callFunc(typename gens<sizeof...(Args)>::type());
  55. }
  56. // direct invocation
  57. Ret operator()(Args... args)
  58. {
  59. return func(args...);
  60. }
  61.  
  62. // internal invocation with tuple unrolling
  63. template<int ...S>
  64. double callFunc(seq<S...>)
  65. {
  66. return func(std::get<S>(params) ...);
  67. }
  68. };
  69.  
  70. int main(void)
  71. {
  72. // arguments
  73. std::tuple<int, float, double> t = std::make_tuple(1, 5, 10);
  74. // var #1 - you can use simple function as delegate
  75. delayed_call<double, int,float, double> saved_foo_fn{t, foo_fn};
  76. foo_struct fs;
  77. // var #2 - you can use member function as delegate
  78. delayed_call<double, int,float, double> saved_foo_fn_struct{t, std::bind(&foo_struct::foo_fn, fs, _1, _2, _3)};
  79. // var #3 - you can use member function with different signature as delegate. bind 0 to xx
  80. // please not that argument order is changed
  81. delayed_call<double, int,float, double> saved_foo_fn_struct_4{t, std::bind(&foo_struct::foo_fn_4, fs, _1, _3, _2, 0l)};
  82. // var #4 - you can use lambda function as delegate
  83. delayed_call<double, int,float, double> saved_lambda{t, [](int x, float y, double z)
  84. {
  85. return x + y + z;
  86. }
  87. };
  88. cout << "saved_foo_fn: " << saved_foo_fn() << endl;
  89. cout << "saved_foo_fn_struct: " << saved_foo_fn_struct() << endl;
  90. cout << "saved_foo_fn_struct_4: " << saved_foo_fn_struct_4() << endl;
  91. cout << "saved_lambda: " << saved_lambda() << endl;
  92. cout << "direct call with (1,2,3) to a member: " << saved_foo_fn_struct(1, 2, 3) << endl;
  93. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
saved_foo_fn: 16
saved_foo_fn_struct: 16
saved_foo_fn_struct_4: 16
saved_lambda: 16
direct call with (1,2,3) to a member: 6