C++类模板的三种特化

    技术2022-05-20  51

    说起C++的模板及模板特化, 相信很多人都很熟悉 ,但是说到模板特化的几种类型,相信了解的人就不是很多。我这里归纳了针对一个模板参数的类模板特化的几种类型, 一是特化为绝对类型; 二是特化为引用,指针类型;三是特化为另外一个类模板。

     这里用一个简单的例子来说明这三种情况:

    //  general version template < class  T > class  Compare{ public :     static   bool  IsEqual( const  T &  lh,  const  T &  rh)    {         return  lh  ==  rh;    }};

    这是一个用于比较的类模板,里面可以有多种用于比较的函数, 以IsEqual为例。 一、特化为绝对类型也就是说直接为某个特定类型做特化,这是我们最常见的一种特化方式, 如特化为float, double等

    //  specialize for float template <> class  Compare < float > { public :     static   bool  IsEqual( const   float &  lh,  const   float &  rh)    {         return  abs(lh  -  rh)  <  10e - 3 ;    }}; //  specialize for double template <> class  Compare < double > { public :     static   bool  IsEqual( const   double &  lh,  const   double &  rh)    {         return  abs(lh  -  rh)  <  10e - 6 ;    }};

     二、特化为引用,指针类型这种特化我最初是在stl源码的的iterator_traits特化中发现的, 如下:

    template  < class  _Iterator > struct  iterator_traits {  typedef typename _Iterator::iterator_category iterator_category;  typedef typename _Iterator::value_type        value_type;  typedef typename _Iterator::difference_type   difference_type;  typedef typename _Iterator::pointer           pointer;  typedef typename _Iterator::reference         reference;}; //  specialize for _Tp* template  < class  _Tp > struct  iterator_traits < _Tp *>  {  typedef random_access_iterator_tag iterator_category;  typedef _Tp                         value_type;  typedef ptrdiff_t                   difference_type;  typedef _Tp *                         pointer;  typedef _Tp &                         reference;}; //  specialize for const _Tp* template  < class  _Tp > struct  iterator_traits < const  _Tp *>  {  typedef random_access_iterator_tag iterator_category;  typedef _Tp                         value_type;  typedef ptrdiff_t                   difference_type;  typedef  const  _Tp *                   pointer;  typedef  const  _Tp &                   reference;};

     

     当然,除了T*, 我们也可以将T特化为 const T*, T&, const T&等,以下还是以T*为例:

    //  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);    }};

    这种特化其实是就不是一种绝对的特化, 它只是对类型做了某些限定,但仍然保留了其一定的模板性,这种特化给我们提供了极大的方便, 如这里, 我们就不需要对int*, float*, double*等等类型分别做特化了。

    三、特化为另外一个类模板

    这其实是第二种方式的扩展,其实也是对类型做了某种限定,而不是绝对化为某个具体类型,如下:

    //  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 ;    }};

    这就把IsEqual的参数限定为一种vector类型, 但具体是vector<int>还是vector<float>, 我们可以不关心, 因为对于这两种类型,我们的处理方式是一样的,我们可以把这种方式称为“半特化”。

    当然, 我们可以将其“半特化”为任何我们自定义的模板类类型:

    //  specialize for any template class type template  < class  T1 >   struct  SpecializedType{    T1 x1;    T1 x2;};template  < class  T > class  Compare < SpecializedType < T >   > { public :     static   bool  IsEqual( const  SpecializedType < T >&  lh,  const  SpecializedType < T >&  rh)    {         return  Compare < T > ::IsEqual(lh.x1  +  lh.x2, rh.x1  +  rh.x2);    }};

     这就是三种类型的模板特化, 我们可以这么使用这个Compare类:

        //  int      int  i1  =   10 ;     int  i2  =   10 ;     bool  r1  =  Compare < int > ::IsEqual(i1, i2);     //  float      float  f1  =   10 ;     float  f2  =   10 ;     bool  r2  =  Compare < float > ::IsEqual(f1, f2);     //  double      double  d1  =   10 ;     double  d2  =   10 ;     bool  r3  =  Compare < double > ::IsEqual(d1, d2);     //  pointer      int *  p1  =   & i1;     int *  p2  =   & i2;     bool  r4  =  Compare < int *> ::IsEqual(p1, p2);     //  vector<T>     vector < int >  v1;    v1.push_back( 1 );    v1.push_back( 2 );    vector < int >  v2;    v2.push_back( 1 );    v2.push_back( 2 );     bool  r5  =  Compare < vector < int >   > ::IsEqual(v1, v2);     //  custom template class      SpecializedType < float >  s1  =  { 10.1f , 10.2f };    SpecializedType < float >  s2  =  { 10.3f , 10.0f };     bool  r6  =  Compare < SpecializedType < float >   > ::IsEqual(s1, s2);     转自:http://blog.csdn.net/prochsh/archive/2008/09/18/2948174.aspx


    最新回复(0)