#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);
}
基于c++运算符doc , ','
是一个从左到右的运算符。它的意思是 a, b, c, d
意思是 (((a, b), c),d)
而不是 (a, (b, (c , d)))
。如果 a、b、c、d 是语句,这一点很重要。
然而,基于折叠表达式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';
关于c++ - 使用逗号运算符和可变模板参数包折叠表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53330713/