一、模板参数
模板参数分为类类型形参与非类型形参
类类型形参:跟在class或者typename之后的参数类型名称
非类型形参:用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用
- 浮点数、类对象以及字符串不允许作为非类型模板参数
- 非类型的模板参数必须在编译期就能确认结果
二、模板的特化
1.概念:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化分为函数模板特化与类模板特化。
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型可能会得到一些错误的结果<例如下面代码>
template<class T>
bool IsEqual(T& left,T& right)
{
char* p1="hello";
char* p2="world";
if(IsEqual(p1,p2))
cout<<p1<<endl;
else
cout<<p2<<endl;
}
2.函数模板特化
步骤:
- 必须有一个基础的函数模板
- 关键字template后面跟<>
- 函数名后跟一对尖括号,制定需要特化的类型
- 函数形参表必须和函数模板的基础参数类型完全相同
template<>
bool IsEqual<char*>(char*& left,char*& right)
{
if(strcmp(left,right)>0)
return true;
return false;
}
但在一般情况下如果函数模板遇到不能处理或者有误的类型,为了实现简单通常都将该函数直接给出
bool IsEqual(char*& left,char*& right)
{
if(strcmp(left,right)>0)
return true;
return false;
}
3.类模板特化
3.1 全特化
概念:全特化是将模板参数列表中的所有参数都确定化
template<class T1,class T2>
class Data
{
public:
Data() {cout<<"Data<T1,T2>"<<endl;}
private:
T1 _d1;
T2 _d2;
};
template<>
class Data<int,char>
{
public:
Data() {cout<<“Data<int,char>"<<endl;}
private:
int _d1;
char _d2;
};
int main()
{
Data<int,char> d1;
Data<int ,int> d2;
}
3.2 偏特化
任何针对模板参数进行进一步条件限制设计的特化版本
- 部分特化
(将模板参数列表中的一部分参数特化)
//将第二个参数特化为int
template<class T1>
class Data<T1,int>
{
public:
Data() {cout<<"Data<T1,int>”<<endl;
private:
T1 _d1;
int _d2;
}
- 参数进一步限制
//两个参数偏特化为指针类型
template<class T1,class T2>
class Data<T1*,T2*>
{
public:
Data() {cout<<"Data<T1*,T2*>"<<endl;
private:
T1 _d1;
T2 _d2;
};
//两个参数偏特化为引用类型
template<class T1,class T2>
class Data<T1&,T2&>
{
public:
Data(const T1& d1,const T2& d2)
:_d1(d1)
,_d2(d2)
{
cout<<"Data<T1&,T2&>"<<endl;
}
private:
const T1& _d1;
const T2& _d2;
};