zoukankan      html  css  js  c++  java
  • 【转】全特化/偏特化

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

        模板有两种特化,全特化和偏特化(局部特化)

        模板函数只能全特化,没有偏特化(以后可能有)。

        模板类是可以全特化和偏特化的。

        全特化,就是模板中模板参数全被指定为确定的类型。

        全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。

        偏特化,就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。

        在类型上加上const、&、*( cosnt int、int&、int*、等等)并没有产生新的类型。只是类型被修饰了。模板在编译时,可以得到这些修饰信息。

        模板的特化是非常有用的。它像一个在编译期的条件判断。当编译器在编译时找到了符合的特化实现,就会使用这个特化实现。这就叫编译器多态(或者叫静态多态)。这种东西对编写基础库是很有用的。这也就是为何c++的基础库大量使用了模板技术,而且大量使用了特化,特别是偏特化。

        在泛型中,利用特化类得到类新的特性,以便找到最适合这种特性的实现。而这一切都是在编译时完成。

  • 相关阅读:
    【Leetcode】【Easy】Remove Duplicates from Sorted List
    【Leetcode】【Easy】Pascal's Triangle II
    【Leetcode】【Easy】Pascal's Triangle
    【Leetcode】【Easy】Binary Tree Level Order Traversal II
    【Leetcode】【Easy】Binary Tree Level Order Traversal
    【Leetcode】【Easy】Maximum Depth of Binary Tree
    【Leetcode】【Easy】Minimum Depth of Binary Tree
    【Leetcode】【Easy】Balanced Binary Tree
    【Leetcode】【Easy】Symmetric Tree
    如何使用Action.Invoke()触发一个Storyboard
  • 原文地址:https://www.cnblogs.com/hbf369/p/2362800.html
Copyright © 2011-2022 走看看