c++ - 使用逗号运算符和可变模板参数包折叠表达式

标签 c++ c++17 variadic-templates operator-keyword fold

#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/

相关文章:

c++ - 编译器与简单元函数的差异

c++ - 将 std::variant<A, B> 转换为 std::variant<A, B, C>

c++ - 使用可变参数模板函数包装基于省略号的函数

c++ - Visual C++ 内联 x86 程序集 : Accessing "this" pointer

C++多重继承

python - 从 python 调用 c++ 函数

c++ - is_same 在将类模板实例化与其基类模板进行比较时返回 false?

c++ - 在 C++ 中使用友元函数

c++ - constexpr 模板参数的显式指定参数无效

c++ - 如何使用Variadic Template继承多个接口(interface)