C++模板编程——可变参函数模板之折叠表达式

devtools/2025/2/4 2:03:30/

目录

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. 后记

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


http://www.ppmy.cn/devtools/155874.html

相关文章

dotnet LINQ 使用简明教程

简介 语言集成查询&#xff08;LINQ&#xff09;是一组强大的技术&#xff0c;它将查询功能直接集成到 c# 语言中。LINQ 查询是 c#.net 中的一等语言结构&#xff0c;就像类、方法、事件一样。LINQ 为查询对象&#xff08; LINQ to objects &#xff09;、关系数据库&#xff…

PVE 中 Debian 虚拟机崩溃后,硬盘数据怎么恢复

问题 在 PVE 中给 Debian 虚拟机新分配硬盘后&#xff0c;通过 Debian 虚拟机开启 Samba 共享该硬盘。如果这个 Debian 虚拟机崩溃后&#xff0c;怎么恢复 Samba 共享硬盘数据。 方法 开启 Samba 共享相关知识&#xff1a;挂载硬盘和开启Samba共享。 新建一个虚拟机&#xf…

【go语言】接口

一、什么是鸭子类型 鸭子类型&#xff08;Duck Typing&#xff09;是一种动态类型系统的概念&#xff0c;源自于一句名言&#xff1a;“如果它走起来像鸭子、叫起来像鸭子&#xff0c;那它就是鸭子。” 这意味着&#xff0c;在鸭子类型的编程语言中&#xff0c;类型不是通过显式…

Microsoft Visual Studio 2022 主题修改(补充)

Microsoft Visual Studio 2022 透明背景修改这方面已经有很多佬介绍过了&#xff0c;今天闲来无事就补充几点细节。 具体的修改可以参考&#xff1a;Microsoft Visual Studio 2022 透明背景修改&#xff08;快捷方法&#xff09;_material studio怎么把背景弄成透明-CSDN博客文…

复制粘贴小工具——Ditto

在日常工作中&#xff0c;复制粘贴是常见的操作&#xff0c;但Windows系统自带的剪贴板功能较为有限&#xff0c;只能保存最近一次的复制记录&#xff0c;这对于需要频繁复制粘贴的用户来说不太方便。今天&#xff0c;我们介绍一款开源、免费且功能强大的剪贴板增强工具——Dit…

使用 MSYS2 qemu 尝鲜Arm64架构国产Linux系统

近期&#xff0c;我的师弟咨询我关于Arm64架构的国产CPU国产OS开发工具链问题。他们公司因为接手了一个国企的单子&#xff0c;需要在这类环境下开发程序。说实在的我也没有用过这个平台&#xff0c;但是基于常识&#xff0c;推测只要基于C和Qt&#xff0c;应该问题不大。 1. …

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)

文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天&#xff0c;不知道你是否留意到&#xff0c;“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注&#xff0c;出于学习的兴趣&#xff0c;我深入研究了一番&#xff0c;才有了这篇文章的诞生。 概念 那么&#xff0c;什么是DeepSeek&#xff1f;首先百…