使用可变参数模板扩展

劳拉·玛菲(Laura Maftei)

以下3个gun函数调用之间有什么区别

template <class... Ts> void fun(Ts... vs) {
  gun(A<Ts...>::hun(vs)...);
  gun(A<Ts...>::hun(vs...));
  gun(A<Ts>::hun(vs)...);
}

我对一个答案很感兴趣,该答案使用一个特定的例子来解释这三个电话。

巴里

最初,我只是从字面上回答了这个问题,但我想对此进行某种程度的扩展,以更全面地说明如何将什么包装扩展为什么。无论如何,这就是我对事情的看法。

紧随其后的任何包都将在适当位置扩展。所以A<Ts...>相当于A<T1, T2, ..., TN>hun(vs...)同样是等同于hun(v1, v2, ..., vn)它变得复杂的地方是,您得到的不是()而不是后跟椭圆的组合((expr)...)这将扩展为用原始版本替换任何包的原始表达式的(expr1, expr2, ..., exprN)whereexpri引用i所以,如果有的话hun((vs+1)...),那就变成了hun(v1+1, v2+1, ..., vn+1)可以带来更多乐趣的地方是expr可以容纳多个包装(只要它们都具有相同的尺寸!)。这就是我们实现标准完美转发模型的方式。

foo(std::forward<Args>(args)...)

这里expr包含两个包(Args并且args都是两个包),并且两个扩展均“迭代”:

foo(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), ..., std::forward<ArgN>(argN));

通过这种推理,您可以快速了解案例,例如致电时会发生什么foo(1, 2, '3')

第一个gun(A<Ts...>::hun(vs)...);扩展为Ts“就地”,然后有一个表达式可以扩展为最后一个椭圆,因此调用:

gun(A<int, int, char>::hun(1), 
    A<int, int, char>::hun(2), 
    A<int, int, char>::hun('3'));

第二个,gun(A<Ts...>::hun(vs...));将两个包扩展到位:

gun(A<int, int, char>::hun(1, 2, '3'));

第三个是,gun(A<Ts>::hun(vs)...)同时扩展两个包:

gun(A<int>::hun(1), 
    A<int>::hun(2), 
    A<char>::hun('3'));

[更新]为完整起见,gun(A<Ts>::hun(vs...)...)请致电:

gun(A<int>::hun(1, 2, '3'),
    A<int>::hun(1, 2, '3'),
    A<char>::hun(1, 2, '3'));

最后,还有最后一种情况可以考虑,我们在椭圆上过大了:

gun(A<Ts...>::hun(vs...)...);

这将无法编译。我们将两者都展开Tsvs“就位”,但是随后我们没有剩下的任何组合可以扩展为最终的椭圆。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章