2013-03-04 59 views
8

我想创建一个接受可变数量模板参数的函数。后来这些参数的函数应该通过自己的立场是这样的:传递可变参数模板参数的位置

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 
} 

给定的代码当然不是编译。有什么方法可以解决它吗?有没有没有太多代码重复可变模板的方法?

+2

我相信你可以避免指向函数指针转换的对象指针。 – sellibitze 2013-03-04 15:18:51

+0

@sellibitze:这是一个问题吗?因为我只能有一个从C函数传递的void *指针用户数据。 – 2013-03-04 15:40:05

+0

数据可以是'void *'。这是一个值得关注的“void *”函数。 – 2013-03-04 15:41:27

回答

14

是的,这是可能的:

// 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; 
}; 

有了这些助手,你需要一个转发你的功能是这样的:

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()); 
} 

编辑:它是如何工作的?首先,我们确定argument packArgssizeof...的大小。 make_indices<N>::type然后扩展为indices<0,1,2,...,N-1>。它作为实现函数的附加参数(来自仅创建虚拟实例的转发器)提供,因此参数推导在实现函数的一侧开始,并将生成的索引放入参数包Ns

该实现函数现在有两个相同大小的参数包,即ArgsNs。当通过省略号...进行扩展时,省略号扩展了的整个表达式它应用于并且它并行扩展所有参数包!在上面的例子中,表达式是read<Args>(Data, Ns+1),很好地扩展到OP伪码。

+0

你可以发表一个简单的例子吗? – 2013-03-04 15:16:22

+2

我刚刚做到了。我给的例子中缺少的是什么? – 2013-03-04 15:17:41

+0

缺少的是一个真实的例子。用'main()'和一些函数(有1,2,3个参数)。你如何使用这些功能和结构? – 2013-03-04 21:09:11