C++之模版的进阶
1.非类型模版参数
模版参数分类类型与非类型形形参
类型形参:出现在模版参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:用一个常亮作为类(函数)模版的一个参数,在类(函数)模版中可以将参数当成常量来使用。
template<class T,size_t N = 10>
//上面的class T即为类型形参,而size_t N = 10即为非类型形参
注意:
1.浮点数,类对象及字符串是不允许作为非类型模版参数的。
2.非类型的模版参数必须在编译器就能确认结果。
2.模版的特化
2.1概念
通常情况下,使用模版可以实现一些与类型无关的代码,但对于一些特殊类型可能会得到一些错误的结果,需要特殊处理。
下面为需要特殊化处理的例子:
template<class T>
bool less(T left,T right)
{
return left < right;
}
int main()
{
Date d1(2022,7,7);
Date d2(2022,7,8);
Date* p1 = &d1;
Date*p2 = &d2
cout << Less(p1,p2) << endl; //结果错误
return 0;
}
上述的Less可以比较,但结果是错误的,这是因为Less内部并没有比较p1和p2指向的内容而只比较了p1和p2指针的地址。
在这种情况下,就需要对模版进行特化。模版的特化也分为:函数模版特化与类模版特化
2.2 函数模版特化
函数模版的特化步骤:
1.必须先有一个基础的函数模版、
2.关键字template后面接一对空的尖括号 <>
3.函数名后面跟一对尖括号,尖括号中指定需要特化的类型。
4.函数形参表:必须要和模版函数的基础参数类型完全相同
template<class T>
bool Less(T left, T right)
{
return left < right;}
//以下就是对less模版进行特化
template<>
bool Less<Date*>(Date* left,Date* right)
{
return*left <*right;
}
int main()
int main()
{
Date d1(2022,7,7);
Date d2(2022,7,8);
Date* p1 = &d1;
Date*p2 = &d2
cout << Less(p1,p2) << endl; //调用特化之后的版本
return 0;
}
注意:一般情况下如果函数模版遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出 。
bool Less(Date* left,Date* right)
{
return *left < *right;
}
这种实现简单明了,可读性更高,所以不建议函数模版特化。
2.3 类模版特化
2.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;};void TestVector(){Data<int, int> d1;Data<int, char> d2;}
2.3.2 偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本
偏特化有以下两种表现方式:
1.部分特化
将模板参数类表中的一部分参数特化
template<class T1>
class Date<T1,int>
{
public:
Date(){cout <<"Data<T1, int>'' <<endl;}
private:
T1_d1;
int_d2;
};
2.参数更进一步的限制
偏特化不仅仅是指特化部分参数,而是针对模版参数更进一步的特化版本
例如两个参数偏特化为指针类型:
template<typename T1,typename T2>
class Data<T1*,T2*>
{
public:
Data()
{cout << "Data<T1*,T2*>" <<endl;}
private:
T1_d1;
T2_d2;
};
3.模版分离编译
3.1 什么是分离编译
一个程序由若干个源文件共同实现,而每一个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
3.2 模版的分离编译
4.模版总结
【优点】
1.增强了代码的灵活性
2.模版复用了代码,节省资源
【缺陷】
1.模版会导致代码膨胀问题
2.出现模版错误时,错误原因难以定位