c++ - 折叠逗号如何工作?

标签 c++ c++17

下面这行是怎么展开的?

template <class... Ts>
void print_all(std::ostream& os, Ts const&... args) {
    (void(os << args), ...);
}

应用规则,

Unary right fold (E op ...) becomes E1 op (... op (EN-1 op EN))

cppreference 提供,

E  = void(os << args)
op = , 

那么展开就变成了

void(os << args[0], ..., (args[N-3], (args[N-2], args[N-1])) )

?

怎么样

v.push_back(args), ...

是不是变成了

v.push_back(args[0], (args[1], ..., (args[N-2], args[N-1])))

扩展和括号都令人困惑。有人会解释吗?

最佳答案

您必须解压缩包含参数包的整个 表达式。不仅仅是参数包。只需遵守规则:

Unary right fold (E op ...) becomes E1 op (... op (EN-1 op EN))

你是对的 op,Evoid(os << args) , 其中args是包,但 Ei 不仅仅是 argsi,它是整个表达式 void(os << args#i) .所以:

(void(os << args), ...);

变为(为方便起见使用 []):

void(os << args[0]), void(os << args[1]), void(os << args[2]), ..., void(os << args[N-1]);

相当于:

os << args[0];
os << args[1];
...
os << args[N-1];

同样,(v.push_back(args), ...) (括号是必需的)将扩展为:

v.push_back(args[0]), v.push_back(args[1]), ..., v.push_back(args[N-1]);

请注意,您也可以将此示例编写为二进制左折叠:

(os << ... << args);

扩展为:

((((os << args[0]) << args[1]) ... ) << args[N-1]);

关于c++ - 折叠逗号如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45603533/

相关文章:

c++ - 线程安全的延迟获取和释放

c++ - 使用 malloc、char 数组和指针

c++ - 使用头文件中定义的 vector 时出现 Unresolved external symbol 错误

c++ - sqlite3 C++ : retrieving a blob

c++ - 将函数参数限制为某些枚举值

c++ - 使用 `void_t`检测多重继承类型重复错误

c++ - 为什么我还必须使用 -lstdc++fs?

c++ - 类型检查的编译时间失败

c++ - std::optional 的普通默认构造函数

c++ - 检测std::shared_ptr持有原始数组(并获取其大小)