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) = -4
	cout << 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. 后记

到这里四种折叠表达式就介绍完毕了,每种都给了讲解和代码示例。有不懂的地方欢迎评论区提问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/963421.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何用微信小程序写春联

​ 生活没有模板,只需心灯一盏。 如果笑能让你释然,那就开怀一笑;如果哭能让你减压,那就让泪水流下来。如果沉默是金,那就不用解释;如果放下能更好地前行,就别再扛着。 一、引入 Vant UI 1、通过 npm 安装 npm i @vant/weapp -S --production​​ 2、修改 app.json …

openRv1126 AI算法部署实战之——TensorFlow TFLite Pytorch ONNX等模型转换实战

Conda简介 查看当前系统的环境列表 conda env list base为基础环境 py3.6-rknn-1.7.3为模型转换环境&#xff0c;rknn-toolkit版本V1.7.3&#xff0c;python版本3.6 py3.6-tensorflow-2.5.0为tensorflow模型训练环境&#xff0c;tensorflow版本2.5.0&#xff0c;python版本…

电介质超表面中指定涡旋的非线性生成

涡旋光束在众多领域具有重要应用&#xff0c;但传统光学器件产生涡旋光束的方式限制了其在集成系统中的应用。超表面的出现为涡旋光束的产生带来了新的可能性&#xff0c;尤其是在非线性领域&#xff0c;尽管近些年来已经有一些研究&#xff0c;但仍存在诸多问题&#xff0c;如…

Python3 OS模块中的文件/目录方法说明十七

一. 简介 前面文章简单学习了 Python3 中 OS模块中的文件/目录的部分函数。 本文继续来学习 OS 模块中文件、目录的操作方法&#xff1a;os.walk() 方法、os.write()方法 二. Python3 OS模块中的文件/目录方法 1. os.walk() 方法 os.walk() 方法用于生成目录树中的文件名&a…

2025年2月2日(网络编程 tcp)

tcp 循环服务 import socketdef main():# 创建 socket# 绑定tcp_server socket.socket(socket.AF_INET, socket.SOCK_STREAM)tcp_server.bind(("", 8080))# socket 转变为被动tcp_server.listen(128)while True:# 产生专门为链接进来的客户端服务的 socketprint(&qu…

Rust 中的注释使用指南

Rust 中的注释使用指南 注释是代码中不可或缺的一部分&#xff0c;它帮助开发者理解代码的逻辑和意图。Rust 提供了多种注释方式&#xff0c;包括行注释、块注释和文档注释。本文将详细介绍这些注释的使用方法&#xff0c;并通过一个示例展示如何在实际代码中应用注释。 1. 行…

使用Pygame制作“青蛙过河”游戏

本篇博客将演示如何使用 Python Pygame 从零开始编写一款 Frogger 风格的小游戏。Frogger 是一款早期街机经典&#xff0c;玩家需要帮助青蛙穿越车水马龙的马路到达对岸。本示例提供了一个精简原型&#xff0c;包含角色移动、汽车生成与移动、碰撞检测、胜利条件等关键点。希望…

渗透测试过程中碰到的Symfony框架

0x01 不是很顺利的Nday利用 在一次渗透测试过程中发现了目标使用了Symfony框架&#xff0c;然后扫了下目录&#xff0c;发现存在app_dev.php 文件&#xff0c;尝试访问 发现开启了debug模式&#xff0c;Symfony 版本号为2.8.34 php版本5.6.40 也能查看phpinfo页面 然后在网上搜…

Games104——网络游戏的进阶架构

这里写目录标题 前言位移移动插值内插&#xff08;Interpolation&#xff09;外插&#xff08;Extrapolation&#xff09; 命中判定Hit Registration在客户端去判定 在服务器端去判定延迟补偿掩体问题躲进掩体走出掩体 技能前摇本地暴击效果 基础MMO框架分布式架构一致性哈希服…

2025年01月27日Github流行趋势

项目名称&#xff1a;onlook项目地址url&#xff1a;https://github.com/onlook-dev/onlook项目语言&#xff1a;TypeScript历史star数&#xff1a;5340今日star数&#xff1a;211项目维护者&#xff1a;Kitenite, drfarrell, iNerdStack, abhiroopc84, apps/dependabot项目简介…

【Redis】set 和 zset 类型的介绍和常用命令

1. set 1.1 介绍 set 类型和 list 不同的是&#xff0c;存储的元素是无序的&#xff0c;并且元素不允许重复&#xff0c;Redis 除了支持集合内的增删查改操作&#xff0c;还支持多个集合取交集&#xff0c;并集&#xff0c;差集 1.2 常用命令 命令 介绍 时间复杂度 sadd …

[SAP ABAP] 静态断点的使用

在 ABAP 编程环境中&#xff0c;静态断点通过关键字BREAK-POINT实现&#xff0c;当程序执行到这一语句时&#xff0c;会触发调试器中断程序的运行&#xff0c;允许开发人员检查当前状态并逐步跟踪后续代码逻辑 通常情况下&#xff0c;在代码的关键位置插入静态断点可以帮助开发…

从TinyZero的数据与源码来理解DeepSeek-R1-Zero的强化学习训练过程

1. 引入 TinyZero&#xff08;参考1&#xff09;是伯克利的博士生复现DeepSeek-R1-Zero的代码参仓库&#xff0c;他使用veRL来运行RL强化学习方法&#xff0c;对qwen2.5的0.5B、1.5B、3B等模型进行训练&#xff0c;在一个数字游戏数据集上&#xff0c;达到了较好的推理效果。 …

深度卷积神经网络实战无人机视角目标识别

本文采用深度卷积神经网络作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对无人机目标数据集进行训练和优化&#xff0c;该数据集包含丰富的无人…

初级数据结构:栈和队列

一、栈 (一)、栈的定义 栈是一种遵循后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09;原则的数据结构。栈的主要操作包括入栈&#xff08;Push&#xff09;和出栈&#xff08;Pop&#xff09;。入栈操作是将元素添加到栈顶&#xff0c;这一过程中&#xf…

数据结构 前缀中缀后缀

目录 前言 一&#xff0c;前缀中缀后缀的基本概念 二&#xff0c;前缀与后缀表达式 三&#xff0c;使用栈实现后缀 四&#xff0c;由中缀到后缀 总结 前言 这里学习前缀中缀后缀为我们学习树和图做准备&#xff0c;这个主题主要是对于算术和逻辑表达式求值&#xff0c;这…

笔灵ai写作技术浅析(三):深度学习

笔灵AI写作的深度学习技术主要基于Transformer架构,尤其是GPT(Generative Pre-trained Transformer)系列模型。 1. Transformer架构 Transformer架构由Vaswani等人在2017年提出,是GPT系列模型的基础。它摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN),完全依赖自…

专业的定制版软件,一键操作,无限使用

今天给大家介绍一个专业的PDF转word的小软件&#xff0c;软件只有5.5M。非常小&#xff0c;而且没有文档大小的限制&#xff0c;可以随意使用。 PDFtu PDF转word 软件第一次使用需要安装一下。 安装好之后&#xff0c;我们就能在桌面找到对应的图标&#xff0c;打开就能直接使…

QGIS系列22-如何提取不规则多边形的中心经纬度

今天我们来学习一下啊如何通过QGIS提取不规则多边形的中心经纬度 1、首先我们把不规则的多边形图形导入进QGIS里面去 2、现在打开的图层是不可以编辑的&#xff0c;因此我们还需要转换成可编辑状态&#xff0c;具体是选择图层&#xff0c;右键点击&#xff0c;选择切换编辑模式…

word2vec 实战应用介绍

Word2Vec 是一种由 Google 在 2013 年推出的重要词嵌入模型,通过将单词映射为低维向量,实现了对自然语言处理任务的高效支持。其核心思想是利用深度学习技术,通过训练大量文本数据,将单词表示为稠密的向量形式,从而捕捉单词之间的语义和语法关系。以下是关于 Word2Vec 实战…