一、模板参数包括三种:
(1)类型参数;
(2)非类型参数;
(3)模板的模板参数(意思是参数本身是个模板);
1. 类型参数
template<typename T>
void func(T first, T second)
{
cout<<"not const one"<<endl;
cout<<"typeof first is: "<<typeid(first).name()<<", typeof second is: "<<typeid(second).name()<<endl;
return ;
}
这里的T就是个类型参数;
2. 非类型参数
template<typename T, int N = 5>
class Base
{
public:
void func()
{
T array[N];
cout<<"sizeof(array) = "<<sizeof(array)<<endl;
return ;
}
};
int main()
{
Base<int> b;
b.func();
return 0;
}
非类型参数可以是:
(1)整型或者枚举型;
(2)指针类型;
(3)引用类型;
3. 模板的模板参数
意思就是模板参数是个模板;
template<template<typename T, typename A = Myallocator> class Container>
class Adaptation
{
//...
};
模板的模板参数就是
class Container,模板的模板参数的参数就是T和A,也就是模板的模板参数的参数也可以具有缺省模板实参;
模板的模板参数的参数只能被自身其他参数的声明使用;
通常模板的模板参数的参数在后面不会用到,所以上面的模板类也可以写为:
template<template<typename , typename = Myallocator> class Container>
class Adaptation
{
...
};
在匹配模板的模板参数时,模板的模板实参的缺省模板实参将不会被考虑;解释如下:
template <typename T1, typename T2, template<typename> class container>
class Relation
{
public:
container<T1> c1;
container<T2> c2;
};
int main()
{
Relation<int, double, std::list> rel;
}
这里list是有两个参数的,
template < class T, class Alloc = allocator<T> > class list;
在实参匹配的过程中,list的缺省模板实参被忽略,所以就导致container和List的模板参数列表不匹配;
二、模板实参
(1)显示模板实参:紧跟在模板名称后面,在一对尖括号里的显示模板实参值。所组成的整体称为template-id。
(2)注入式类名称:
(3)缺省模板实参:当所有模板参数都有缺省值时,也要保留尖括号;
(4)实参演绎:不显示指定函数模板实参,在函数的调用语句中,根据函数调用实参的类型来推导出函数模板实参;
对于函数的返回值,是得不到推导的机会的,所以最好把其放在模板参数的开始,在使用时,为其提供显示模板实参,后面的参数可以通过实参演绎获得;
template<typename T, int N = 5>
class Base
{
public:
void func()
{
T array[N];
cout<<"sizeof(array) = "<<sizeof(array)<<endl;
return ;
}
};
int main()
{
Base<int> b;
b.func();
return 0;
}
这里
Base<int> b; 就是模板实参;
template<typename T, int N = 5>,这里N = 5是默认实参;