C++模板编程——可变参函数模板之折叠表达式
目录
1. 什么是折叠表达式
2. 一元左折
3. 一元右折
4. 二元左折
5. 二元右折
6. 后记
上一节主要讲解了可变参函数模板和参数包展开,这一节主要讲一下折叠表达式。
1. 什么是折叠表达式
折叠表达式是C++17中引入的概念,引入折叠表达式的目的是为了计算某个值。这跟可变参有关。
上一节提到了递归展开参数包,通过递归调用的方式可以一个一个地拿到每一个参数并进行处理。
而折叠表达式允许我们一次性让所有参数参与计算。
让我们来看代码感受一下:
#include <iostream>using namespace std;template<typename... T>
auto add_all(T... args)
{return (... + args); // 圆括号不可以省略,圆括号中的内容就是折叠表达式
}int main()
{cout << add_all(1, 2, 3, 4, 5) << endl;
}
运行结果如下图所示:

从结果可以看到,add_all(1,2,3,4,5)的结果是(1+2+3+4+5)的求和结果。
在return 语句后面的圆括号中的内容就是折叠表达式。
折叠表达式一般有4种格式,每种格式都是用圆括号括起来。
- 一元左折
- 一元右折
- 二元左折
- 二元右折
左折就是参数从左侧开始计算,右折就是参数从右侧开始计算。
现在不理解没关系,下面会详细介绍。
2. 一元左折
一元左折的格式为:(... 运算符 一包参数)
计算过程为:(((参数1 运算符 参数2) 运算符 参数3) ... 运算符 参数N)
这种形式的三个点在开头,中间是运算符,一包参数在右侧,整体用圆括号括起来的形式就是一元左折。
上面代码中演示的就是一元左折的形式。下面再举个别的例子。
#include <iostream>using namespace std;template<typename... T>
auto mul_all(T... args)
{return (... * args);
}int main()
{cout << mul_all(1, 2, 3) << endl;// ((1+2)+3) = 6
}
运行结果如下图所示:

mul_all函数中的(... * args)就是一元左折。
理解起来应该很容易,其中运算符可以换成其他的,可以编写代码尝试一下。
一元左折就先介绍到这里。
3. 一元右折
一元左折的格式为:(一包参数 运算符 ...)
计算过程为:(参数1 ... (参数N-2 运算符(参数N-1 运算符 参数N)))
一元右折和一元左折的格式非常相似,只是一包参数的位置和...的位置反了过来。
计算过程变成了从右侧开始计算。
这里再强调一次,左折就是参数从左侧开始计算,右折就是参数从右侧开始计算。
下面再给一个具体的代码示例:
#include <iostream>using namespace std;template<typename... T>
auto sub_all_left(T... args) // 一元左折
{return (... - args);
}template<typename... T>
auto sub_all_right(T... args) // 一元右折
{return (args - ...);
}int main()
{cout << sub_all_left(1, 2, 3) << endl; // ((1-2)-3) = -4cout << sub_all_right(1, 2, 3) << endl; // (1-(2-3)) = 2
}
这里展示了一元左折和一元右折的减法运算符的实现,运行结果如下图所示:

代码比较好理解,不太理解的话仔细看看注释和前面的文字,帮助理解。
一元右折就介绍到这里。
4. 二元左折
二元左折的格式为:(init 运算符 ... 运算符 一包参数)
计算过程为:((((init 运算符 参数1) 运算符 参数2) 运算符 参数3) ... 运算符 参数N)
其中,init相当于一个初始值,也可以是一个对象什么的,只要能参与运算符的运算就可以。
下面看一段代码帮助理解:
#include <iostream>using namespace std;template<typename U, typename... T>
auto sub_all_left_with_init(U init, T... args) // 二元左折
{return (init - ... - args);
}int main()
{int init = 10;cout << sub_all_left_with_init(init, 2, 3, 4) << endl; // ((((init-2))-3)-4)=1
}
运行结果如下图所示:

上面那个例子看完之后,再来看看这个例子,启发一下。
#include <iostream>
using namespace std;template<typename... T>
void print_all(T... args)
{(cout << ... << args) << endl;
}int main()
{print_all(1, 2, 3, 4, 5); // 12345
}
运行结果如下图所示:

因为cout << arg的返回值仍然是cout,所以二元左折可以进行,好好体会一下。
5. 二元右折
二元左折的格式为:(一包参数 运算符 ... 运算符 init)
计算过程为:(参数1 ... (参数N-2 运算符 (参数N-1 运算符 (参数N 运算符 init ))))
跟二元左折很类似,直接上代码感受一下吧:
#include <iostream>using namespace std;template<typename U, typename... T>
auto sub_all_right_with_init(U init, T... args) // 二元右折
{return (args - ... - init);
}int main()
{int init = 10;cout << sub_all_right_with_init(init, 2, 3) << endl;//(2-(3-init)) = 9
}
运行结果如图所示:

6. 后记
到这里四种折叠表达式就介绍完毕了,每种都给了讲解和代码示例。有不懂的地方欢迎评论区提问
相关文章:
C++模板编程——可变参函数模板之折叠表达式
目录 1. 什么是折叠表达式 2. 一元左折 3. 一元右折 4. 二元左折 5. 二元右折 6. 后记 上一节主要讲解了可变参函数模板和参数包展开,这一节主要讲一下折叠表达式。 1. 什么是折叠表达式 折叠表达式是C17中引入的概念,引入折叠表达式的目的是为了…...
ArkTS渲染控制
文章目录 if/else:条件渲染ArkUI通过自定义组件的build()函数和@Builder装饰器中的声明式UI描述语句构建相应的UI。在声明式描述语句中开发者除了使用系统组件外,还可以使用渲染控制语句来辅助UI的构建,这些渲染控制语句包括控制组件是否显示的条件渲染语句,基于数组数据快…...
在Scene里面绘制编辑工具
功能要求 策划要在scene模式下编辑棋子摆放。用handle.GUI绘制来解决了。 问题 在scene模式下编辑产生的数据,进入游戏模式后就全不见了。改为executeAlways也没用。我的解决办法是把编辑数据序列化保存到本地。在OnEnable的时候再读取。但是我忽然想到ÿ…...
UbuntuWindows双系统安装
做系统盘: Ubuntu20.04双系统安装详解(内容详细,一文通关!)_ubuntu 20.04-CSDN博客 ubuntu系统调整大小: 调整指南: 虚拟机中的Ubuntu扩容及重新分区方法_ubuntu重新分配磁盘空间-CSDN博客 …...
[Linux]如何將腳本(shell script)轉換到系統管理服務器(systemd service)來運行?
[InfluxDB]Monitor Tem. and Volt of RaspberryPi and Send Message by Line Notify 在Linux中,shell腳本(shell script)常用於運行各種自動化的流程,包含API串接,設置和啟動應用服務等等,腳本語法也相對易學易讀,因此…...
【leetcode详解】T598 区间加法
598. 区间加法 II - 力扣(LeetCode) 思路分析 核心在于将问题转化, 题目不是要求最大整数本身,而是要求解最大整数的个数 结合矩阵元素的增加原理,我们将抽象问题转为可操作的方法,其实就是再找每组ops中…...
分层多维度应急管理系统的设计
一、系统总体架构设计 1. 六层体系架构 #mermaid-svg-QOXtM1MnbrwUopPb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QOXtM1MnbrwUopPb .error-icon{fill:#552222;}#mermaid-svg-QOXtM1MnbrwUopPb .error-text{f…...
稀疏进化训练:机器学习优化算法中的高效解决方案
稀疏进化训练:机器学习优化算法中的高效解决方案 稀疏进化训练:机器学习优化算法中的高效解决方案引言第一部分:背景与动机1.1 传统优化算法的局限性1.2 进化策略的优势1.3 稀疏性的重要性 第二部分:稀疏进化训练的核心思想2.1 稀…...
实战:如何利用网站日志诊断并解决收录问题?
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/50.html 利用网站日志诊断并解决收录问题是一种非常有效的方法。以下是一个实战指南,帮助你如何利用网站日志来诊断并解决网站的收录问题: 一、获取并分析网站日志 …...
群晖搭建Gitea教程(使用系统自带的postgresql)
基于群晖7.2.2,使用套件中心的gitea,和系统自带的postgresql postgresql: 切换到postgres用户 sudo -I -u postgres 在想要保存数据库的磁盘路径下创建PostgreSql文件夹 初始化数据库文件夹配置 initdb -D ./PostgreSql 备份./PostgreSql路径下的post…...
备考蓝桥杯嵌入式2:使用LCD完成显示
LCD LCD(液晶显示器,Liquid Crystal Display)是一种常见的平面显示技术,广泛应用于电视、电脑显示器、手机屏幕等设备。蓝桥杯中,也有涉及到使用LCD来完成字符串显示的要求和操作。 考场上会给予LCD的驱动包…...
网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。
一、前言 我从24年11月份开始学习网络爬虫应用开发,经过2个来月的努力,于1月下旬完成了开发一款网络爬虫软件的学习目标。这里对本次学习及应用开发进行一下回顾总结。 前几天我已经发了一篇日志(网络爬虫学习:应用selenium从搜…...
Elasticsearch的索引生命周期管理
目录 说明零、参考一、ILM的基本概念二、ILM的实践步骤Elasticsearch ILM策略中的“最小年龄”是如何计算的?如何监控和调整Elasticsearch ILM策略的性能? 1. **监控性能**使用/_cat/thread_pool API基本请求格式请求特定线程池的信息响应内容 2. **调整…...
Observability:实现 OpenTelemetry 原生可观察性的商业价值
作者:来自 Elastic David Hope 利用开放标准和简化的数据收集转变组织的可观察性策略。 现代组织面临着前所未有的可观察性挑战。随着系统变得越来越复杂和分散,传统的监控方法难以跟上步伐。由于数据量每两年翻一番,系统跨越多个云和技术&am…...
C语言中的线程本地变量
这处线程本地变量可不是简单的函数中的本地变量。线程除了可以共享存在于进程内的全局变量外,还可以有属于自己的线程本地变量。线程本地变量的值只能够在某个具体线程的生存期内可用。变量的实际存储空间会在线程开始时分配,线程结束时回收。线程不会对…...
Zabbix 推送告警 消息模板 美化(钉钉Webhook机器人、邮件)
目前网络上已经有很多关于Zabbix如何推送告警信息到钉钉机器人、到邮件等文章。 但是在搜索下来,发现缺少了对告警信息的美化的文章。 本文不赘述如何对Zabbix对接钉钉、对接邮件,仅介绍我采用的美化消息模板的内容。 活用AI工具可以减轻很多学习、脑力负…...
罗格斯大学:通过输入嵌入对齐选择agent
📖标题:AgentRec: Agent Recommendation Using Sentence Embeddings Aligned to Human Feedback 🌐来源:arXiv, 2501.13333 🌟摘要 🔸多代理系统必须决定哪个代理最适合给定的任务。我们提出了一种新的架…...
机器学习7-全连接神经网络3-过拟合与超参数
机器学习6-全连接神经网络3-过拟合欠拟合 过拟合应对过拟合-最优方案:获取更多的训练数据应对过拟合-次优方案:正则化应对过拟合-次优方案2:随机失活综合考量 超参数超参数优化方法 过拟合 机器学习的根本问题是优化和泛化的问题。优化——是…...
【PyTorch】7.自动微分模块:开启神经网络 “进化之门” 的魔法钥匙
目录 1. 梯度基本计算 2. 控制梯度计算 3. 梯度计算注意 4. 小节 个人主页:Icomi 专栏地址:PyTorch入门 在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架,为构建和训练神经网络提供了高效且灵活…...
11 3D变换模块(transform3d.rs)
transform3d.rs代码定义了一个名为 Transform3D 的 Rust 结构体,它用于表示一个3D变换矩阵。这个结构体是泛型的,包含三个类型参数:T、Src 和 Dst。其中,T 用于矩阵元素的数据类型,Src 和 Dst 用于表示变换的源和目标类…...
MATLAB基础应用精讲-【数模应用】梯度直方图(HOG)(附C++和python代码实现)(二)
目录 前言 几个高频面试题目 HOG与SIFT区别 边缘特征与梯度方向直方图的关系 算法原理 什么是HOG 图像中像素点的梯度计算 为每个cell构造梯度方向直方图HOG 数学模型 方向梯度直方图计算步骤 第一步:预处理 第二步:计算梯度图像 第三步:在8*8的网格中计算梯度…...
pytorch生成对抗网络
人工智能例子汇总:AI常见的算法和例子-CSDN博客 生成对抗网络(GAN,Generative Adversarial Network)是一种深度学习模型,由两个神经网络组成:生成器(Generator)和判别器࿰…...
Baklib在企业知识管理领域的领先地位与三款竞品的深度剖析
内容概要 在现代企业中,知识管理已成为提高工作效率和推动创新的重要手段。Baklib作为一款领先的知识中台,以其集成化和智能化的特性,帮助企业在这一领域取得了显著成就。该平台具备强大的知识收集、整理、存储和共享功能,通过构…...
2 MapReduce
2 MapReduce 1. MapReduce 介绍1.1 MapReduce 设计构思 2. MapReduce 编程规范3. Mapper以及Reducer抽象类介绍1.Mapper抽象类的基本介绍2.Reducer抽象类基本介绍 4. WordCount示例编写5. MapReduce程序运行模式6. MapReduce的运行机制详解6.1 MapTask 工作机制6.2 ReduceTask …...
人工智能学习(四)之机器学习基本概念
机器学习基本概念详细解析:从生活实例轻松入门 在当今数字化时代,机器学习作为人工智能领域的核心技术之一,正深刻地改变着我们的生活和工作方式。从智能语音助手到图像识别系统,从个性化推荐引擎到自动驾驶汽车,机器…...
大模型openai范式接口调用方法
本文将介绍如下内容: 一、为什么选择 OpenAI 范式接口?二、调用 Openai 接口官方调用 Demo 示例三、自定义调用 Openai 接口 一、为什么选择 OpenAI 范式接口? OpenAI 范式接口因其简洁、统一和高效的设计,成为了与大型语言模型…...
DeepSeek API接口中的openAI是什么意思?
老六哥的小提示:我们可能不会被AI轻易淘汰,但是会被“会使用AI的人”淘汰。 DeepSeek是一款基于先进推理技术的大型语言模型,能够根据用户提供的简洁提示词生成高质 曾经有外媒评价说:DeepSeek盗用了openAI的技术,或者…...
重构字符串(767)
767. 重构字符串 - 力扣(LeetCode) 解法: class Solution { public:string reorganizeString(string s){string res;//因为1 < s.length < 500 , uint64_t 类型足够uint16_t n s.size();if (n 0) {return res;}unordere…...
测压表压力表计量表针头针尾检测数据集VOC+YOLO格式4862张4类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4862 标注数量(xml文件个数):4862 标注数量(txt文件个数):4862 …...
【C++语言】卡码网语言基础课系列----12. 位置互换
文章目录 练习题目位置互换具体代码实现 小白寄语诗词共勉 练习题目 位置互换 题目描述: 给定一个长度为偶数位的字符串,请编程实现字符串的奇偶位互换。 输入描述: 输入包含多组测试数据。 输入的第一行是一个整数n,表示有测试…...
