Full specialization
template <class key>
class hash{}
template<>
class hash<char>{}
template<>
class hash<int>{}
template<>
class hash<long>{
size_t operator() (const long x){
return x;
}
}
cout<< hash<long>() (100);
//先创建一个临时对象,之后调用()重载
full specialization aims to specialize some type.
for exampl:
this is a function for judging equality of two members
template<class T>
bool Isequal(T& p1, T& p2){
return p1 == p2;
}
But it does’t work for string. We need to override this special type
template<>
bool Isequal<char*> (char* p1, char* p2){
return strcmp(p1, p2) == 0;
}
- 模板及其特例化版本应该声明在同一个头文件中。所有同名模板的声明应该放在前面,然后是这些模板的特例化版本
注意如果是函数模版,就不需要写<>
template <class T>
T max(const T lhs, const T rhs){
return lhs > rhs ? lhs : rhs;
}
template <>
int max(const int lhs, const int rhs){
return lhs > rhs ? lhs : rhs;
}
//这是因为编译器根据int max(const int, const int)的函数签名可以推导出来它是T max(const T, const T)的特化。
Note that if specialization funtion does’t have arugements. It has various interpretation. For example
template <class T>
void f(){ T d; }
template <>
void f(){ int d; }
此时编译器不知道f()是从f<T>()特化来的,编译时会有错误:
error: no function template matches function template specialization 'f'
这时我们便需要显式指定"模板实参":
template <class T>
void f(){ T d; }
template <>
void f<int>(){ int d; }
partial specialization (偏特化)
- arguments (参数的个数上)
- range: shrink the range. For example, arbitary type to pointer (任意类型的变为任意指针类型)
For arguments:
类似于全特化,偏特化也是为了给自定义一个参数集合的模板,但偏特化后的模板需要进一步的实例化才能形成确定的签名。 值得注意的是函数模板不允许偏特化,
template <class T1, class T2>
class A<T1, T2>{
...
};
template <class T2>
class A<int, T2>{
...
};
函数模板是不允许偏特化的,下面的声明会编译错:
template <class T1, class T2>
void f(){}
template <class T2>
void f<int, T2>(){}
但函数允许重载,声明另一个函数模板即可替代偏特化的需要:
template <class T2>
void f(){} // 注意:这里没有"模板实参"
多数情况下函数模板重载就可以完成函数偏特化的需要,一个例外便是std命名空间。 std是一个特殊的命名空间,用户可以特化其中的模板,但不允许添加模板(其实任何内容都是禁止添加的)
For range:
template <class T>
class A{}
template <class U>
class A<U*>{}
// we limit if the type is pointer thereby goes second class
A<string> a;
A<string*> b;
这个设计是为了如果针对指针要做不同的处理,就使用这个偏特化