类模板可以被特化:
用template<>声明一个类的时候,表示这是一个特化类。
template<class T> class Test { public: T test(T v) { cout<<"T test(T v)"<<endl; cout<<"sizeof(T) = "<<sizeof(T)<<endl; return v; } }; //Test 类模板int特化 template<> class Test<int> { public: int test(int v) { cout<<"int test(int v)"<<endl; cout<<"sizeof(int)"<<sizeof(int)<<endl; return v; } };
特化类模板的意义:
当类模板在处理某种特定类型有缺陷时, ,可以通过 可以通过
类模板的特化来克服处理这种特定类型带来的不足
eaample:函数模板特化
#include <iostream> using namespace std; template <typename T> T mymax(const T t1, const T t2) { return t1 < t2 ? t2 : t1; } template<> const char* mymax(const char* t1,const char* t2) { return (strcmp(t1,t2) < 0) ? t2 : t1; } main() { int highest = mymax(5,10); cout<<highest<<endl;//输出10 char c = mymax('a', 'z'); cout<<c<<endl;//输出z const char* p1 = "hello"; const char* p2 = "world"; const char* p = mymax(p1,p2); cout<<*p<<endl;//输出h /* 前面两个mymax都能返回正确的结果.而第三个却不能, 因为,此时mymax直接比较两个指针p1 和 p2 而不是其指向的内容. 针对这种情况,当mymax函数的参数类型为const char* 时,需要特化。 */ return 0; }
类模板的局部特化:
类模板可以被局部特化
可以指定类模板的特定实现, 并要求某些类型参数 仍然必须得模板的用户指定
template <class T, class Allocator>
class vector { // … // };
template <class Allocator>
class vector<bool, Allocator> { //…//};
这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。
函数模板的偏特化
严格的来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。
template <class T> void f(T); (a)
根据重载规则,对(a)进行重载
template < class T> void f(T*); (b)
如果将(a)称为基模板,那么(b)称为对基模板(a)的重载,而非对(a)的偏特化。
为什么需要特化, 而不重新定义新类 而不重新定义新类?
特化和重新定义新类看上去没有本质区别, ,但是如 果定义新类, 那么将变成一个类模板和一个新类
使用的时候需要考虑究竟是用类模板还是用新类而特化可以统一的方式使用类模板和特化类, 编译器自动优先选择特化类
非类型模板参数:
函数模板和类模板的函数参数可以是普通数值:
#include <iostream> using namespace std; template<typename T, int N> void func() { T array[N] = {0}; for(int i = 0; i < N; i++) { array[i] = i + 1; cout<<array[i]<<endl; } } main() { func<int,4>(); return 0; }
类型模板参数的限制:
变量不能作为模板参数
浮点数和类对象不能作为模板参数
全局指针不能作为模板参数
总之只能是字面常量值 func<int,4>;
对于模板类和特化类,编译器会自动优先选择特化类!!!