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';
});
我正在尝试一个简单的消息传递API,试图为消息和参数提供一个简单的模板化接口。当我想将参数传递给函数时,我遇到了一个问题。
我没有太多使用可变参数模板,并且想知道我的问题是否有一个优雅的解决方案。
答案 0 :(得分:7)
这是一个简单的框架,用于解压缩元组并将其元素作为给定函数的参数提供:
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)>());
}
在您的Consume()
功能中,您可以这样做:
call_with_tuple(handler, mArgs);
有更多背景信息:
#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);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
};
这是一个live example。
答案 1 :(得分:5)
这个怎么样?
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)...);
}
};
现场演示here。