【C++11新特性】可变参数模板

文章目录

  • 1. 认识可变参数模板
  • 2. 可变参数模板的定义方式
  • 3. 参数包的展开方式
    • 3.1 递归展开参数包
    • 3.2 逗号表达式展开参数包

1. 认识可变参数模板

可变参数模板是C++11新增的最强大的特性之一,它对参数高度泛化,能够让我们创建可以接收可变参数的函数模板和类模板。

  • 在C++11之前,类模型和函数模型中只能包含固定数量的模板参数,可变参数模板无疑是一个巨大的改进,但由于可变参数模板比较抽象,因此使用起来需要一定技巧。
  • 在C++11之前其实也有可变参数的概念,比如printf函数就能够接收任意多个参数,但这是函数参数的可变参数,并不是模板的可变参数。

2. 可变参数模板的定义方式

在这里插入图片描述

  • 模板参数Args前面有省略号,代表它是一个可变参数模板,我们把带省略号的参数称为参数包,参数包里面可以包含0到N(N>=0)个模板参数,而args则是一个函数形参参数包。
  • 模板参数包Args和函数形参参数包args的名字可以任意指定。

现在调用ShowList函数时就可以传入任意多个参数了,并且这些参数可以是不同类型的。
在这里插入图片描述
我们可以在函数模板中通过sizeof计算参数包中参数的个数
在这里插入图片描述
但是我们无法直接获取参数包中的每个参数,只能通过展开参数包的方式获取,这是使用可变参数模板的一个主要特点,也是最大的难点。

3. 参数包的展开方式

3.1 递归展开参数包

递归展开参数包的方式如下:

  • 给函数模板增加一个模板参数,这样就可以从接收到的参数包分离出一个参数出来。
  • 在函数模板中递归调用该函数模板,调用时传入剩下的参数包。
  • 如此递归下去,每次分离出参数包的一个参数,直到参数包中的所有参数都被取出来。

比如我们要打印调用函数时传入的各个参数,那么函数模板可以这样编写:
在这里插入图片描述
这时我们面临的问题就是,如果终止函数的递归调用。

编写无参的递归终止函数

我们可以在刚才的基础上,再编写一个无参的递归终止函数,该函数的函数名与展开函数的函数名相同。
在这里插入图片描述
这样一来,当递归调用ShowList函数模板时,如果传入的参数包中参数的个数为0,那么就会匹配到这个无参的递归终止函数,这样就结束了递归。

  • 但如果外部调用ShowList函数时就没有传入参数,那么就会直接匹配到无参的递归终止函数。
  • 而我们本意是想让外部调用ShowList函数时匹配的都是函数模板,并不是让外部调用时直接匹配到这个递归终止函数。

鉴于此,我们可以将展开函数和递归调用函数的函数名改为ShowListArg,然后重新编写一个ShowList函数模板,该函数模板的函数体重要做的技术调用ShowListArg函数展开参数包。
在这里插入图片描述
这时无论外部调用时传入多少个参数,最终匹配到的都是同一个函数了。

编写带参的递归终止函数

除了编写无参的递归终止函数,也可以编写带参的递归终止函数来终止递归,比如这里编写一个带一个参数的递归终止函数。
在这里插入图片描述
这样一来,在递归调用过程中,如果传入的参数包中参数的个数为1,那么就会匹配到这个递归终止函数,这样也就结束了递归。但是需要注意,这里的递归调用函数需要写成函数模板,因为我们并不知道最后一个参数是什么类型的。

但该方法有一个弊端就是,我们在调用ShowList函数时必须至少传入一个参数,否则就会报错。因为此时无论是调用递归终止函数还是展开函数,都需要至少传入一个参数。

不可以通过判断参数包中参数的个数来终止递归!

既然我们可以通过sizeof计算出参数包中参数的个数,那我们能不能在ShowList函数中设置一个判断,当参数包中参数为0时就终止递归呢?

这种方法是不可行的,原因如下:

  • 函数模板并不能调用,函数模板需要在编译时根据传入的实参类型进行推演,生成对应的函数,这个生成的函数才能够被调用。
  • 而这个推演过程是在编译时进行的,当推演到参数包args中参数个数为0时,还需要将当前函数推演完毕,这时就会继续推演传入0个参数时的ShowList函数,此时就会产生报错,因为ShowList函数至少要求传入一个参数。

3.2 逗号表达式展开参数包

通过列表获取参数包中的参数

数组可以通过列表进行初始化
在这里插入图片描述
如果参数包中各个参数的类型都是整型,那么也可以把这个参数包放到列表当初始化这个整形数组,此时参数包中参数就放到数组中了。
在这里插入图片描述这时调用ShowList函数时就可以传入多个整型参数了。

在这里插入图片描述

但C++并不像Python这样的语言,C++规定一个容器中存储的数据类型必须是相同的,因此如果这样写的话,那么调用ShowList函数时传入的参数只能是整型的,并且还不能传入0个参数,因为数组的大小不能为0,因此我们还需要在此基础上借助逗号表达式来展开参数包。

通过逗号表达式展开参数包

虽然我们不能使用不同类型的参数去初始化一个整形数组,但我们可以借助逗号表达式。

  • 逗号表达式会从左到右依次计算各个表达式,并且将最后一个表达式的值作为返回值进行返回。
  • 将逗号表达式的最后一个表达式设置为一个整型值,确保逗号表达式返回的是一个整形值。
  • 将处理参数包中参数的动作封装成一个函数,将该函数的调用动作作为逗号表达式的第一个表达式。

这样一来,在执行逗号表达式时就会先调用处理函数处理对应的参数,然后再将逗号表达式中的最后一个整形值作为返回值来初始化整型数组。
在这里插入图片描述

  • 我们这里要做的就是打印参数包中的各个参数,因此处理函数中要做的就是将传入的参数进行打印即可。
  • 可变参数的省略号在逗号表达式外面,表示需要将逗号表达式展开,如果省略号加在args的后面,那么参数包展开后会全部传入PrintArg函数,代码中的 {(PrintArg(args), 0)…} 将会展开成 {(PrintArg(arg1), 0), (PrintArg(arg2), 0), (PrintArg(arg3), 0), etc…}

这时调用ShowList函数时就可以传入多个不同类型的参数了,但调用时仍然不能传入0个参数,因为数组的大小不能为0,如果想要支持传入0个参数,也可以写一个无参的ShowList函数。

在这里插入图片描述

实际上我们也可以不用逗号表达式,因为这里的问题就是初始化整型数组时必须用整数,那我们可以将处理函数的返回值设置为整型,然后用这个返回值去初始化整型数组也是可以的。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

QEMU 仿真RISC-V freeRTOS 程序

1. 安裝RISC-V 仿真環境 --QEMU 安裝包下載地址: https://www.qemu.org/ 安裝命令及安裝成功效果如下所示, target-list 設定爲riscv32-softmmu, $ cat ~/project/qemu-8.0.4/install.sh sudo apt-get install libglib2.0-dev sudo apt-get install libpixman-1-dev ./co…

给微软.Net runtime运行时提交的几个Issues

前言 因为目前从事的CLRJIT,所以会遇到一些非常底层的问题,比如涉及到微软的公共运行时和即时编译器或者AOT编译器的编译异常等情况,这里分享下自己提的几个Issues。原文:微软.Net runtime运行时提交的几个Issues Issues 一.issues one 第一个System.Numerics.Vecto…

报错处理:Docker容器无法启动

具体报错: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"program\": executable file not found in $PATH": unknown. 报错环境: 该报错出现在使用…

Orange Pi 3B 开发板 开箱评测 和 系统安装教程

香橙派 Orange Pi 3B(RK3566)开发板 开箱测评 和 系统烧录教程 简介 香橙派 Orange Pi 3B 是一款树莓派大小的单板计算机,但接口更加齐全,包括一个全尺寸 HDMI 接口和一个 M.2 存储插槽,售价199起。 Orange Pi 3B 采…

leetcode438. 找到字符串中所有字母异位词(java)

滑动窗口 找到字符串中所有字母异位词滑动窗口数组优化 上期经典 找到字符串中所有字母异位词 难度 - 中等 Leetcode 438 - 找到字符串中所有字母异位词 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出…

软考:中级软件设计师:大数据

软考:中级软件设计师:大数据 提示:系列被面试官问的问题,我自己当时不会,所以下来自己复盘一下,认真学习和总结,以应对未来更多的可能性 关于互联网大厂的笔试面试,都是需要细心准备的 &#x…

网络经济与企业管理【五】之市场营销管理

感谢内容提供者:金牛区吴迪软件开发工作室 上一篇:网络经济与企业管理【四】之企业组织管理 文章目录 第五章:市场营销管理一、市场营销概述二、市场营销过程1.市场营销的过程2.目标营销经历的三个阶段3.选择目标市场的三种战略4.市场营销组…

【市场营销学三】企业战略与营销管理

【市场营销学三】企业战略与营销管理 一、企业战略与规划1.1、企业战略特征1.2、企业战略层次结构1.3、企业战略规划过程 二、总体战略2.1、认识和界定企业使命2.2、区分战略业务单位2.3、明确投资组合2.4、选择业务成长战略 三、经营战略3.1、分析竞争环境3.2、选择竞争战略 四…

【市场营销学二】市场营销管理哲学及其贯彻

【市场营销学二】市场营销管理哲学及其贯彻 一、市场营销哲管理哲学及其演进1.1、 什么是市场营销管理1.2、什么是市场营销管理哲学1.3、以企业为中心的观念1.4、以消费者为中心的观念1.5、以利益相关者和社会整体利益为中心的观念 二、以全方位营销促进顾客满意及客户忠诚2.1、…

Docker容器:docker consul的注册与发现及consul-template

Docker容器:docker consul的注册与发现及consul-template守护进程 一.docker consul的注册与发现介绍 1.什么是服务注册与发现 (1)服务注册与发现是微服务架构中不可或缺的重要组件。 (2)为解决服务都是单节点的&a…

DiskCatalogMaker for Mac简单智能快速的磁盘管理工具

DiskCatalogMaker是一款Mac上的磁盘目录管理工具。它可以帮助用户快速创建和管理磁盘目录,方便查找和访问存储在磁盘上的文件和文件夹。它具有快速扫描和索引功能,生成详细的目录列表,支持关键字搜索和自定义标签。 此外,DiskCat…

Zotero教程

Zotero教程 简介 Zotero是一款集成式的文献管理工具,支持一键导出bib格式文献库或一键插入Word文档。当然,作为一款文献管理工具,它的核心功能就是文献的管理。不清楚你是否有这样的苦恼,看过的论文很难归类,有得论文…

python使用matplotlib 画柱状图代码_Python 使用 matplotlib 画柱状图教程

Python 使用 matplotlib 画图是非常方便的,之前的文章记录了《Python 使用 matplotlib 画折线图教程》,今天就再次记录一下使用 matplotlib 画柱状图的教程。一般来说,也就折线图和柱状图这两种图比较常见,所以基本上老唐也就用了这两个。 一、基本柱状图 代码:import mat…

(动态规划) 剑指 Offer 48. 最长不含重复字符的子字符串 ——【Leetcode每日一题】

❓剑指 Offer 48. 最长不含重复字符的子字符串 难度:中等 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为…

SpringBoot 2.x 集成QQ邮箱、网易系邮箱、Gmail邮箱发送邮件

在Spring中提供了非常好用的 JavaMailSender接口实现邮件发送,在SpringBoot的Starter模块中也为此提供了自动化配置。 项目源码已托管在Gitee-SpringBoot_Guide 几个名词解释 什么是POP3、SMTP和IMAP? 详细介绍-请移步至网易帮助文档 IMAP和POP3有什么区别&#x…

Gmail配置邮箱客户端

公司的游戏的找回密码功能发邮件是走GMail渠道来实现的。之前在做这一部分的时候,受到QQ邮箱的影响,以为没什么大问题(之前QQ邮箱配置过什么,也比较简单,简单设置好独立密码即可)然后主要原因是这次再次经历了这个过程…

matlab 点云的二进制形状描述子

目录 一、功能概述1、算法概述2、主要函数3、参考文献二、代码示例三、结果展示四、参数解析输入参数名称-值对应参数输出参数五、参考链接本文由CSDN点云侠原创,

网易企业邮箱登录服务器出错,网易企业邮箱登录出现故障,无法正常登录

9月1日上午8:30左右,强比科技企业邮箱客服中心陆续接到网易企业邮箱用户反馈,在通过“mail.域名”登录邮箱过程中出现异常,页面出现“您所请求的网址(URL)无法获取”等错误提示,导致无法正常登录邮箱。 随后,客服人员进…

非常难得的iPad版房地产售楼助手应用

一款高质量的iPad房地产售楼助手应用,采用的是类似facebook,新浪微博,腾讯微博,人人网的布局视图。功能有:客户管理系统(可添加,编辑等);2.房源管理系统;3.房贷计算器等&…

新IPAD安装程序

新IPAD安装程序 安装爱思助手iPad连接电脑复制UDID生成两个签名文件ipa签名安装制作好的ipa下拉设置服务器IP 安装爱思助手 https://www.i4.cn/ iPad连接电脑 复制UDID 生成两个签名文件 把复制的UDID发给研发或IT部,拿到生成的两个签名文件 ipa签名 安装制作…