【C++11】可变参数的函数模板 的 定义 和 应用练习

news2024/10/7 16:20:40

文章目录

    • 定义
    • 常见应用
      • 模板参数包展开
      • 可变参数模板类
      • 可变参数模板函数重载
    • 练习
      • 打印任意数量的参数
      • 将任意数量的参数合并为一个字符串
      • 解包元组(Tuple Unpacking)
    • emplace_back
      • 和 push_back 的比较
      • 实例

定义

可变参数模板(Variable-length argument template)是C++11引入的特性之一,也称为“展开包”(Expansion Pack)。它允许我们在函数模板中使用可变数量的参数,这些 参数可以是任意类型 ,并且可以在函数模板中以类似于函数参数列表的方式进行使用。

使用可变参数模板时,需要在函数模板的参数列表中 使用省略号(…) 来表示可变数量的参数,并通过模板参数包展开来访问这些参数。

> 图片

它里面包含了 0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数


常见应用

模板参数包展开

可变参数的 模板参数包可以通过展开 来实现模板的多态性。

  1. 递归展开
// 递归终止函数
template <class T>
void ShowList(const T& t)
{
	cout << t << endl;
}
// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{
	cout << value <<" ";
	ShowList(args...);
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("show"));
	return 0;
}

ShowList() 函数被定义为两个版本:一个递归终止函数和一个可变参数模板函数。递归终止函数只接受一个参数,并将它打印到标准输出中。可变参数模板函数接受一个参数和一个参数包,将第一个参数打印到标准输出中,并递归调用自身来处理参数包。

  1. 逗号表达式展开
template <class T>
void PrintArg(T t)
{
	// 打印模板参数
	cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	// 将可变参数展开成一个数组a
	int arr[] = { (PrintArg(args), 0)... };
	cout << endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

两次执行结果:

在这里插入图片描述

可变参数模板类

可变参数模板也可以用于定义类模板,如下图:

在这里插入图片描述

在这个例子中,我们定义了一个可变参数模板类 Tuple,它接受任意数量和类型的参数,并包含一个 std::tuple 类型的成员变量 values。在 main() 函数中,我们创建了一个包含整数、字符串和浮点数的元组,并将它赋值给 t 中的 values 成员变量。

可变参数模板函数重载

可变参数模板可以与函数重载一起使用,实现不同参数数量或类型的函数重载。例如:

template<class T>
void print(T t) {
	std::cout << t << std::endl;
}

template<typename T, typename... Args>
void print(T t, Args... args) {
	std::cout << t << " ";
	print(args...);
}

int main() {
	print(1, 2, 3, "hello", 'A'); // 输出 1 2 3 hello A
	return 0;
}

在这个例子中,我们定义了两个 print() 函数,一个接受单个参数,另一个接受任意数量的参数。在调用时,编译器会根据参数数量和类型来选择对应的函数进行调用。


练习

打印任意数量的参数

使用可变参数模板可以方便地打印任意数量的参数。例如,我们可以编写一个函数模板来打印任意数量的参数:

在这里插入图片描述

将任意数量的参数合并为一个字符串

使用可变参数模板可以方便地将任意数量的参数合并为一个字符串。例如,我们可以编写一个函数模板来将任意数量的字符串合并为一个字符串:

template<class ...Args>
std::string concat(Args... args) {
	// 创建一个stringstream对象ss,用于将多个参数拼接成一个字符串。
	std::stringstream ss;
	int arr[] = { (ss << args, 0)... }; // 折叠表达式,将所有参数写入 ss 中
	return ss.str();
}

int main()
{
	// 执行下面代码
	string s = concat("hello", " ", "world", ".");
	cout << s << endl;
	return 0;
}

代码执行结果:(合并成功)

> 图片

解包元组(Tuple Unpacking)

使用可变参数模板可以方便地解包元组(Tuple)。例如,我们可以编写一个函数模板来计算元组中所有元素的和

// 解包元组(Tuple Unpacking)
template<class ...Args>
// 定义元组类
class Tuple 
{
public:
	std::tuple<Args...> values;
};

int main() {
	Tuple<int, std::string, double> tp;
	tp.values = std::make_tuple(1, "hello", 1.14);
	std::cout << std::get<0>(tp.values) << " " << std::get<1>(tp.values) << " " << std::get<2>(tp.values) << std::endl;
	return 0;
}

程序执行结果:

在这里插入图片描述


emplace_back

C++11 中 STL容器引入了 emplace 相关接口函数,它支持模板的可变参数,和 万能引用

在这里插入图片描述
在这里插入图片描述

和 push_back 的比较

emplace_back()和push_back()都是向容器的尾部添加元素的函数,比如在C++中常用的std::vector容器。它们之间的主要区别在于元素的构造方式性能方面

  1. 构造方式
  • push_back()函数接受一个已经构造好的元素作为参数,然后将该元素的副本插入到容器中。这意味着在调用push_back()之前,必须先创建一个完整的元素对象,然后将其复制。
  • emplace_back()函数接受参数,并在容器内直接构造一个新的元素。它使用传递的参数来构造元素,而不是通过复制或移动现有的元素。因此,在调用emplace_back()时,可以直接传递构造该元素所需的参数,而无需提前创建完整的元素对象。
  1. 性能:
  • emplace_back()函数接受参数,并在容器内直接构造一个新的元素。它使用传递的参数来构造元素,而不是通过复制或移动现有的元素。因此,在调用emplace_back()时,可以直接传递构造该元素所需的参数,而无需提前创建完整的元素对象。
  • 相比之下,emplace_back()直接在容器内构造元素,并避免了额外的拷贝操作。这在大量添加元素时可以带来性能上的改进,尤其是对于复制构造代价较高的对象或容器。

实例

在这里插入图片描述

可以看出在使用上两者差别不大,主要是内部的具体过程

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

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

相关文章

IT技术相关网站

OSCHINA - 中文开源技术交流社区https://www.oschina.net CSDN - 专业开发者社区https://www.csdn.netSegmentFault 思否 - 中国领先的开发者技术社区https://segmentfault.com 有穹_一个开发者的作品发布平台https://www.youqiong.net牛客网 - 找工作神器|笔试题库|面试经验|实…

完美适配小爱课程表(河南科技学院)

1.前言&#xff1a; 前文请参照我的以前的博客&#xff1a; 青果教务系统适配小爱课程表 本文代码现已开源&#xff1a; 小爱课程表适配gitee小爱课程表适配github 去年的时候试着适配了我们学校的小爱课程表&#xff0c;但是由于水平不够&#xff0c;直接把接口以及参数照搬&a…

redhawk: ir drop如何计算?effective instance resistance和min res path有什么区别?

往期文章链接: redhawk: static analysis redhawk: dynamic analysis redhawk: 什么timing window?

网络安全(黑客)自学!走进黑客的世界

谈起黑客&#xff0c;可能各位都会想到&#xff1a;盗号&#xff0c;其实不尽然&#xff1b;黑客是一群喜爱研究技术的群体&#xff0c;在黑客圈中&#xff0c;一般分为三大圈&#xff1a;娱乐圈 技术圈 职业圈。 娱乐圈&#xff1a;主要是初中生和高中生较多&#xff0c;玩网恋…

但愿世间不纷争,何惜法典卷生尘——北大团队开源法律大模型chatLaw助力法律垂直领域研究发展

今天看到一个比较热门的项目就是来自于北大研究团队刚刚开源的chatLaw法律领域数据开发构建的大模型&#xff0c;官方项目地址在这里&#xff0c;如下所示&#xff1a; 目前已经收货2.1k的star量还是很不错的了。 官方提供的学术报告文章地址在这里&#xff0c;如下所示&#…

API接口设计不合理?个人和公司都有问题

前言 在软件产品或项目开发过程中&#xff0c;往往涉及到大量API接口的开发任务。而一个接口的诞生如果是令人费解的、痛苦折磨的以及有严重后遗症的&#xff0c;究其根本原因还在于设计API接口的时候不够清晰、合理以及缺乏长远考虑。我依据多位同事的问答、实际工作的经验和…

【rsync】远程同步,快速增量备份

rsync远程同步 1.rsync远程同步1.1 rsync概述1.2 下行同步1.3 远程文件同步总结 2. 搭建rsync远程文件同步2.1 搭建rsync远程下行同步2.1.1 配置rsync服务器端&#xff08;同步源&#xff09;2.1.2 配置rsync客户机&#xff08;发起端&#xff09; 2.2 免交互配置2.3 rysnc认证…

水电站运行数据3D可视化展示方便管理运维

水电站是现代能源体系中的重要组成部分&#xff0c;对于保障国家能源安全和经济发展具有重要的意义。然而&#xff0c;由于水电站的建设和管理涉及到大量的技术和专业知识&#xff0c;许多人对水电站的运行和维护存在许多疑惑和困惑。为了解决这些问题&#xff0c;我们引入了全…

OpenShift 4 - 可观测性之 OpenShift Logging - Loki(附视频)

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在支持 OpenShift 4.12 OpenShift Logging Operator 5.7.2 Loki Operator 5.7.2 的环境中验证 文章目录 OpenShift 基于 Loki 的日志架构安装配置基于 Loki 的日志环境安装 OpenShift Logging Operator 和…

工地能耗监测系统

随着全球气候变化的影响日益严重&#xff0c;环保意识逐渐深入人心&#xff0c;绿色建筑和节能减排成为了建筑行业的热门话题。而在建筑工地中&#xff0c;能耗监测成为了一项不可或缺的任务。为了更好地实现能耗监测&#xff0c;工地能耗监测系统应运而生。本文将从以下几个方…

每日一练 | 华为认证真题练习Day72

1、Eth-Trunk两端的负载分担模式可以不一致。 A. 对 B. 错 2、如下图所示的网络&#xff0c;交换机使用机接口和路由器的子接口对&#xff0c;则以下哪个配置可以实现这种需求&#xff1f; A. interface Vlanif10 ip address 10.0.12.1 255.255.255.0 # interface Gigabit…

在Rust中使用torch------day1环境配置Yolov8推理

现在不管什么专业,貌似多多少少都得和深度学习扯上点关系才好写文章(水文章).其中最常用的深度学习框架应该是tensorflow,pytorch这些python的三方库,既然最近在学Rust那就来借机讲讲torch的Rust绑定—tch-rs 其实tch实际上是基于libtorch的封装,而不是pytorch.因此使用起来如…

云原生——什么是云原生数据库?

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 突然间&#xff0c;云原生数据库就火了。根据IDC《2021年下半…

WinForm中使用AnyCAD控件

一、添加DLL程序集 AnyCAD.Foundation.Net.dll AnyCAD.Presentation.Net.dll AnyCAD.Exchange.Net.dll 二、初始化控件 1.首先创建一个窗体 2.在窗体上放置一个Panel用来放置三维控件 3.初始化控件 完整代码如下&#xff1a; using AnyCAD.Presentation; using System; …

Generalized Category Discovery(论文翻译)

Generalized Category Discovery 摘要1.导言2.相关工作3.广义类发现3.1 我们的方法 图1.我们提出一个新的设置&#xff1a;“广义类别发现”及其解决方法。我们的设置可以简洁地描述为&#xff1a;给定一个子集具有类标签的数据集&#xff0c;对数据集中所有未标记的图像进行分…

【嵌入式Qt开发入门】如何使用Qt进行绘图——QPainter 绘图

绘图与图表在嵌入式里有的比较多&#xff0c;尤其是图表&#xff0c;我们常在股票里看到的“图表折线/曲线 图/饼状图等”都可以用 Qt 的图表来实现。绘图和图表的内容本章主要介绍绘图和图表的基本操作&#xff0c;以简单的例子呈现绘图与图表的用法&#xff0c;目的就是快速入…

抖音怎么私信发名片

抖音怎么私信发名片&#xff0c;抖音私信卡片制作教程来了&#xff0c;视频版教程#新媒体运营工具#软件#抖音消息卡片 hello&#xff0c;大家&#xff0c;我是百收网SEO&#xff0c;今天给大家说一下个人号自动回复卡片&#xff0c;相比企业号自动回复卡片&#xff0c;它的优势…

MATLAB | 终于找到了修改图例图标的方法(可以自己设计图例啦?)

讲一点扒MATLAB底裤的事情叭&#xff0c;就是之前写的有一些绘图函数&#xff0c;比如阴影柱状图&#xff0c;想要把图例里的图标进行修改让其也带着阴影&#xff0c;我采取的是直接绘制一些会检测图例框移动的阴影图标来冒充图例的图标&#xff0c;那么有没有办法真正的自定义…

如何轻松应对广泛存在开源“0Day”

跟不少安全人员讨论过一个很通俗的话题 作为网安从业者最讨厌的是什么&#xff1f; 不同的人给了很多不同的答案 有的人说&#xff1a; 但更多的人都在说&#xff1a; “零日漏洞”(zero-day)又叫零时差攻击&#xff0c;是指被发现后立即被恶意利用的安全漏洞。通俗地讲&…

QScintilla自制代码编辑器系列(1)编译库文件与运行测试例子

1.下载工程源码 我本人机器上的QT是6.4 可以下载最新的代码 https://www.riverbankcomputing.com/static/Downloads/QScintilla/2.14.0/QScintilla_src-2.14.0.zip 2. 编译生成文件 无需改动可以顺利生成库文件 3. 运行例子 1&#xff09;拷贝头文件 将整个Qsci文件夹拷…