模板的特化
根据C++模板(分离编译)
可以了解到使用模板可以实现一些与类型无关的代码,但是有时候遇到特殊情况,eg:指针
可能会出现一些错误。这个时候就需要模板的特化
1.函数模板特化
先写一个比较大小的模板函数
template<class T>
bool less(const T left,const Tright)
{
return left < right;
}
假设现在有一个日期类(部分代码,日期类本身已经实现运算符重载) 可以参考类和对象(三)运算符重载,初始化列表
class Date
{
private:
int _year;
int _month;
int _day;
}
Date d1(2022, 10, 1);
Date d2(2021, 2, 23);
Date* p1 = &d1;
Date* p2 = &d2;
cout << zjt::less(p1, p2) << endl;
如果此时写上述代码,比较结果会出现随机值,此时比较的是p1,p2指向的地址,而不是其指向的内容,此时就需要对模板进行特化,即:在原来模板类的基础上,针对特殊类型进行特殊化的实现方式,此时就是针对指针类型进行特化
函数模板的特化步骤:
- 必须要先有一个基础的函数模板
- 关键字template后面接一对空的尖括号<>
- 函数名后跟一对尖括号,尖括号中指定需要特化的类型
- 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
此时对上述模板函数进行特化
template<>
bool less<Date*>( Date* left, Date* right)
{
return *left < *right;
}
此时就可以正确调用了。
类模板特化
函数模板的特化只有全特化但是类模板的特化分全特化和半特化(也叫偏特化)
偏特化不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
非类型模板参数
模板参数分类型形参与非类型形参
template<class T> template <typename T>
类型形参:
用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用
template<class T,size_t N = 10>
此时在类中将N当作常数使用
注意:
1.浮点数,类对象以及字符串是不允许作为非类型模板参数的
2.非类型的模板参数必须在编译器就能确定
array 也是一种容器 (C++11新增 封装过的原生数组)根据官网的源代码可以看到,其第二个参数就是非类型模板参数。
根据其解释可以发现:
它是一个固定大小的容器,相当于就是一个固定大小的数组。
array对比原生数组,优势就是能严格检查越界,数组的越界是抽查,不是很靠谱。