C++模板的特化与偏特化
C++模板的特化与偏特化
最近在看STL的过程中,发现自己对于模板这里的知识有所生疏,因此今日将这部分内容再做整理,以备后忘。
关于C++模板的概念这里不再赘述,默认读者已经具备基础知识。
模板的特化
先看一段代码:
#include<iostream>usingnamespacestd;template<classT>classTClass{public:boolEqual(constT&arg,constT&arg1);};template<classT>boolTClass<T>::Equal(constT&arg,constT&arg1){return(arg==arg1);}intmain(){TClass<int>obj;cout<<obj.Equal(2,2)<<endl;cout<<obj.Equal(2,4)<<endl;}
类里面就包括一个Equal方法,用来比较两个参数是否相等;上面的代码运行没有任何问题;但是,如果你传入一个float和一个double类型的参数,那么得到的结果有可能不是你想要的。所以,对于float或者double类型,我们需要进行特殊处理,处理如下:
#include<iostream>usingnamespacestd;template<classT>classCompare{public:boolIsEqual(constT&arg,constT&arg1);};//已经不具有template的意思了,已经明确为float了template<>classCompare<float>{public:boolIsEqual(constfloat&arg,constfloat&arg1);};//已经不具有template的意思了,已经明确为double了template<>classCompare<double>{public:boolIsEqual(constdouble&arg,constdouble&arg1);};template<classT>boolCompare<T>::IsEqual(constT&arg,constT&arg1){cout<<"CallCompare<T>::IsEqual"<<endl;return(arg==arg1);}boolCompare<float>::IsEqual(constfloat&arg,constfloat&arg1){cout<<"CallCompare<float>::IsEqual"<<endl;return(abs(arg-arg1)<10e-3);}boolCompare<double>::IsEqual(constdouble&arg,constdouble&arg1){cout<<"CallCompare<double>::IsEqual"<<endl;return(abs(arg-arg1)<10e-6);}intmain(){Compare<int>obj;Compare<float>obj1;Compare<double>obj2;cout<<obj.IsEqual(2,2)<<endl;cout<<obj1.IsEqual(2.003,2.002)<<endl;cout<<obj2.IsEqual(3.000002,3.0000021)<<endl;}
这样就实现了模板的特化,对于float和double的特化版本,甚至可以做一些与非特化的不一样的事情,这也是模板特化的初衷,使得特化的模板具有与非特化模板一同的行为。
模板偏特化
上面对模板的特化进行了总结。那模板的偏特化呢?所谓的偏特化是指提供另一份template定义式,而其本身仍为templatized;也就是说,针对template参数更进一步的条件限制所设计出来的一个特化版本。这种偏特化的应用在STL中是随处可见的。比如:
template<classIterator>structiterator_traits{typedeftypenameIterator::iterator_categoryiterator_category;typedeftypenameIterator::value_typevalue_type;typedeftypenameIterator::difference_typedifference_type;typedeftypenameIterator::pointerpointer;typedeftypenameIterator::referencereference;};template<classT>structiterator_traits<T*>{typedefrandom_access_iterator_tagiterator_category;typedefTvalue_type;typedefptrdiff_tdifference_type;typedefT*pointer;typedefT&reference;};template<classT>structiterator_traits<constT*>{typedefrandom_access_iterator_tagiterator_category;typedefTvalue_type;typedefptrdiff_tdifference_type;typedefconstT*pointer;typedefconstT&reference;};
模板的偏特化与模板特化的区别在于,模板特化以后,实际上其本身已经不是templatized,而偏特化,仍然带有templatized。我们来看一个实际的例子:
#include<iostream>usingnamespacestd;//一般化设计template<classT1,classT2>classTestClass{public:TestClass(){cout<<"T1,T2"<<endl;}};//针对普通指针的偏特化设计template<classT1,classT2>classTestClass<T1*,T2*>{public:TestClass(){cout<<"T1*,T2*"<<endl;}};//针对const指针的偏特化设计template<classT1,classT2>classTestClass<constT1*,T2*>{public:TestClass(){cout<<"constT1*,T2*"<<endl;}};intmain(){TestClass<int,char>obj;//T1,T2TestClass<int*,char*>obj1;//T1*,T2*TestClass<constint*,char*>obj2;//constT1*,T2*return0;}
上面的代码就实现了模板的偏特化
特化与偏特化的调用顺序
对于模板、模板的特化和模板的偏特化都存在的情况下,编译器在编译阶段进行匹配时,是如何抉择的呢?从哲学的角度来说,应该先照顾最特殊的,然后才是次特殊的,最后才是最普通的。编译器进行抉择也是尊从的这个道理。从上面的例子中,我们也可以看的出来,这就就不再举例说明。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。