C++——可变模板参数

声明:由于对可变模板参数了解资源有限,以下有些观点仅为个人参考手册实践得出的,不要被我个人的观点误导。


一.基本语法知识

1.基本知识

C++11的新特性–可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。

2.基本语法

template <class... T>
void f(T... args);

上面的可变模版参数的定义当中,省略号的作用有两个:
(1)声明一个参数包T… args,这个参数包中可以包含0到任意个模板参数;
(2)在模板定义的右边,可以将参数包展开成一个一个独立的参数。
上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难
点,即如何展开可变模版参数
可变模版参数和普通的模版参数语义是一致的,所以可以应用于函数和类,即可变模版参数函数和可变模版参数类,然而,模版函数不支持偏特化,所以可变模版参数函数和可变模版参数类展开可变模版参数的方法还不尽相同。

二.基本使用方法

1.基本演示

先来看一下简便的演示:

template<typename...T>
void fun1(T...args)
{
	cout << "参数个数为:" << sizeof...(args) << endl;//打印变参的个数
}

int main()
{
	fun1();
	fun1(1, "");
	fun1(1, 2, 3, 4);
	fun1('a', 2, "abc", " ", 'w');

	return 0;
}

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

2.参数展开

如果我们需要将参数包中的每个参数打印出来的话就需要通过一些方法了。
展开可变模版参数函数的方法一般有两种:
①通过递归函数来展开参数包。
②是通过逗号表达式来展开参数包。
(1)递归方式展开参数包
通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止函数,递归终止函数正是用来终止递归的。

//递归终结函数
void print()
{
	cout << "这里是终结函数" << endl;
}

//typename在简单的参数类型中使用
//typename...在可变参数的类型中使用
//比如下面,个人理解为:T1为普通参数类型,T2...为可变参数类型,即T2...是一个组合而不是...args
//注意可以看成两个类型,T1(普通参数)和T2...(可变参数)
template<typename T1, typename...T2>
void print(T1 head, T2...args)
{
	cout << head << endl;
	print(args...);//当参数输出完时,这个相当于print(),会调用终结函数print()
}


int main()
{
	print(1, 2, 3, 4);

	return 0;
}

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

(2)逗号表达式展开参数包
递归函数展开参数包是一种标准做法,也比较好理解,但也有一个缺点,就是必须要一个重载的递归终止函数,即必须要有一个同名的终止函数来终止递归,这样可能会感觉稍有不便。有没有一种更简单的方式呢?其实还有一种方法可以不通过递归方式来展开参数包,这种方式需要借助逗号表达式和初始化列
表。比如前面print的例子可以改成这样:

template<typename  T>
void printarg(T arg)
{
	cout << arg << endl;
}

//可变参数模板
template<typename...Args>
void expand(Args... args)
{
	int num[] = {(printarg(args), 0)...};//对每个参数都传入到printarg中
}

int main()
{
	expand(1, 2, 3, 4, 5, 6,  7);
	return 0;
}

运行结果:
在这里插入图片描述
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)打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在数组构造的过程展开参数包。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

孟小胖_H

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

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

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

打赏作者

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

抵扣说明:

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

余额充值