C++模板编程——可变参函数模板

目录

1. 可变参函数模板基本介绍

2. 参数包展开——通过递归函数

3. 参数包展开——通过编译期间if语句(constexpr if)

4. 重载

5. 后记


进来看的小伙伴们应该对C++中的模板有了一定了解,下面给大家介绍一下可变参函数模板。过于基础的概念将不仔细介绍。

1. 可变参函数模板基本介绍

先来看一个可变参函数模板的示例:

#include <iostream>using namespace std;template<typename... T>
void myFunc(T... args)
{cout << "----------------MyFunc begin -----------------" << endl;cout << "收到的参数个数:" << sizeof...(args) << endl;cout << "收到的参数类型个数:" << sizeof...(T) << endl;cout << "----------------MyFunc end   -----------------" << endl;
}int main()
{myFunc();myFunc(1);myFunc(1, 2);myFunc(1, 2, 3);
}

运行结果如下图:

仔细观察上面给出的代码,有三点需要注意:

  1. template行中typename后面跟着三个点,然后是类型模板参数T
  2. 在函数签名行void myFunc(T... args),因为T后面跟着三个点,所以T称为可变参类型。看起来是一个类型,实际上其代表了0个到多个的类型。 args称为一包参数,每个参数的类型都可以为任意类型。
  3. 在C++11引入了sizeof...()的语法,这是固定写法,用于可变参函数模板或可变参模板内部,表示模板参数个数或类型数量。只有这种...的可变参才可以使用。

上面的代码有一个问题,在拿到了一堆参数args之后,我们需要拿到每一个参数进行处理。这就涉及到了参数包的展开,下面将介绍两种参数包展开的两种方法。

2. 参数包展开——通过递归函数

参数包展开的套路是比较固定的,通过递归函数进行参数包展开是一种经典手法。

为了实现递归函数的方式展开参数包,需要编写一个参数包展开函数和一个同名的递归终止函数

这两个函数一起实现参数包的展开。

先看代码:

#include <iostream>using namespace std;void myFunc() // 同名的参数包递归终止函数
{cout << "参数包展开的递归终止函数" << endl;
}template<typename T, typename... U>
void myFunc(T arg1, U... args) // 参数包展开函数
{cout << "收到的参数为:" << arg1 << endl;myFunc(args...);
}int main()
{myFunc(1, 2, 3);
}

运行截图如下图所示:

通过代码可以看到参数包展开函数是一个函数模板。void myFunc(T arg1, U... args);它的函数签名中,T为1个参数,U为0个或多个参数类型。所以这个函数模板最少需要一个参数

通过代码可以看到,递归终止函数为一个同名的普通的函数(不是函数模板)接收0个参数


在main函数中调用myFunc(1,2,3);时,1会匹配到arg1,2和3会匹配到args。

在myFunc内部会调用myFunc(2,3);,2会匹配到arg1,3会匹配到args。

myFunc内部继续调用myFunc(3);,3会匹配到arg1,args没有匹配到任何参数。

接着会调用myFunc(); 调用递归终止函数。

通过这种递归调用的方式就实现了参数包的展开,这是一种固定的编程手法,理解学会就好了。

3. 参数包展开——通过编译期间if语句(constexpr if)

在C++17标准中增加了编译期间if语句。与常规的if语句类似,但是在if语句后增加了一个constexpr关建字,这个关建字代表编译时求值。

有了编译期间if语句就非常方便了,不需要编写递归终止函数了。具体看下面的代码:

#include <iostream>using namespace std;template<typename T, typename ...U>
void myFunc(T arg1, U... args)
{cout << "收到的参数为:" << arg1 << endl;if constexpr (sizeof...(args) > 0){myFunc(args...);}else{cout << "没有更多参数了" << endl;}
}int main()
{myFunc(1, 2, 3);
}

运行结果如下图所示:

使用if constexpr和sizeof...()来判断args中含有的参数个数。当剩余的参数个数大于0时,继续递归调用,否则会执行else分支。

非常好理解,而且编写起来也非常方便。

需要注意的是,if constexpr所指定的条件必须在编译期间能够求值,不可以是变量。

4. 重载

可变参函数模板也可以重载,具体见下面的代码。

#include <iostream>using namespace std;template<typename... T>
void myFunc(T... args)
{cout << "void myFunc(T... args); 执行了" << endl;
}template<typename... T>
void myFunc(T*... args)
{cout << "void myFunc(T*... args); 执行了" << endl;
}void myFunc(int arg)
{cout << "void myFunc(int arg); 执行了" << endl;
}int main()
{myFunc(1, 2, 3);myFunc((int*)nullptr);myFunc(1);
}

运行截图如下所示:

5. 后记

可变参函数模板还是比较好理解的,有讲得不对的地方敬请批评指正。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

海外问卷调查之渠道查,企业经营的指南针

海外问卷调查&#xff0c;是企业调研最常用到的方法&#xff0c;有目的、有计划、有系统地收集研究对象的现实状况或历史状况的一种有效手段&#xff0c;是指导企业经营的有效手段。 海外问卷调查充分运用历史法、观察法等方法&#xff0c;同时使用谈话、问卷、个案研究、测试…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.3 结构化索引:记录数组与字段访问

2.3 结构化索引&#xff1a;记录数组与字段访问 目录/提纲 #mermaid-svg-gEcf7BuFng5Yj4mv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-gEcf7BuFng5Yj4mv .error-icon{fill:#552222;}#mermaid-svg-gEcf7BuFng5Y…

在GPIO控制器中,配置通用输入,读取IO口电平时,上拉和下拉起到什么作用

上下拉电阻作用 在通用输入的时候&#xff0c;也就是在读某个IO的电平的时候 一定要让IO口先保持一个电平状态&#xff0c;这样才能检测到不同电平状态。 如何保持电平状态&#xff1f; 1. 可以通过芯片内部的上下拉电阻&#xff0c;由于是弱上下拉一般不用 2. 硬件外界一个…

Unity学习笔记

1.创建基础物体 层级面板右键 2.创建C#脚本 点击资源浏览器 - 右键 脚本组件需要挂在到一个物体上才能运行 点击立方体 - 添加组件 点击运行 3.安装Shader Graph

【python】python油田数据分析与可视化(源码+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 【python】python油田数据分析与可视化&#xff08…

129.求根节点到叶节点数字之和(遍历思想)

Problem: 129.求根节点到叶节点数字之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 直接利用二叉树的先序遍历&#xff0c;将遍历过程中的节点值先利用字符串拼接起来遇到根节点时再转为数字并累加起来&#xff0c;在归的过程中&#xf…

SpringCloud篇 微服务架构

1. 工程架构介绍 1.1 两种工程架构模型的特征 1.1.1 单体架构 上面这张图展示了单体架构&#xff08;Monolithic Architecture&#xff09;的基本组成和工作原理。单体架构是一种传统的软件架构模式&#xff0c;其中所有的功能都被打包在一个单一的、紧密耦合的应用程序中。 …

一、TensorFlow的建模流程

1. 数据准备与预处理&#xff1a; 加载数据&#xff1a;使用内置数据集或自定义数据。 预处理&#xff1a;归一化、调整维度、数据增强。 划分数据集&#xff1a;训练集、验证集、测试集。 转换为Dataset对象&#xff1a;利用tf.data优化数据流水线。 import tensorflow a…

鸟哥Linux私房菜笔记(三)

鸟哥Linux私房菜笔记&#xff08;三&#xff09; 该第三部分和第四部分主要为原书的第十一章&#xff08;正则表达式与文件格式化处理&#xff09;&#xff0c;第十二章学习shell脚本&#xff0c;第十六章&#xff08;进程管理与SElinux初探部分&#xff09;&#xff0c;第十七…

基于springboot+vue的哈利波特书影音互动科普网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.12 连续数组:为什么contiguous这么重要?

2.12 连续数组&#xff1a;为什么contiguous这么重要&#xff1f; 目录 #mermaid-svg-wxhozKbHdFIldAkj {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wxhozKbHdFIldAkj .error-icon{fill:#552222;}#mermaid-svg-…

【网络】3.HTTP(讲解HTTP协议和写HTTP服务)

目录 1 认识URL1.1 URI的格式 2 HTTP协议2.1 请求报文2.2 响应报文 3 模拟HTTP3.1 Socket.hpp3.2 HttpServer.hpp3.2.1 start()3.2.2 ThreadRun()3.2.3 HandlerHttp&#xff08;&#xff09; 总结 1 认识URL 什么是URI&#xff1f; URI 是 Uniform Resource Identifier的缩写&…

力扣第149场双周赛

文章目录 题目总览题目详解找到字符串中合法的相邻数字重新安排会议得到最多空余时间I3440.重新安排会议得到最多空余时间II 第149场双周赛 题目总览 找到字符串中合法的相邻数字 重新安排会议得到最多空余时间I 重新安排会议得到最多空余时间II 变成好标题的最少代价 题目…

HTB:Alert[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用ffuf对alert.htb域名进行子域名FUZZ 使用go…

96,【4】 buuctf web [BJDCTF2020]EzPHP

进入靶场 查看源代码 GFXEIM3YFZYGQ4A 一看就是编码后的 1nD3x.php 访问 得到源代码 <?php // 高亮显示当前 PHP 文件的源代码&#xff0c;用于调试或展示代码结构 highlight_file(__FILE__); // 关闭所有 PHP 错误报告&#xff0c;防止错误信息泄露可能的安全漏洞 erro…

吴恩达深度学习——有效运作神经网络

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 训练集、验证集、测试集偏差、方差正则化正则化参数为什么正则化可以减少过拟合Dropout正则化Inverted Dropout其他的正则化方法数据增广Early stopping 归一化梯度消失与梯度爆…

【xdoj-离散线上练习】T251(C++)

解题反思&#xff1a; 开始敲代码前想清楚整个思路比什么都重要嘤嘤嘤&#xff01;看到输入m, n和矩阵&#xff0c;注意不能想当然地认为就是高m&#xff0c;宽n的矩阵&#xff0c;细看含义 比如本题给出了树的邻接矩阵&#xff0c;就是n*n的&#xff0c;代码实现中没有用到m这…

deep seek R1本地化部署及openAI API调用

先说几句题外话。 最近deep seek火遍全球&#xff0c;所以春节假期期间趁着官网优惠充值了deep seek的API&#xff0c;用openAI的接口方式尝试了下对deep seek的调用&#xff0c;并且做了个简单测试&#xff0c;测试内容确实非常简单&#xff1a;通过prompt提示词让大模型对用…

01.双Android容器解决方案

目录 写在前面 一&#xff0c;容器 1.1 容器的原理 1.1.1 Namespace 1.1.2 Cgroups&#xff08;Control Groups&#xff09; 1.1.3 联合文件系统&#xff08;Union File System&#xff09; 1.2 容器的应用 1.2.1 微服务架构 1.2.2 持续集成和持续部署&#xff08;CI/…

Python 绘图工具详解:使用 Matplotlib、Seaborn 和 Pyecharts 绘制散点图

目录 数据可视化1.使用 matplotlib 库matplotlib 库 2 .使用 seaborn 库seaborn 库 3 .使用 pyecharts库pyecharts库 注意1. 确保安装了所有必要的库2. 检查Jupyter Notebook的版本3. 使用render()方法保存为HTML文件4. 使用IFrame在Notebook中显示HTML文件5. 检查是否有其他输…