使用可变参数模板进行扩展

使用可变参数模板进行扩展

本文介绍了使用可变参数模板进行扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

gun 函数的以下3个调用有什么区别?

What is the difference between the following 3 calls for gun function?

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



我感兴趣的是一个解释这三个调用使用一个具体例子的答案。

I am interested in an answer that explains the three calls using a specific example.

推荐答案

最初我只是简单地回答了问题,但我想扩展这一点,以提供一个更彻底的解释,扩展成什么。这是我如何思考的事情。

Originally I just literally answered the question, but I wanted to expand this somewhat to provide a more thorough explanation of how what packs are expanded into what. This is how I think about things anyway.

任何紧跟着一个省略号的数据包都会被放大。因此 A< Ts ...> 等效于 A hun(vs ...)类似地等同于 hun(v1,v2,...,vn) 。当它变得复杂是当而不是一个后面跟一个椭圆你得到的东西像((expr)...)。这将扩展到(expr1,expr2,...,exprN)其中 expri 任何包替换为 i th版本。因此,如果你有 hun((vs + 1)...),则变成 hun(v1 + 1,v2 + 1,... ,vn + 1)。其中更有趣的是 expr 可以包含多个包(只要它们都有相同的大小!)。这是我们如何实现标准的完美转发模型;

Any pack immediately followed by an ellipses is just expanded in place. So A<Ts...> is equivalent to A<T1, T2, ..., TN> and hun(vs...) is similarly equivalent to hun(v1, v2, ..., vn). Where it gets complicated is when rather than a pack followed by ellipses you get something like ((expr)...). This will get expanded into (expr1, expr2, ..., exprN) where expri refers to the original expression with any pack replaced with the ith version of it. So if you had hun((vs+1)...), that becomes hun(v1+1, v2+1, ..., vn+1). Where it gets more fun is that expr can contain more than one pack (as long as they all have the same size!). This is how we implement the standard perfect forwarding model;

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

这里 expr code> Args 和 args 都是包)和扩展遍历两者:

Here expr contains two packs (Args and args are both packs) and the expansion "iterates" over both:

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

这种推理应该能够快速浏览你的案例, foo(1,2,'3')

That reasoning should make it possible to quickly walk through your cases for, say, what happens when you call foo(1, 2, '3').

第一个, (A< Ts ...> :: hun(vs)...); 扩展 Ts in place表达式扩展最后一个省略号,因此这会调用:

The first one, gun(A<Ts...>::hun(vs)...); expands Ts "in place" and then there's an expression to expand for the last ellipses, so this calls:

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

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

The second one, gun(A<Ts...>::hun(vs...)); expands both packs in place:

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

第三个, gun(A< Ts> :: hun )...),同时展开这两个包:

The third one, gun(A<Ts>::hun(vs)...), expands both packs at the same time:

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

[更新]为了完整起见, gun(A< Ts> (vs ...)...)会调用:

[update] For completeness, gun(A<Ts>::hun(vs...)...) would call:

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

最后,最后一种情况要考虑我们在椭圆上的位置:

Finally, there's one last case to consider where we go overboard on the ellipses:

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

这将无法编译。我们扩大 Ts vs 在适当位置,但是我们没有任何包最后的椭圆。

This will not compile. We expand both Ts and vs "in place", but then we don't have any packs left to expand for the final ellipses.

这篇关于使用可变参数模板进行扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 18:38