以下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...)...);
这将无法编译。我们将两者都展开Ts
并vs
“就位”,但是随后我们没有剩下的任何组合可以扩展为最终的椭圆。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句