折叠表达式 (fold expression)

本文详细介绍了C++17中引入的折叠表达式,涵盖基本语法、四种类型的折叠操作及其示例代码,展示了其在模板编程中的高效应用,如参数累积和逻辑操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

折叠表达式是C++17中引入的一项特性,旨在简化可变参数模板的处理。它允许开发者对模板参数包中的所有元素执行一个给定的操作符,从而将它们“折叠”成单一的值。


一、基本语法

折叠表达式可分为四种类型:

  1. 一元右折叠: ( pack op … )
  2. 一元左折叠: ( … op pack )
  3. 二元右折叠:( pack op … op init )
  4. 二元左折叠: ( init op … op pack )
    op是二元操作符,pack是参数包,init是初始值。

折叠表达式支持所有C++中的二元操作符,包括但不限于:
算术运算符:+, -, *, /, %
逻辑运算符:&&, ||
比较运算符:==, !=, <, >, <=, >=
位运算符:&, |, ^, <<, >>

左折叠从参数包的第一个元素开始处理,而右折叠从最后一个元素开始处理。
带初始值的折叠表达式(二元折叠)提供了额外的灵活性,允许在操作开始或结束时引入一个固定的初始值。

上述几种折叠表达式,展开后解释如下:
1) 一元右折叠 (E op …) 展开后变成:(E1 op (… op (EN-1 op EN)))
2)一元左折叠 (… op E) 展开后变成:(((E1 op E2) op …) op EN)
3)二元右折叠 (E op … op I) 展开后变成:(E1 op (… op (EN−1 op (EN op I))))
4)二元左折叠 (I op … op E) 展开后变成:((((I op E1) op E2) op …) op EN)

二、示例代码

1. 一元左折叠

template<typename... Args>
auto sum(Args... args) {
    return (... + args); // 使用折叠表达式
}

2. 一元右折叠

template<typename... Args>
auto concat_right(Args... args) {
    return (args + ...); // 正确的右折叠示例
}

3. 二元左折叠

#include <iostream>

template<typename T, typename... Args>
auto sum_with_init(T init, Args... args) {
    return (init + ... + args); 
}

int main() {
    auto result = sum_with_init(10, 1, 2, 3, 4); // 初始值为10
    std::cout << "The sum is: " << result << std::endl; // 应该输出20
    return 0;
}

4. 二元右折叠

#include <iostream>

template<typename... Args>
auto sum_right_fold(Args... args) {
    int init = 0; // 初始值
    return (args + ... + init); // 使用初始值的右折叠
}

int main() {
    auto result = sum_right_fold(1, 2, 3, 4); // 应该计算为 1 + (2 + (3 + (4 + 0)))
    std::cout << "The sum is: " << result << std::endl;

    return 0;
}

三、其他

  1. 使用操作符 sizeof… 获取模板参数包args中的参数个数。
    例: sizeof…(args)
  2. 二元折叠表达式中的两个op必须相同。
  3. 如果初始值 init 是一个包含操作符的表达式,且init中的操作符比折叠表达式中的op优先级高,则 init 要用()括起来。
    例:(args + … + (1 * 2))

总结

折叠表达式是C++17标准的一个强大特性,它为模板编程提供了更高效、更简洁的方式来处理可变数量的参数。通过使用折叠表达式,开发者可以轻松实现参数包的累积、逻辑操作等复杂操作,无需依赖于复杂的模板递归或其他技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值