特化为另外一个类模板:
// specialize for vector<T>
template<class T>
class Compare<vector<T> >
{
public:
static bool IsEqual(const vector<T>& lh, const vector<T>& rh)
{
if(lh.size() != rh.size()) return false;
else
{
for(int i = 0; i < lh.size(); ++i)
{
if(lh[i] != rh[i]) return false;
}
}
return true;
}
};
混合型的:
template<typename T1, typename T2>
class X {…};
template<typename T>
class X<vector<T>, int&> {…}; //至于这里怎么都把T2搞没了变成只依赖一个模板参数T了的问题,大家别着急,我来告诉你个本质的东西,把我这么三点就可以了:1.模板参数个数一致;2.只要template <…>里面有东西不是<>,比如typename T,那么特化时就得用到T;3.不进行任何对模板参数的修饰也是不行的,比如template<typename T> class<T>{…},至少你也得搞个const T之类的吧,呵呵。下面是我搞出来的几种特殊情况,它们都是正确的:
template<typename T1, typename T2>
class X {};
template<typename T>
class X<vector<T>, T&> {};
template<typename T>
class X<vector<T>, int&> {};
template<>
class X<vector<double>, int&> {};
template<typename T1, typename T2, typename T3>
class X<map<T1,T2>, T3&> {};
最后,还有一种超级牛X的,在tr1里面用以实现function的,以前我都没见过还可以这么玩的:
template<typename T>
class Y;//这是在声明一个类模板,既然声明了,以后就得按这个规矩来,在我们之前的编程(www.cppentry.com)经验里,可以重复声明一个东西没问题,但是为同一个东东重复声明出不同的东西就不可以了,因此你就不能再声明诸如template<typename T1, typename T2> class Y;这样的声明了;其实没有什么是不能声明的,既然我们可以声明变量,声明函数,声明类,那么当然我们也可以声明函数模板或者类模板的。
template<typename R, typename P1, typename P2>
class Y<R (P1, P2)> {…};//针对带两个参数,有返回值的函数类型特化,这里R (P1,P2)是定义了一种类型,该类型是一个隐式的函数指针,返回R,参数为P1和P2,这种对函数指针的定义完全等同于R (*)(P1,P2),但是前一种定义很不常见,大家一般是不会注意到这个地方的。
好了,说了不少关于类模板的特化了,下面再简要说说函数模板的特化:
函数模板的特化只能是全特化,而不能是偏特化,因此对于函数的特化就比较简单了,就是重新搞一遍就可以了,举几个例子如下:
template <class 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;
}
但是你不能这么搞:
template <>
bool mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0);
}
其实对于mymax这个模板函数的定义而言,是用一个模板参数控制了三个地方,那么你在特化的时候,就也需要用一个特定的类型修改那三处相应的地方,如果你非要返回bool,那么你只能再定义一个函数模板了:
template <class T>
bool mymax(const T t1, const T t2)
{
return t1 < t2 t2 : t1;
}
问题又来了,大家都知道函数重载是不关心返回值的,而只关心参数个数以及类型是否不一致,不一致就是重载,但是对于模板函数而言,这个规矩不再成立,因为任何与模板相关的东西都只是个架子放在那里而已,只要它符合语法规则就可以了,这些架子只是在有人要调用它们时才会发挥效力,也就是说,在编译的时候会为你搜寻合适的模板函数或者类,只要能找到就ok了,而且还要求是只找到一个,要是找到多个也不行,呵呵。
其实,对于函数而言,虽然不能偏特化,即不能再在函数名字后面像模板类一样搞个<typename T>出来,但是可以通过函数的重载(注意这里说的重载是指的模板重载,而不是普通意义的函数重载)变通的实现偏特化:
template <typename T1, typename T2>
bool mymax(T1 t1, T2 t2)
{
return t1 < t2 t2 : t1;
}
template <typename T1>
bool mymax(T1 t1, int t2)
{
return t1 < t2 t2 : t1;
}