【C++11】可变参数模板

news/2024/10/31 3:19:01/

文章目录


C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象,使用起来需要一定的技巧,所以这块还是比较晦涩的。

下面就是一个基本可变参数的函数模板:

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。

如何获取可变参数的个数?

利用sizeof…(可变参数包名称)计算包的大小

#include<iostream>
using namespace std;
template <class ...Args>//可变参数模板
void ShowList(Args... args)
{cout << sizeof...(args) << endl;//这里用sizeof
}
int main()
{ShowList();ShowList('x');ShowList('x', 'y');ShowList('x', 1);return 0;
}

运行结果:
在这里插入图片描述

如何解析出可变参数包?

递归思维推导——代码如下:

#include<string>
#include<iostream>
using namespace std;
//递归终止函数
void ShowList()
{cout << endl;
}
template <class T, class ...Args>//可变参数模板
void ShowList(const T& val, Args... args)
{cout << val << " ";ShowList(args...);
}
int main()
{ShowList();ShowList('x');ShowList('x', 'y');ShowList('x', 1);ShowList(1, 'A', std::string("sort"));return 0;
}

运行结果:
在这里插入图片描述
解析:
第一个ShowList函数没有传参数,而我们又自己实现了ShowList(),所以编译器直接去调用这个函数,不会走模板,所以什么都没有打印;第二个,函数只传递了char字符,通过可变参数模板的推导,T为char类型,而可变参数包为0,注意可变参数包可以包含了0到N(N>=0)个模版参数,所以只打印了’x’,打印之后的下一句代码又递归调用了自己,由于这时编译器推导出来的可变参数为0,所以会去调用我们自己实现的无参的ShowList函数,打印换行;然后我们再以最后一句代码为例,第一层函数,T为int类型,val为1,打印1,可变参数包的大小为2,,包含’A’,“sort”,然后递归调用自己来到第2层,T为char,val为’A’,可变参数包大小为1,包含"sort",打印出’A’后,递归调用自己,打印出"sort",完毕之后,可变参数包的大小这就为0了,最后调用我们自己实现的无参函数打印换行。over!
在这里插入图片描述

但是我们看到STL中的函数用到可变参数包,参数是这样写的:
在这里插入图片描述
那是因为。。。不一样的写法罢了,看看下面的代码,你们应该秒懂:

template <class ...Args>//可变参数模板
void ShowList(Args... args)//多来一层函数接口
{_ShowList(args...);
}

逗号表达式展开参数包

这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg
不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式
实现的关键是逗号表达式
。我们知道逗号表达式会按顺序执行逗号前面的表达式。expand函数中的逗号表达式:(printarg(args), 0),也是按照这个执行顺序,先执行printarg(args),再得到逗号表达式的结果0。同时还用到了C++11的另外一个特性——初始化列表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)…}将会展开成((printarg(arg1),0),(printarg(arg2),0), (printarg(arg3),0), etc… ),最终会创建一个元素值都为0的数组int arr[sizeof…(Args)]。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)打印出参数,只是逗号表达式的结果是最后一个值,即0。也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在数组构造的过程展开参数包。

#include<string>
#include<iostream>
using namespace std;template<class T>
void PrintArg(T t)//不是递归终止函数,不存在递归,是一个处理参数包中每一个参数的函数
{cout << t << " ";
}template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args),0)... };cout << endl;
}int main()
{ShowList(1, 'A', string("sort"));return 0;
}

STL容器中的empalce相关接口函数:

vector/emplace_back
list/emplace_back

template <class... Args>
void emplace_back (Args&&... args);

首先我们看到的emplace系列的接口,支持模板的可变参数,并且万能引用(注意模板中的是万能引用,不叫右值引用)。那么相对insert和emplace系列接口的优势到底在哪里呢?

int main()
{std::list< std::pair<int, char> > mylist;// emplace_back支持可变参数,拿到构建pair对象的参数后自己去创建对象// 那么在这里我们可以看到除了用法上,和push_back没什么太大的区别mylist.emplace_back(10, 'a');mylist.emplace_back(20, 'b');mylist.emplace_back(make_pair(30, 'c'));mylist.push_back(make_pair(40, 'd'));mylist.push_back({ 50, 'e' });for (auto e : mylist)cout << e.first << ":" << e.second << endl;return 0;
}

下面我们试一下带有拷贝构造和移动构造的string,我们会发现其实差别也不到,emplace_back是直接构造,push_back是先构造,再移动构造。

int main()
{std::list< std::pair<int, zxn::string> > mylist;mylist.emplace_back(10, "sort");mylist.emplace_back(make_pair(20, "sort"));mylist.push_back(make_pair(30, "sort"));mylist.push_back({ 40, "sort"});return 0;
}

在这里插入图片描述

我们再插入日期类试试:
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/news/203907.html

相关文章

ADS8688驱动(FPGA)

ADS8688 为 16 位采样芯片&#xff0c;最大采样范围 − 10.24 V ∼ 10.24 V -10.24V\sim10.24V −10.24V∼10.24V &#xff0c;最大采样率 500 k S P S 500 kSPS 500kSPS&#xff0c;8 采样通道&#xff0c;每个通道都可支持双极性 10.24 V \pm 10.24V 10.24V、 5.12 V \…

认识微型计算机系统结构实践报告,认识微机的主要部件实训报告.doc

认识微机的主要部件实训报告.doc 1 实训 2 认识微机的主要部件实训报告 实训内容 1&#xff0e;认识CPU、主板、内存条&#xff0c;了解主要技术指标。 2&#xff0e;认识硬盘、软盘等存储设备&#xff0c;了解主要技术指标。 3&#xff0e;认识键盘、鼠标、显卡、显示器等输入…

.NET Framework 中的字符编码

字符是可以通过多种不同方式表示的抽象实体。 字符编码是一个支持字符集中的每个字符进行配对值表示该字符的系统。 例如&#xff0c;摩尔斯电码是一种为罗马字母表中的每个字符与点的模式和短划线适用于在电报线路中传输的字符编码。 计算机的字符编码对一个支持字符集中的每个…

初级hifi

要听好听的音乐真是一个环节差了都不行啊。我的耳机是hd650和hd800&#xff0c;听了3个版本的神秘园的Dawn Of A New Century 新世纪的曙光&#xff0c;明显能感觉出不同版本的好坏&#xff0c;所以同样的音乐&#xff0c;cd不同差异可能很大。另外&#xff0c;用foobar和adobe…

CPU发展历程!

机顶盒核心部件 &#xff0d;&#xff0d;&#xff0d;CPU发展历程&#xff01; 在盒子界打滚以来&#xff0c;只是看到、听到各厂家CPU不断升级换代&#xff0c;宣称这个盒子能整4K、 能播超高清和硬解H.265什么的。实际上…却是无力应证。网络上&#xff0c;关于这方面的帖…

adpcm 解码音量小_音质提升不只是一点点HiFi捆绑利器aune BU1便携解码耳放评测

烧友&#xff1a;phoexi 香港展的时候路过aune展位&#xff0c;看到一个金色的小机器&#xff0c;我还以为是失传已久的限量版B1ltd。走近一看玻璃窗和B1不一样&#xff0c;才发现这是传说中的新品便携解码耳放BU1。 BU1做工相当好&#xff0c;比B1s好&#xff0c;外壳的拉丝工…

解码resources时里面是空的_【汛情手记】要干不要水,从一款单4499解码衍生的臆想...

春风不度玉门关&#xff0c;又见才子伴乐谈。 2020确实不是一个太平的年份&#xff0c;才别疫情&#xff0c;又遇汛清&#xff0c;最近长江沿线城市水灾不断&#xff0c;我所在的城市启动了一级响应&#xff0c;作为预备役非战斗人员&#xff0c;才子已经被指派上前线驻点巡堤&…

pcm5102a解码芯片音质评测_精品推荐:用家票选TOP 30款最佳便携式解码耳放(中)...

下面是国外知名网站《Headfonics.com》用家票选的30款最佳便携式解码耳放,供您选购参考!本篇为中篇。 十一、ALO Audio Rx耳放 查看 ALO Audio Rx耳放 评测>> 目前该产品有“HIFI说影音城”商家在售,点击查看>> 口碑评说: “Rx是ALO一支复古的耳放。这次ALO一反…