p23specialization


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;

这个设计是为了如果针对指针要做不同的处理,就使用这个偏特化


Author: Moule Lin
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Moule Lin !
  TOC