可能重复:
How do I expand a tuple into variadic template function's arguments?
“unpacking” a tuple to call a matching function pointer
在C ++ 11模板中,有没有办法将元组用作(可能是模板)函数的各个args?
例:
假设我有这个功能:
void foo(int a, int b)
{
}
我有元组auto bar = std::make_tuple(1, 2)
。
我可以用它以模板方式拨打foo(1, 2)
吗?
我的意思不仅仅是foo(std::get<0>(bar), std::get<1>(bar))
因为我想在一个不知道args数量的模板中这样做。
更完整的示例:
template<typename Func, typename... Args>
void caller(Func func, Args... args)
{
auto argtuple = std::make_tuple(args...);
do_stuff_with_tuple(argtuple);
func(insert_magic_here(argtuple)); // <-- this is the hard part
}
我应该注意,我不想创建一个适用于一个arg的模板,另一个适用于两个arg的模板等等。
答案 0 :(得分:59)
尝试这样的事情:
// implementation details, users never invoke these directly
namespace detail
{
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static void call(F f, Tuple && t)
{
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
}
};
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
{
static void call(F f, Tuple && t)
{
f(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename F, typename Tuple>
void call(F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
}
示例:
#include <cstdio>
int main()
{
auto t = std::make_tuple("%d, %d, %d\n", 1,2,3);
call(std::printf, t);
}
使用一些额外的魔法并使用std::result_of
,您可能还可以使整个事物返回正确的返回值。
答案 1 :(得分:4)
创建一个“索引元组”(一个编译时整数元组),然后转发到另一个函数,该函数将索引推断为参数包,并在包扩展中使用它们来调用元组上的std::get
:< / p>
#include <redi/index_tuple.h>
template<typename Func, typename Tuple, unsigned... I>
void caller_impl(Func func, Tuple&& t, redi::index_tuple<I...>)
{
func(std::get<I>(t)...);
}
template<typename Func, typename... Args>
void caller(Func func, Args... args)
{
auto argtuple = std::make_tuple(args...);
do_stuff_with_tuple(argtuple);
typedef redi::to_index_tuple<Args...> indices;
caller_impl(func, argtuple, indices());
}
我index_tuple
的实施位于https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h
但它依赖于模板别名,所以如果你的编译器不支持你需要修改它以使用C ++ 03风格的“模板类型定义”并用
typedef typename redi::make_index_tuple<sizeof...(Args)>::type indices;
caller_impl(func, argtuple, indices());
类似的实用程序在C ++ 14中标准化为std::index_sequence
(有关独立的C ++ 11实现,请参阅index_seq.h)。