【问题标题】:Passing position of variadic template argument传递可变参数模板参数的位置
【发布时间】:2013-02-18 17:21:58
【问题描述】:

我想创建一个接受可变数量模板参数的函数。稍后使用这些参数,函数应该像这样传递它们的位置:

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
}

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

【问题讨论】:

  • 我相信你可以避免将对象指针转换为函数指针。
  • @sellibitze:有问题吗?因为我只能拥有从 C 函数传递的 void* 指针用户数据。
  • 数据可以是void *。值得关注的是 void * 的功能。
  • @JurajBlaho:这种演员阵容非常不便携。我建议你解释一下你打算这样解决什么问题。如果您这样做,您可能会收到更多有用的答案。在我看来,我们有一点 X/Y 问题。
  • @sellibitze:感谢您的评论,现在我看到指向void* 的转换函数指针是UB。我将不得不以不同的方式解决它,但我仍然能够使用已接受答案中的想法来解决问题。

标签: c++ c++11 variadic-templates


【解决方案1】:

是的,这是可能的:

// 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&lt;N&gt;::type 然后扩展为 indices&lt;0,1,2,...,N-1&gt;。它作为附加参数提供给实现函数(来自刚刚创建一个虚拟实例的转发器),因此参数推导在实现函数方面启动,并将生成的索引放入参数包Ns

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

【讨论】:

  • 你能发一个简单的例子吗?
  • 我刚做了。我给出的示例中缺少什么?
  • 缺少的是一个真实的例子。带有main() 和一些函数(带有 1,2,3 个参数)。您如何使用这些函数和结构?
  • 我花了一些时间才完全理解代码,似乎它应该可以工作。
  • 我还是不明白。这个:typename make_indices&lt;sizeof...(Args)&gt;::type() 是如何编译的?应该是编译错误。
猜你喜欢
  • 2014-10-20
  • 2012-12-29
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
相关资源
最近更新 更多