C++模板的特化
对模板特化的理解:特化整体上分为全特化和偏特化,这一点大家都没有什么置疑,但是细分它们各包括哪几种状态就很难界定了,而且很多权威的书上都不一致,管它呢,反正我们能会用各种特化就可以了。下面就谈谈我个人对特化的划分和定义:所谓特化,就是将泛型的东东搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。这是网上某个人的一些看法:模板有两种特化,全特化和偏特化(局部特化)模板函数只能全特化,没有偏特化(以后可能有)。模板类是可以全特化和偏特化的。全特化,就是模板中模板参数全被指定为确定的类型。全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。偏特化,就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。在类型上加上const、&、*( cosnt int、int&、int*、等等)并没有产生新的类型。只是类型被修饰了。模板在编译时,可以得到这些修饰信息。我个人也比较赞同这位仁兄的划分,全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现,貌似在我的这种理解下,全特化的东西不论是类还是函数都有这样的特点,template <>然后是完全和模板类型没有一点关系的类实现或者函数定义,如果你要说,都完全确定下来了,那还搞什么模板呀,直接定义不就完事了?但是很多时候,我们既需要一个模板能应对各种情形,又需要它对于某个特定的类型(比如bool)有着特别的处理,这中情形下就是需要的了。既然刚才提到了全特化的标志,那么再说说其他一些共性的东西:一个特化的模板类的标志:在定义类实现时加上了<>,比如class A<int, T>;而在定义一个模板类的时候,class A后面是没有<>的全特化的标志:template <>然后是完全和模板类型没有一点关系的类实现或者函数定义偏特化的标志:template <typename T.....>,就是说还剩下点东西,不像全特化<>整得那么彻底首先推荐两个不错的网址:http://www.cnblogs.com/cutepig/archive/2009/02/12/1389479.htmlhttp://read.newbooks.com.cn/info/175115.html先说类模板的特化吧:谁都没的说的全特化:// general versiontemplate<class T>class Compare{public:static bool IsEqual(const T& lh, const T& rh){return lh == rh;}};// specialize for floattemplate<>class Compare<float>{public:static bool IsEqual(const float& lh, const float& rh){return abs(lh - rh) < 10e-3;}};谁都没的说的偏特化:template<class T1, class T2>class A{}template<class T1>class A<T1, int>{}接下来的特化种类,到底划归到全特化还是偏特化,你自己看着办吧,不过大致就以下这些了,逃不出我们的手掌心了:特化为引用,指针类型:// specialize for T*template<class T>class Compare<T*>{public:static bool IsEqual(const T* lh, const T* rh){return Compare<T>::IsEqual(*lh, *rh);}};特化为另外一个类模板:// 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;//这是在声明一个类模板,既然声明了,以后就得按这个规矩来,在我们之前的编程经验里,可以重复声明一个东西没问题,但是为同一个东东重复声明出不同的东西就不可以了,因此你就不能再声明诸如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;}问题又来了,大家都知道函数重载是不关心返回值的,而只关心参数个数以及类型是否不一致,不一致就是重载,但是对于模板函数而言,这个规矩不再成立,因为任何与模板相关的东西都只是个架子放在那里而已,只要它符合语法规则就可以了,这些架子只是在有人要调用它们时才补充:软件开发 , C++ ,
上一个:模板的全特化与偏特化
下一个:Floyd(最短路径问题)
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊