首先明确一点,有模板的特例化,就必须得先有原模板。
什么是完全特例化
这里直接举一个例子。
首先写一个函数模板,这个函数应该能够比较整型数,并且应该按照字典序大小比较字符串,但是本题如果直接调用compare("aaa", "bbb")
,有可能是比较字符串内容所在地址的大小,这样就不符合预期了:
template<typename T>
bool compare (T a, T b) {
cout << "template compare" << endl;
return a > b;
}
int main () {
compare(10, 20); //实参推演为整型
return 0;
}
template
bool compare (T a, T b) {
cout << “template compare” << endl;
return a > b;
}
所以我们应该为字符串特意写一个模板类型,这就叫模板的完全特例化
template<typename T>
bool compare (T a, T b) {
cout << "template compare" << endl;
return a > b;
}
template<>
bool compare<const char*> (const char *a, const char *b) {
cout << "compare<const char*>" << endl;
return strcmp(a, b) > 0;
}
int main () {
compare(10, 20); //实参推演为整型
//应该推演出const char*,但是其实比较的是a和b地址的大小
compare("aaa", "bbb");
return 0;
}
什么是非完全特例化
见如下代码:
在本例中,我们对指针类型进行了非完全特例化,因为有可能在调用这个Vector模板类的时候,我们不知道具体的数据结构,只知道是一个指针,这样非完全特例化就派上用场了。
template<typename T>
class Vector {
public:
Vector() {cout << "Call Vector template init" << endl; }
};
//下面这个是对char*类型提供的完全特例化版本
template<>
class Vector<char*> {
public:
Vector() {cout << "Call Vector<char*> init" << endl; }
};
//下面是对指针类型提供的部分特例化版本(这里的部分指的是,我们只知道是个指针具体是什么不知道)
template<typename Ty>
class Vector<Ty*> {
public:
Vector() {cout << "Call Vector<Ty*> init" << endl; }
};
int main () {
Vector<int> vec1;
Vector<char*> vec2;
Vector<int*> vec3;
return 0;
}
⭐️完全特例化和非完全特例化小总结
从上面例子可以看出,对于某个类型而言,如果该模板有完全特例化版本,那就用完全特例化,如果有部分特例化版本那就用部分特例化,如果都没有,就用原模板。