C++模板的特化 (一)

2014-11-24 08:38:14 · 作者: · 浏览: 3
对模板特化的理解:
特化整体上分为全特化和偏特化,这一点大家都没有什么置疑,但是细分它们各包括哪几种状态就很难界定了,而且很多权威的书上都不一致,管它呢,反正我们能会用各种特化就可以了。
下面就谈谈我个人对特化的划分和定义:
所谓特化,就是将泛型的东东搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。
这是网上某个人的一些看法:
模板有两种特化,全特化和偏特化(局部特化)
模板函数只能全特化,没有偏特化(以后可能有)。
模板类是可以全特化和偏特化的。
全特化,就是模板中模板参数全被指定为确定的类型。
全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。
偏特化,就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。
在类型上加上const、&、*( cosnt int、int&、int*、等等)并没有产生新的类型。只是类型被修饰了。模板在编译时,可以得到这些修饰信息。
我个人也比较赞同这位仁兄的划分,全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现,貌似在我的这种理解下,全特化的东西不论是类还是函数都有这样的特点,template <>然后是完全和模板类型没有一点关系的类实现或者函数定义,如果你要说,都完全确定下来了,那还搞什么模板呀,直接定义不就完事了?但是很多时候,我们既需要一个模板能应对各种情形,又需要它对于某个特定的类型(比如bool)有着特别的处理,这中情形下就是需要的了。
既然刚才提到了全特化的标志,那么再说说其他一些共性的东西:
一个特化的模板类的标志:在定义类实现时加上了<>,比如class A;而在定义一个模板类的时候,class A后面是没有<>的
全特化的标志:template <>然后是完全和模板类型没有一点关系的类实现或者函数定义
偏特化的标志:template ,就是说还剩下点东西,不像全特化<>整得那么彻底
首先推荐两个不错的网址:
http://www.cnblogs.com/cutepig/archive/2009/02/12/1389479.html
http://read.newbooks.com.cn/info/175115.html
先说类模板的特化吧:
谁都没的说的全特化:
// general version
template
class Compare
{
public:
static bool IsEqual(const T& lh, const T& rh)
{
return lh == rh;
}
};
// specialize for float
template<>
class Compare
{
public:
static bool IsEqual(const float& lh, const float& rh)
{
return abs(lh - rh) < 10e-3;
}
};
谁都没的说的偏特化:
template
class A
{
}
template
class A
{
}
接下来的特化种类,到底划归到全特化还是偏特化,你自己看着办吧,不过大致就以下这些了,逃不出我们的手掌心了:
特化为引用,指针类型:
// specialize for T*
template
class Compare
{
public:
static bool IsEqual(const T* lh, const T* rh)
{
return Compare::IsEqual(*lh, *rh);
}
};
特化为另外一个类模板:
// specialize for vector
template
class Compare >
{
public:
static bool IsEqual(const vector& lh, const vector& 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
class X {...};
template
class X, int&> {...}; //至于这里怎么都把T2搞没了变成只依赖一个模板参数T了的问题,大家别着急,我来告诉你个本质的东西,把我这么三点就可以了:1.模板参数个数一致;2.只要template <...>里面有东西不是<>,比如typename T,那么特化时就得用到T;3.不进行任何对模板参数的修饰也是不行的,比如template class{...},至少你也得搞个const T之类的吧,呵呵。下面是我搞出来的几种特殊情况,它们都是正确的:
template
class X {};
template
class X, T&> {};
template
class X, int&> {};
template<>
class X, int&> {};
template
class X, T3&> {};
最后,还有一种超级牛X的,在tr1里面用以实现function的,以前我都没见过还可以这么玩的:
template
class Y;//这是在声明一个类模板,既然声明了,以后就得按这个规矩来,在我们之前的 编程经验里,可以重复声明一个东西没问题,但是为同一个东东重复声明出不同的东西就不可以了,因此你就不能再声明诸如template class Y;这样的声明了;其实没有什么是不能声明的,既然我们可以声明变量,声明函数,声明类,那么当然我们也可以声明函数模板或者类模板的。
template
class Y {...};//针对带两个参数,有返回值的函数类型特化,这里R (P1,P2)是定义了一种类型,该类型是一个隐式的函数指针,返回R,参数为P1和P2,这种对函数指针的定义完全等同于R (*)(P1,P2),但是前一种定义很不常见,大家一般是不会注意到这个地方的。
好了,说了不少关于类模板的特化了,下面再简要说说函数模板的特化:
函数模板的特化只能是全特化,而不能是偏特化,因此对于函数的特化就比较简单了,就是重新搞一遍就可以了,举几个例子如下:
template
T mymax(const T t1, const T t2)
{
return t1 < t2 t2 : t1;
}
template <>
const char* mymax(c