I want the Foo class to keep a pointer to the function that it received during construction, and call that function at some point. I turned to these two questions for help:
And, based on the answers, came up with this code:
#include <functional> template < int N, typename... ARGS > struct apply_func { static void applyTuple( std::function<void(ARGS...)>& f, const std::tuple<ARGS...>& t, ARGS... args ) { apply_func<N-1>::applyTuple( f, t, std::get<N-1>( t ), args... ); } }; template <typename... ARGS> struct apply_func<0,ARGS...> { static void applyTuple( std::function<void(ARGS...)>& f, const std::tuple<ARGS...>& /* t */, ARGS... args ) { f( args... ); } }; template < typename... ARGS > void applyTuple( std::function<void(ARGS...)>& f, std::tuple<ARGS...> const& t ) { apply_func<sizeof...(ARGS), ARGS...>::applyTuple( f, t ); } template<typename... ARGS> class Foo { std::function<void(ARGS...)> m_f; std::tuple<ARGS...> *argument_pack; public: Foo(std::function<void(ARGS...)> f):m_f(f){} void operator()(ARGS... args); void run(); }; template<typename... ARGS> void Foo<ARGS...>::operator()(ARGS... args) { m_f(args...); // this works } template<typename... ARGS> void Foo<ARGS...>::run() { applyTuple<ARGS...>(m_f, *argument_pack); // this doesn't compile } void bar(int i, double d){} int main(void) { Foo<int,double> foo(bar); foo(1,1.0); // this works foo.run(); // this doesn't compile }
If you compile with 'g ++ -std = C ++ 0x', the following line will produce the following error:
test.cc: In function 'void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]': test.cc:52:9: instantiated from 'void Foo<ARGS>::run() [with ARGS = {int, double}]' test.cc:61:17: instantiated from here test.cc:27:8: error: no matching function for call to 'apply_func<2, int, double>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&)' test.cc:27:8: note: candidate is: test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}] test.cc:6:19: note: candidate expects 4 arguments, 2 provided test.cc: In static member function 'static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]': test.cc:27:8: instantiated from 'void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]' test.cc:52:9: instantiated from 'void Foo<ARGS>::run() [with ARGS = {int, double}]' test.cc:61:17: instantiated from here test.cc:9:9: error: no matching function for call to 'apply_func<1>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&, const double&, int&, double&)' test.cc:9:9: note: candidate is: test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}] test.cc:6:19: note: candidate expects 2 arguments, 5 provided test.cc: In static member function 'static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}]': test.cc:9:9: instantiated from 'static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]' test.cc:27:8: instantiated from 'void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]' test.cc:52:9: instantiated from 'void Foo<ARGS>::run() [with ARGS = {int, double}]' test.cc:61:17: instantiated from here test.cc:9:9: error: no matching function for call to 'get(const std::tuple<>&)' test.cc:9:9: note: candidates are: /usr/include/c++/4.6/utility:133:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&) /usr/include/c++/4.6/utility:138:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&) /usr/include/c++/4.6/tuple:531:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&) /usr/include/c++/4.6/tuple:538:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)
What am I missing? Thanks!