C++_可变参数模板

       

目录

1、可变参数模板的用法

2、参数包展开

2.1 递归方式展开

2.2 逗号表达式形式展开 

3、参数包的大小

结语 


前言:

        C++11引入了可变参数模板,他的作用是可以让创建的函数模板或者类模板的模板参数可以接收任意数量参数,在C++11前,只能手写固定数量个模板参数,并且只能接收与之对应数量的参数,有了可变参数模板后,代码就变得更加的灵活了。

1、可变参数模板的用法

        可变参数必须是搭配着模板使用的,具体写法如下:

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以接收多个实参。
template <class ...Args>
void ShowList(Args... args)
{}

         可以发现,可变参数模板的写法非常特殊,需要先创建一个模板,并且该模板的参数需要用三个点:’...‘来声明,如上代码,Args就成了一个模板参数包,再用该模板参数去作为args的类型,则args为函数形参参数包,这一类args就可以接收多个实参了(可接收0~n个参数,n>=0)。

2、参数包展开

        虽然args可以接收多个参数,但是无法直接读取这些参数的内容,因此最重要的一步是将args参数包中的内容展开并读取到里面的数据,这也是可变参数模板的一个难点——参数包的展开。

2.1 递归方式展开

        采用类似于递归的方式进行参数包的展开(注意调用参数包的写法),具体代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

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...);//当只剩下一个参数时会走第一个ShowList
}
int main()
{
	ShowList(1, 'A', string("hello world"));
	return 0;
}

         运行结果:

        具体流程如下图所示:

2.2 逗号表达式形式展开 

        除了上述的递归方式,还可以把参数包放到一个数组里, 写法如下:

#define _CRT_SECURE_NO_WARNINGS 1

#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', "hello world");
	return 0;
}

        运行结果:

        具体过程:{(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... ),因为是逗号表达式,所以先执行逗号前面的内容,即(printarg(args),因此会先去调用函数printarg,也就是说在构造arr数组的过程就将参数包展开了,并且该数组arr的全部元素都是0(因为逗号表达式的结果取最后一个),该数组的大小是参数包的大小,并且参数包中有多少个参数就有多少个元素0,数组的最终结果应该是:arr[sizeof...(args)] = {0,0,0..}。

3、参数包的大小

         参数包的大小即该参数包里总共有多少个参数,与参数的类型无关,只与个数有关,示例代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

template<class ...Args>
void func(Args... args)
{
	cout << __FUNCTION__ << ":" << sizeof...(args) << endl;//注意求参数包的写法
}

int main()
{
	func();//一个参数没有则参数包为0
	func('A', "hello world");//两个参数,参数包为2
	func(1,'A',"hello world");//三个参数,参数包为3
	return 0;
}

        运行结果:

        此处注意计算参数包的写法。 

结语 

        以上就是关于可变参数模板的讲解,比如当我们不知道要传多少个参数给到模板时,这类场景下就可以使用可变参数模板了,该模板参数可以接收任意数量个参数,然后再用特殊的写法将其内容展开就可以读取到参数包里的数据了。

        最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!! 

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安权_code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值