传递可变参数模板参数的位置

问题描述:

我想创建一个包含可变数量的模板参数的函数。后来有这些参数,函数应该这样传递它们的位置:

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.