【问题标题】:variadic template parameter pack expanding for function calls用于函数调用的可变参数模板参数包扩展
【发布时间】:2011-10-19 22:46:45
【问题描述】:

我正在寻找类似的东西:

template< typename T>  
void func(T t)
{
}

template< typename... Parms> 
void anyFunc( Parms... p)
{
    func<Parms>(p)... ;  //error 
    func(p)... ;         //error 
}

如果参数包扩展是在另一个函数调用中完成的:

template< typename T>
int some(T t)
{}

template< typename... Parms>
void func(Parms ...p)
{}

template< typename... Parms>
void somemore(Parms... p)
{
   func( some(p)...);
}

int main() 
{
 somemore(1,2,3,4,10,8,7, "Hallo");
}

参数包扩展也适用于基类初始化器列表。

是否有任何解决方案也适用于返回“void”的函数。上述解决方法不会,而在参数列表中使用返回 void 的函数调用将永远无法工作。

有什么想法吗?

【问题讨论】:

  • Hacky 解决方案是将函数调用与逗号运算符结合起来(因此包扩展模式不会产生void)并使用某种只是“吃掉”其参数的虚拟函数。像this 这样的东西。怀疑这是你想要的东西,虽然。 :)

标签: c++11 variadic-templates


【解决方案1】:

不幸的是,正如您所注意到的,扩展参数包仅在解析器需要逗号分隔的条目列表的某些上下文中有效 - 逗号只是句法分隔符而不是逗号运算符的上下文。这可以说是当前文本的一个缺陷。

一个丑陋的解决方法:

func((some(p), 0)...);

请注意,函数参数的计算顺序以及 some 调用的顺序未指定,因此您必须小心任何副作用。

【讨论】:

  • 很容易通过在初始化列表中使用包扩展来以正确的顺序评估函数。注意:g++ 4.8.1 有bug,向后求值!
  • , 0的目的是什么?
  • @Peregring-lk: 使省略号 (some(p), 0) 下的表达式具有非 void 类型——这是必需的,因为您需要一个有效的非 void 类型才能传递给辅助函数 @987654325 @.
【解决方案2】:

一个小的帮助类怎么样:

template <typename Func, typename A, typename ...Args> struct Caller
{
  static void call(Func & f, A && a, Args && ...args)
  {
    f(std::forward<A>(a));
    Caller<Func, Args...>::call(f, std::forward<Args>(args)...);
  }
};

template <typename Func, typename A> struct Caller<Func, A>
{
  static void call(Func & f, A && a)
  {
    f(std::forward<A>(a));
  }
};

template <typename Func, typename ...Args>
void Call(Func & f, Args && ...args)
{
  Caller<Func, Args...>::call(f, std::forward<Args>(args)...);
}

然后你可以在你的客户端代码中加入以下内容:

void foo(A);
Call(foo, a1, a2, a3);

【讨论】:

  • @Dolanor:感谢您的修复。对于这么短的帖子来说,这是一个惊人的错误数量:-S
  • 没问题。我需要让它进行实验,为什么不分享更正? ;)
猜你喜欢
  • 2015-05-21
  • 2014-10-30
  • 1970-01-01
  • 2014-04-12
  • 2021-10-01
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
相关资源
最近更新 更多