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);
//first create a temporary object, then call the overloaded ()
full specialization aims to specialize some type.
for example:
this is a function for judging equality of two members
template<class T>
bool Isequal(T& p1, T& p2){
return p1 == p2;
}
But it doesn’t work for string. We need to override this special type
template<>
bool Isequal<char*> (char* p1, char* p2){
return strcmp(p1, p2) == 0;
}
- A template and its specializations should be declared in the same header file. The declarations of all templates with the same name should come first, followed by their specializations
Note that for a function template you don’t need to write <>
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;
}
//This is because the compiler can deduce from the signature int max(const int, const int) that it is a specialization of T max(const T, const T).
Note that if specialization function doesn’t have arguments. It has various interpretation. For example
template <class T>
void f(){ T d; }
template <>
void f(){ int d; }
Here the compiler does not know that f() is specialized from f<T>(), so compilation fails with:
error: no function template matches function template specialization 'f'
In this case we need to explicitly specify the "template argument":
template <class T>
void f(){ T d; }
template <>
void f<int>(){ int d; }
partial specialization
- arguments (in the number of parameters)
- range: shrink the range. For example, arbitrary type to pointer (any type becomes any pointer type)
For arguments:
Like full specialization, partial specialization provides a custom template for a set of parameters, but a partially specialized template must be instantiated further before it has a concrete signature. Note that function templates cannot be partially specialized.
template <class T1, class T2>
class A<T1, T2>{
...
};
template <class T2>
class A<int, T2>{
...
};
Function templates cannot be partially specialized; the following declaration fails to compile:
template <class T1, class T2>
void f(){}
template <class T2>
void f<int, T2>(){}
But functions can be overloaded, so declaring another function template meets the need for partial specialization:
template <class T2>
void f(){} // Note: there is no "template argument" here
In most cases, overloading function templates covers the need for partial specialization. One exception is the std namespace: std is a special namespace in which users may specialize templates but may not add templates (in fact, adding anything at all is forbidden)
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;
The point of this design is that when pointers need different handling, this partial specialization is used