是的,这是可能的:
// 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 packArgs
到sizeof...
的大小。 make_indices<N>::type
然后扩展为indices<0,1,2,...,N-1>
。它作为实现函数的附加参数(来自仅创建虚拟实例的转发器)提供,因此参数推导在实现函数的一侧开始,并将生成的索引放入参数包Ns
。
该实现函数现在有两个相同大小的参数包,即Args
和Ns
。当通过省略号...
进行扩展时,省略号扩展了的整个表达式它应用于并且它并行扩展所有参数包!在上面的例子中,表达式是read<Args>(Data, Ns+1)
,很好地扩展到OP伪码。
我相信你可以避免指向函数指针转换的对象指针。 – sellibitze 2013-03-04 15:18:51
@sellibitze:这是一个问题吗?因为我只能有一个从C函数传递的void *指针用户数据。 – 2013-03-04 15:40:05
数据可以是'void *'。这是一个值得关注的“void *”函数。 – 2013-03-04 15:41:27