【C++闯关笔记】模板的特化
系列文章目录
上篇文章:【C++闯关笔记】STL:deque与priority_queue的学习和使用-CSDN博客
文章目录
目录
系列文章目录
文章目录
前言
一、非类型模板参数介绍
二、模板特化
1.函数模板特化
2.类模板特化
1)全特化
2)偏特化
总结
前言
在【C++闯关笔记】封装②:友元与模板_c++封装,友元-CSDN博客 一文中,我们讨论了函数模板的基本用法,并明确了模板是泛型编程的基础。
本文在模板的基础用法之上,介绍什么是模板的特化。
一、非类型模板参数介绍
模板参数分 类类型形参 与非类型形参。
在一些C++教材上一般只介绍类类型模板参数,而非类型模板参数却少有提及。
类类型形参:即出现在模板参数列表中,跟在class或者typename之类的参数类型名称。如下文代码中的 T 类型。
template<typename T>void swap( T& left, T& right){T temp = left;left = right;right = temp;}
非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。如下文代码中的 size_t N 。
//一个静态定长数组
template<class T,size_t N =10>
class Array
{
public:T& operator[](size_t pos){ return _array[pos];}bool empty(){return _size == 0;}size_t size()const{return _size;}
private:T _array[N];size_t _size;
};
非类型模板参数常与类类型模板参数一起使用,但非类型模板参数有些细节需要注意:
浮点数、类对象以及字符串是不能作为非类型模板参数的。
二、模板特化
模板可以实现不同类型的数据使用同一套代码实例化,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理。
比如下面代码中,将地址传给函数Less就会造成错误。
template<class T>
bool Less(T left, T right)
{return left < right;
}int main()
{int a = 1,b = 2;Less(a,b);//正确Less(&a,&b);//错误return 0;
}
此时就需要特殊处理。
1.函数模板特化
特化,翻译一下就是特殊的实例化,即在原模板类的基础上,针对特殊类型所进行特殊化的实现方 式。
特化的步骤:
①. 已经有了一个基础的模板;
②. 关键字template后面接一对空的尖括号<>
③. 函数名/类名后跟一对尖括号,尖括号中指定需要特化的类型。
④. 函数形参表: 必须要和模板函数的基础参数类型完全相同。
就拿上面的Less模板函数,特化处理指针作为示例:
// 函数模板 -- 参数匹配template<class T>bool Less(T left, T right){return left < right;}// 对Less函数模板进行特化template<>bool Less<Date*>(Date* left, Date* right){return *left < *right;}
2.类模板特化
1)全特化
全特化:将模板参数列表中所有的参数都确定化。
//类模板
template<class T1,class T2>
class Temp
{
public:Temp(){cout << "template<class T1,class T2>" << endl;}
};//全特化
template<>
class Temp<int, double>
{
public:Temp(){cout << "Temp<int, double>" << endl;}
};
2)偏特化
偏特化又分为两个部分,一是由如template<class T, int>的部分特化。
部分特化
template<class T1,class T2>
class Temp
{
public:Temp(){cout << "template<class T1,class T2>" << endl;}
};template<class T1>
class Temp<T1,int>
{
public:Temp(){cout << "Temp<T1,int>" << endl;}
};
二是针对模板参数的特定条件限制所设计出来的特化版本,如对指针类型的特化。
template<class T1,class T2>
class Temp
{
public:Temp(){cout << "template<class T1,class T2>" << endl;}
};//偏特化(特殊特化)
template<typename T1, typename T2>
class Temp<T1*, T2*>
{
public:Temp(){cout << "Temp<T1,int>" << endl;}
};
细节注意
函数模板或者类模板的定义与声明最好在一个文件中,将声明和定义放到一个文件 "xxx.hpp"或者”“xxx.h” ,否则会出现链接错误!
总结
最后对模板做个总结:
【优点】
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
2. 增强了代码的灵活性
【缺陷】
1. 模板会导致代码膨胀问题,也会导致编译时间变长
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误