传递可变参数模板参数的位置
我想创建一个包含可变数量的模板参数的函数。后来有这些参数,函数应该这样传递它们的位置:
I would like to create a function that takes a variable number of template arguments. Later with these arguments the function should pass their position like this:
template<typename R, typename Args...>
R myFunction(Data &data, void *function) {
auto f = (R (*)(Args...))function;
return f(read<Args1>(data, 1), read<Args2>(data, 2), ...);// <-- This is the problem
}
给定的代码当然是不可编译的。有什么办法来解决它吗?有没有办法没有可变参数模板没有太多的代码重复?
The given code is of course not compilable. Is there any way to fix it? Is there a way to do it without variadic templates without too much code duplication?
是的,这是可能的:
// we need a compile-time helper to generate indices
template< std::size_t... Ns >
struct indices
{
typedef indices< Ns..., sizeof...( Ns ) > next;
};
template< std::size_t N >
struct make_indices
{
typedef typename make_indices< N - 1 >::type::next type;
};
template<>
struct make_indices< 0 >
{
typedef indices<> type;
};
使用这些助手,您的函数需要一个转发器,如下所示:
With these helpers, you need one forwarder for your function like this:
template<typename R, typename... Args, std::size_t... Ns>
R myFunctionImpl(void *Data, void *function, indices<Ns...> ) {
auto f = (R (*)(Args...))function;
return f(read<Args>(Data, Ns + 1)...);// +1 because indices is zero-based
}
template<typename R, typename... Args>
R myFunction(void *Data, void *function) {
return myFunctionImpl< R, Args... >( Data, function, typename make_indices<sizeof...(Args)>::type() );
}
EDIT:首先,我们确定参数包的大小 Args
sizeof ...
。 make_indices< N> :: type
然后扩展为索引< 0,1,2,...,N-1>
。它作为实现函数的一个附加参数(来自只是创建一个虚拟实例的转发器),因此参数推导在实现函数的侧面执行,并将生成的索引放入参数包 Ns
。
How does it work? First, we determine the size of the argument pack Args
through sizeof...
. make_indices<N>::type
then expands into indices<0,1,2,...,N-1>
. It is given as an additional parameter to the implementation function (from the forwarder who just creates a dummy instance), hence argument deduction kicks in on the implementation function's side and puts the generated indices into the argument pack Ns
.
实现函数现在有两个大小相同的参数包,即 Args
和 Ns
。当通过省略号 ...
扩展时,省略号展开应用到的整个表达式,并且并行地展开所有参数包!在上面的例子中,表达式是 read< Args>(Data,Ns + 1)
,可以很好地扩展到OPs伪代码中。
The implementation function now has two argument packs with the same size, namely Args
and Ns
. When expanded through the ellipsis ...
, the ellipsis expands the whole expression that it's applied to and it expands all parameter packs in parallel! In the above example that expression is read<Args>(Data, Ns+1)
, which nicely expands into the OPs pseudo-code.