一、可变参函数模板
/*********************可变参数函数模板**********************/
template<typename... T> //T:一包类型 ,args: 一包形参
void myfunc(T... args)
{
cout << "可变参数 函数 模板" << endl;
cout << sizeof...(args) << endl;
cout << sizeof...(T) << endl;
}
- 注意这三个点(…)出现的位置。在具体的函数形参中,出现在了类型名的后面(Eg:T…)。但如果这个类型后面有引用,则出现在引用的后面(Eg: T&…)。具体示例如下。
template<typename T,typename... U>
void myfunc1(const T& firstarg, const U&... othetarg)
{
cout << "含有一个非变参的类型typename T,typename... U" << endl;
//cout << sizeof...(firstarg) << endl; //sizeof...只能用在一包类型或一包形参上
cout << sizeof...(othetarg) << endl;
}
函数包的展开
函数包的展开会利用与函数模板一样的同名函数,来作为终止条件,此函数需要注意的是参数为空。
递归函数的方式展开函数包,对于函数模板也有一般的形式要求。
- 带一个单独的参数;
- 后面跟一个“一包参数”;
/*********************参数包的展开(递归函数的方式展开)**********************/
//先写一个函数模板的同名函数,作为展开的终止函数,此函数 的形参要为0
void display_args()
{
cout << "执行了终止函数" << endl;
}
template<typename T,typename... U>
void display_args(const T& firstarg, const U&... otherargs)
{
cout << firstarg << endl;
display_args(otherargs...); //注意传进来的是一包形参,这里的...不能省略
}
- 因为参数是一个个被剥离,到最后一次的时候参数为空,而函数模板的参数至少为一个,当参数为空的时候会调用与函数模板同名的函数,来作为递归的终止条件。
二、可变参类模板
在类的模板中先有泛化后有特化。可变参类模板的用途一般定位为中高级应用。
/*********************可变参数类模板**********************/
//泛化版本的模板(现有泛化才有特化)
template<typename... Args>
class MyClass
{
public:
MyClass()
{
printf("MyClass::MyClass()泛化版本执行了,this = %p\r\n", this);
}
};
///*****************************当增加了一个特殊的特化类模板会被先执行(当和泛化类模板共存时)******************************************************/
//template<>
//class MyClass<>
//{
//public:
// MyClass()
// {
// printf("MyClass::MyClass()特殊的特化版本执行了,this = %p\r\n", this);
// }
//};
///***********************************************************************************/
//可变参类模板
template<typename First,typename...Others>
class MyClass<First,Others...>: private MyClass<Others...> //先执行父类的构造函数,后执行子类的构造函数
{
public:
MyClass() :m_i(0)
{
printf("MyClass::MyClass()偏特化版本执行了,this = %p, sizeof...(Others) = %d\r\n", this, sizeof...(Others));
}
//增加一个有参数的构造函数
MyClass(First parf, Others... paro):m_i(parf),MyClass<Others...>(paro...) //注意此处第二个参数的写法
{
cout << "-------------------begin--------------------" << endl;
printf("MyClass::MyClass(parf,...paro)执行了,this = %p\n", this);
cout << "m_i = " << m_i << endl;
cout << "--------------------end---------------------" << endl;
}
First m_i;
};
这是通过递归的方式展开参数包。类似于函数模板的展开,在递归继承的时候,参数为空就会停止类模板的继承,进而实例化一个泛化版本的类。具体的层次关系如下。
在类的实例化中先执行的是父类的构造函数。