Ke *_*ang 11 c++ fold operator-keyword variadic-templates c++17
#include<iostream>
using namespace std;
template<typename ...Args>
void output_argus(Args&&... args)
{
((cout << args << '\n'), ...); // #1
(... , (cout << args << '\n')); // #2
}
int main()
{
output_argus(1, "test", 5.6f);
}
Run Code Online (Sandbox Code Playgroud)
基于c ++ operator doc,','是一个从左到右的运算符.意思a, b, c, d是意义(((a, b), c),d)不是(a, (b, (c, d))).如果a,b,c,d是陈述,这一点很重要.
但是,基于fold表达式doc,','应该使用一元左折.
我的问题为什么我的代码中的两个语句都有效?不应该只#2工作吗?以及如何理解...和args.和嵌套的折叠表达式?
假设我们在一个二元运算符上折叠3个表达式,并使用一元折叠.我们在这里有两个选择:( (xs @ ...)一元右折)和(... @ xs)(一元左折).
(xs @ ...) 扩展到 (a @ (b @ c))
(... @ xs) 扩展到 ((a @ b) @ c)
我们可以说的表达式之间有什么区别a @ (b @ c)和(a @ b) @ c?如果这些类型@是关联的,那么这两个表达式是相同的.这就是联想意味着什么.如果你有一个整数参数包,那么一元左折叠+和一元右折叠+将具有相同的值(模数溢出),因为加法是关联的.另一方面,减法不是关联的.(xs - ...)并且(... - xs)意味着非常不同的事情
同样,,C++中的运算符是关联的.将表达式括起来的方式无关紧要.((a, b), c)并(a, (b, c))评估和丢弃a,然后评估和丢弃b,然后评估c,这是结果.更容易看出你是否将表达式简化为字母为什么会出现这种情况.
其结果是,无论是((cout << args << '\n'), ...)和(... , (cout << args << '\n'))做同样的事情,他们都实际上意味着:
cout << args1 << '\n';
cout << args2 << '\n';
// ...
cout << argsN << '\n';
Run Code Online (Sandbox Code Playgroud)
从链接页面,您的 #1 扩展如下:
((cout << args? << '\n'), ((cout << args? << '\n'), (cout << args? << '\n')));
Run Code Online (Sandbox Code Playgroud)
删除一些重复以使其更清晰:
args?, (args?, args?)
Run Code Online (Sandbox Code Playgroud)
对于#2,扩展归结为:
(args?, args?), args?
Run Code Online (Sandbox Code Playgroud)
让我们来看看每个人的评价。
#1:
args? , (args?, args?)
^^^
Run Code Online (Sandbox Code Playgroud)
带下划线的逗号计算左侧,打印1. 然后右侧被评估,其评估的打印args?,打印test,则打印args?,打印5.6。
#2:
(args?, args?) , args?
^^^
Run Code Online (Sandbox Code Playgroud)
带下划线的逗号计算左侧。这会触发对另一个逗号的评估,该逗号评估args?,printing 的打印1,然后评估args?,printing 的打印test。现在带下划线的逗号已完成评估左侧并评估右侧,打印5.6.
如您所见,尽管括号的分组不同,但两者都会对每个单独的参数产生相同的评估顺序。
请注意,通常情况下,这可能并不总是成立。某些运算符(例如 )+没有像逗号运算符那样有保证的计算顺序。如果使用这样的运算符而不是逗号来连接打印表达式,编译器最终可以选择以任何顺序评估单个参数打印。
| 归档时间: |
|
| 查看次数: |
699 次 |
| 最近记录: |