Calling a function with specific arguments from a varadic templated class

template< typename ... Args > class Message { public: Message( Args&& ... args ) { mArgs = std::make_tuple( args ... ); } std::tuple< Args ... > mArgs; typedef std::function< void ( Args ... ) > HandlerType; void Consume( HandlerType handler ) { // handler( mArgs ); // How does one unpack this? } }; // Testing code Message<int, int> msg(1, 2); msg.Consume( [] ( int i, int j ) { std::cout << i << ',' << j << '\n'; }); 

I am trying to use a simple messaging API, trying to provide a simple template interface for messages and arguments. I run into a problem when I want to pass arguments to a function.

I did not use variation patterns too much, and I was wondering if there is an elegant solution to my problem.

+4
source share
2 answers

Here is a simple structure for unpacking a tuple and providing its elements as arguments for this function:

 namespace detail { template<int... Is> struct seq { }; template<int N, int... Is> struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; template<int... Is> struct gen_seq<0, Is...> : seq<Is...> { }; template<typename F, typename... Ts, int... Is> void call_with_tuple(F&& f, std::tuple<Ts...> const& t, seq<Is...>) { (std::forward<F>(f))(std::get<Is>(t)...); } } template<typename F, typename... Ts> void call_with_tuple(F&& f, std::tuple<Ts...> const& t) { detail::call_with_tuple(std::forward<F>(f), t, detail::gen_seq<sizeof...(Ts)>()); } 

Inside your Consume() function, you can simply do:

 call_with_tuple(handler, mArgs); 

With another context:

 #include <iostream> #include <functional> template< typename ... Args > class Message { public: Message( Args&& ... args ) { mArgs = std::make_tuple( args ... ); } std::tuple< Args ... > mArgs; typedef std::function< void ( Args ... ) > HandlerType; void Consume( HandlerType handler ) { call_with_tuple(handler, mArgs); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } }; 

And here is a living example .

+7
source

How about this?

 template<size_t... indexes> struct index_tuple {}; template<size_t head, size_t... indexes> struct index_tuple<head, indexes...> { typedef typename index_tuple<head-1, head-1, indexes...>::type type; }; template<size_t... indexes> struct index_tuple<0, indexes...> { typedef index_tuple<indexes...> type; }; template<typename... Args> struct index_tuple_maker { typedef typename index_tuple<sizeof...(Args)>::type type; }; template< typename ... Args > class Message { public: Message( Args&& ... args ) { mArgs = std::make_tuple( args ... ); } std::tuple< Args ... > mArgs; typedef std::function< void ( Args ... ) > HandlerType; void Consume( const HandlerType &handler ) { Consume(handler, typename index_tuple_maker<Args...>::type()); } private: template<size_t... ns> void Consume(const HandlerType &handler, index_tuple<ns...>) { handler(std::get<ns>(mArgs)...); } }; 

Live demo here .

+5
source

Source: https://habr.com/ru/post/1483469/


All Articles