fork(2) download
  1. #include <tuple>
  2. #include <iostream>
  3.  
  4. // sequence
  5.  
  6. template<size_t...>
  7. struct Sequence
  8. { };
  9.  
  10. template<size_t N, size_t... Seq>
  11. struct GenerateSequence : GenerateSequence<N - 1, N - 1, Seq...>
  12. { };
  13.  
  14. template<size_t... Seq>
  15. struct GenerateSequence<0, Seq...>
  16. {
  17. using type = Sequence<Seq...>;
  18. };
  19.  
  20. // invoke tuple
  21.  
  22. struct TupleForEachInvoker
  23. {
  24. template<typename Func, typename ForEachFunc, typename Tuple, size_t... Seq>
  25. static auto invoke(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple, Sequence<Seq...>)
  26. -> decltype(func(forEachFunc(std::get<Seq>(std::forward<Tuple>(tuple)))...))
  27. {
  28. return func(forEachFunc(std::get<Seq>(std::forward<Tuple>(tuple)))...);
  29. }
  30.  
  31. template<typename Func, typename ForEachFunc, typename... Args>
  32. static auto apply(Func&& func, ForEachFunc&& forEachFunc, std::tuple<Args...>&& args)
  33. -> decltype(invoke(std::forward<Func>(func),
  34. std::forward<ForEachFunc>(forEachFunc),
  35. std::forward<std::tuple<Args...>>(args),
  36. typename GenerateSequence<sizeof...(Args)>::type()))
  37. {
  38. return invoke(std::forward<Func>(func),
  39. std::forward<ForEachFunc>(forEachFunc),
  40. std::forward<std::tuple<Args...>>(args),
  41. typename GenerateSequence<sizeof...(Args)>::type());
  42. }
  43. };
  44.  
  45. template<typename Func, typename ForEachFunc, typename Tuple>
  46. inline auto invokeWithMemberFromAll(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple)
  47. -> decltype(TupleForEachInvoker::apply(std::forward<Func>(func),
  48. std::forward<ForEachFunc>(forEachFunc),
  49. std::forward<Tuple>(tuple)))
  50. {
  51. return TupleForEachInvoker::apply(std::forward<Func>(func),
  52. std::forward<ForEachFunc>(forEachFunc),
  53. std::forward<Tuple>(tuple));
  54. }
  55.  
  56. // exemplar
  57.  
  58. template<typename T>
  59. struct Foo
  60. {
  61. T& data() { return _val; }
  62. T _val;
  63. };
  64.  
  65. struct Extract
  66. {
  67. template<typename T>
  68. T& operator() (Foo<T>& f) { return f.data(); }
  69. };
  70.  
  71. int main()
  72. {
  73. Foo<int> i { 5 };
  74. Foo<double> d { 6. };
  75. Foo<const char*> s { "hello world" };
  76.  
  77. auto cb = [](int& i, const double& d, const char* s)
  78. {
  79. std::cout << "i=" << i << ", d=" << d << ", s=" << s << std::endl;
  80.  
  81. i += 2;
  82. };
  83.  
  84.  
  85. // rvalue reference to tuple
  86. invokeWithMemberFromAll(cb, Extract{}, std::tie(i, d, s));
  87.  
  88. std::cout << i.data() << std::endl;
  89.  
  90. // lvalue reference to tuple - fails
  91. auto tuple = std::tie(i, d, s);
  92. invokeWithMemberFromAll(cb, Extract{}, tuple);
  93.  
  94. std::cout << i.data() << std::endl;
  95.  
  96. }
  97.  
Compilation error #stdin compilation error #stdout 0s 3140KB
stdin
Standard input is empty
compilation info
prog.cpp: In function 'int main()':
prog.cpp:92:46: error: no matching function for call to 'invokeWithMemberFromAll(main()::<lambda(int&, const double&, const char*)>&, Extract, std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&)'
  invokeWithMemberFromAll(cb, Extract{}, tuple);
                                              ^
prog.cpp:92:46: note: candidate is:
prog.cpp:46:13: note: template<class Func, class ForEachFunc, class Tuple> decltype (TupleForEachInvoker::apply(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<Tuple>(tuple))) invokeWithMemberFromAll(Func&&, ForEachFunc&&, Tuple&&)
 inline auto invokeWithMemberFromAll(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple)
             ^
prog.cpp:46:13: note:   template argument deduction/substitution failed:
prog.cpp: In substitution of 'template<class Func, class ForEachFunc, class Tuple> decltype (TupleForEachInvoker::apply(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<Tuple>(tuple))) invokeWithMemberFromAll(Func&&, ForEachFunc&&, Tuple&&) [with Func = main()::<lambda(int&, const double&, const char*)>&; ForEachFunc = Extract; Tuple = std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&]':
prog.cpp:92:46:   required from here
prog.cpp:49:43: error: cannot bind 'std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>' lvalue to 'std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&&'
                 std::forward<Tuple>(tuple)))
                                           ^
prog.cpp:32:14: note: initializing argument 3 of 'static decltype (TupleForEachInvoker::invoke(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<std::tuple<_Tail ...> >(args), typename GenerateSequence<sizeof... (Args)>::type())) TupleForEachInvoker::apply(Func&&, ForEachFunc&&, std::tuple<_Tail ...>&&) [with Func = main()::<lambda(int&, const double&, const char*)>&; ForEachFunc = Extract; Args = {Foo<int>&, Foo<double>&, Foo<const char*>&}; decltype (TupleForEachInvoker::invoke(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<std::tuple<_Tail ...> >(args), typename GenerateSequence<sizeof... (Args)>::type())) = void; typename GenerateSequence<sizeof... (Args)>::type = Sequence<0u, 1u, 2u>]'
  static auto apply(Func&& func, ForEachFunc&& forEachFunc, std::tuple<Args...>&& args)
              ^
stdout
Standard output is empty