C++ 17 折叠表达式

C++ 17 折叠表达式
枫C++ 17 折叠表达式
C++17 引入的
折叠表达式(Fold Expression)主要是给可变参数模板服务的。它的意义很直接:把一包参数按照某个运算符“折叠”成一个表达式,省掉以前那种递归展开模板的写法。
1. 为什么需要折叠表达式?
在 C++17 之前,如果我们想对一组参数求和,常见写法通常是递归模板:
1 | int sum() |
这种写法能用,但比较啰嗦,而且可读性一般。
有了折叠表达式之后,代码可以直接写成:
1 | template <typename... Args> |
明显简洁很多。
2. 基本语法
折叠表达式分为四种形式:
1 | ( ... op pack ) |
其中:
pack:参数包op:运算符init:初始值
2.1 一元左折叠
1 | (... + args) |
等价于:
1 | ((arg1 + arg2) + arg3) + arg4 |
2.2 一元右折叠
1 | (args + ...) |
等价于:
1 | arg1 + (arg2 + (arg3 + arg4)) |
对于加法这种结合性比较自然的运算,左右折叠结果通常一样;但对于减法这类运算,左右折叠就会不同。
3. 最常见的使用场景
3.1 求和
1 |
|
输出:
1 | 10 |
3.2 判断多个条件是否都成立
1 | template <typename... Args> |
使用起来很直观:
1 | bool ret = allTrue(true, true, false); |
3.3 依次输出多个参数
1 |
|
调用:
1 | print(1, "hello", 3.14); |
4. 带初始值的折叠
有时候参数包可能为空,或者你希望给运算提供一个默认起点,这时可以使用带初始值的形式。
1 | template <typename... Args> |
这种写法在处理空参数包时更稳一些。
示例
1 |
|
输出:
1 | 24 |
5. 可以使用哪些运算符?
折叠表达式支持的运算符并不只有 +。常见还有:
+-*/&&||,<<>>
其中 && 和 || 在写条件组合时尤其方便。
6. 使用时要注意的点
6.1 左折叠和右折叠结果可能不同
例如减法:
1 | template <typename... Args> |
leftSub(10, 3, 2) 和 rightSub(10, 3, 2) 的结果并不一样。
6.2 空参数包问题
不是所有运算符都适合在空参数包下直接折叠。
如果你不确定参数个数,最好提供初始值。
6.3 可读性优先
虽然折叠表达式很短,但如果你把很复杂的逻辑都塞进一行,代码也会变得难读。
它适合做“简单、重复、规则一致”的参数包处理。
总结
折叠表达式可以看作是 C++17 给可变参数模板补上的一块重要拼图。它让很多原本需要递归模板展开的代码,变成了更短、更直接的写法。
如果项目里经常要处理参数包,比如批量输出、批量判断、批量求和,那么这个特性会非常顺手。














