可变参数模板
0、课前秀
- C++11之前,类模板和函数模板只能含有固定数量的模板参数。
- C++11允许模板定义中包含0到任意多个模板参数,写法上,在typename或class后面带上省略号
...
。
- 省略号的作用:
- 在模板定义的右边,可以将参数包展开成一个一个独立的参数。
1、可变参数模板函数
- 如果需要用参数包中的参数,则一定要将参数包展开。有两种展开参数包的方法:
- (1)通过递归的模板函数来将参数包展开
- (2)通过逗号表达式和初始化列表方式展开参数包
1.1、可变参数模板函数的定义
template <class... T>
void f(T... args)
{
cout<<sizeof...(args)<<endl; //打印变参的个数
}
f();//0
f(1,2);//2
f(1,2.5,"");//3
1.2、递归函数方式展开参数包
- 提供一个参数包展开的函数和一个递归终止函数。
- 重载的递归终止函数。
#include<iostream>
using namespace std;
//递归终止函数
void print()
{
cout<<"empty"<<endl;
}
//参数包展开函数
template<class T,class ...Args>
void print(T head, Args... rest)
{
cout<<"parameter "<<head<<endl;
print(rest...);
}
int main(void)
{
print(1,2,3,4);
return 0;
}
- 通过type_traits来展开并打印参数包 没写呢
1.3、逗号表达式和初始化列表方式展开参数包
template <class T>
void printarg(T t)
{
cout<<t<<endl;
}
template <class ...Args>
void expand(Args... args)
{
int arr[]={(printarg(args),0)...};
}
expand(1,2,3,4);
2、可变参数模板类
std::tuple
就是一个可变模板类,template <class... Types> class tuple;
- 可变参数模板类的参数包展开的方式
2.1、模板递归和特化方式展开参数包
2.2、继承方式展开参数包
//整型序列的定义
template<int...>
struct IndexSeq{};
//继承方式,开始展开参数包
template<int N, int... Indexs>
struct MakeIndexes:MakeIndexes<N-1,N-1,Indexes...>{};
//模板特化,终止展开参数包的条件
template<int... Indexs>
struct MakeIndexes<0,Indexes...>
{
typedef IndexSeq<Indexes...>type;
};
int main()
{
using T = MakeIndexes<3>::type;
cout<<typeid(T).name()<<endl;
return 0;
}
3、可变参数模板消除重复代码
ReadMe
- 20200506写完半稿,只是初步知道了语法以及应用,但具体怎么用还没有太多概念,还需要再复习一下模板类,模板函数。参考《深入应用C++11》的3.2内容。