• oop &&GP 模板 ---> 特化和偏特化


    OOP面向对象编程

    GP泛型编程(generic programming)

    两者的主要区别就是OOP将数据和对数据的操作放在一起,

    GP就是将数据和操作独立开来

     

    GP:   数据就是container进行存储,操作就是函数,也就是最数据操作的算法,container和algorithn都可以各自闭门造车,之间通过iteration联通就可以了

    比如说sort

    sort(begin,end,cmp)

    algorithm通过iteration操作确定范围,并通过iteration来取出contain中的数据

    大家可以看一下钱的stl六大部件中的那张六大部件的关系图

     

     

    为什么list不能使用sort(没有内置sort)

    list《int》ls

    ls.sort()错误

    sort内部的源码中cmp那里有first+(last-first)/2

    也就是对迭代器不定数量的偏移,如果想要这样操作,那么操作的数据在内存中的位置一定是连续的

    但是list存储的链表吗,链表每一个元素所占的地址不是连续的,我们在操作list的时候可以通过迭代器一个一个的进行偏移,但是不能偏移多个,因为地址不是连续,所以内部也就不能使用sort

     

    random access iterator

    所有algorithm,其内部设计元素本身的操作,无非就是比大小

     8**************************************************************************************************

    模板

    一:模板有函数模板和类模板

    类模板很常见了,我们使用的stl都需要使用类模板,类模板需要《type》去指定类型,这是为了告诉编译器类型,否则编译器没有线索去判断什么类型

    上面这张图是函数函数min,首先我们定义了stone的两个对象,之后我们使用min模板函数,这个时候编译器做了一件非常棒的事情,就是编译器对函数模板进行了实参类型的推导,编译器会看他的参数r1,找到上一行,发现是stone类型的,如果min中的T就是stone类型了,之后min要进行操作,编译器进入min后走到<的时候,首先他作用于<左边的参数,并到T类型中查看时候与<的重载,发现在stone类中确实有重载,编译器于是走到operator中,发现是按到weight比较的,于是执行

     二:成员模板

     不重要


    类模板又有特化,和偏特化,偏特化又有个数上的偏和范围上的偏

    模板特化

    有时为了需要,针对特定的类型,需要对模板进行特化,也就是所谓的特殊处理。比如有以下的一段代码:

    #include <iostream>
    using namespace std;
     
    template <class T>
    class TClass
    {
    public:
         bool Equal(const T& arg, const T& arg1);
    };
     
    template <class T>
    bool TClass<T>::Equal(const T& arg, const T& arg1)
    {
         return (arg == arg1);
    }
     
    int main()
    {
         TClass<int> obj;
         cout<<obj.Equal(2, 2)<<endl;
         cout<<obj.Equal(2, 4)<<endl;
    }

    类里面就包括一个Equal方法,用来比较两个参数是否相等;上面的代码运行没有任何问题;但是,你有没有想过,在实际开发中是万万不能这样写的,对于float类型或者double的参数,绝对不能直接使用“==”符号进行判断。所以,对于float或者double类型,我们需要进行特殊处理,处理如下:

     1 #include <iostream>
     2 using namespace std;
     3  
     4 template <class T>
     5 class Compare
     6 {
     7 public:
     8      bool IsEqual(const T& arg, const T& arg1);
     9 };
    10  
    11 // 已经不具有template的意思了,已经明确为float了
    12 template <>
    13 class Compare<float>
    14 {
    15 public:
    16      bool IsEqual(const float& arg, const float& arg1);
    17 };
    18  
    19 // 已经不具有template的意思了,已经明确为double了
    20 template <>
    21 class Compare<double>
    22 {
    23 public:
    24      bool IsEqual(const double& arg, const double& arg1);
    25 };
    26  
    27 template <class T>
    28 bool Compare<T>::IsEqual(const T& arg, const T& arg1)
    29 {
    30      cout<<"Call Compare<T>::IsEqual"<<endl;
    31      return (arg == arg1);
    32 }
    33  
    34 bool Compare<float>::IsEqual(const float& arg, const float& arg1)
    35 {
    36      cout<<"Call Compare<float>::IsEqual"<<endl;
    37      return (abs(arg - arg1) < 10e-3);
    38 }
    39  
    40 bool Compare<double>::IsEqual(const double& arg, const double& arg1)
    41 {
    42      cout<<"Call Compare<double>::IsEqual"<<endl;
    43      return (abs(arg - arg1) < 10e-6);
    44 }
    45  
    46 int main()
    47 {
    48      Compare<int> obj;
    49      Compare<float> obj1;
    50      Compare<double> obj2;
    51      cout<<obj.IsEqual(2, 2)<<endl;
    52      cout<<obj1.IsEqual(2.003, 2.002)<<endl;
    53      cout<<obj2.IsEqual(3.000002, 3.0000021)<<endl;
    54 }

    注意一个问题就是

    20 template <>
    21 class Compare<double>
    22 {
    23 public:
    24      bool IsEqual(const double& arg, const double& arg1);
    25 };


    注意对于特化一定要是带有空的<>的,注意格式的问题,和正常的模板类有很大的不用结构问题

    模板偏特化

    上面对模板的特化进行了总结。那模板的偏特化呢?所谓的偏特化是指提供另一份template定义式,而其本身仍为templatized;也就是说,针对template参数更进一步的条件限制所设计出来的一个特化版本。这种偏特化的应用在STL中是随处可见的。比如:

    
    
    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;
    };
    
    
    
    看了了么?这就是模板偏特化,与模板特化的区别在于,模板特化以后,实际上其本身已经不是templatized,而偏
    特化,仍然带有templatized。也就是说不为空的<>,<>内部仍然指明是什么具体类型,我们来看一个实际的例子:
    #include <iostream>
    using namespace std;
     
    // 一般化设计
    template <class T, class T1>
    class TestClass
    {
    public:
         TestClass()
         {
              cout<<"T, T1"<<endl;
         }
    };
     
    // 针对普通指针的偏特化设计
    template <class T, class T1>
    class TestClass<T*, T1*>
    {
    public:
         TestClass()
         {
              cout<<"T*, T1*"<<endl;
         }
    };
     
    // 针对const指针的偏特化设计
    template <class T, class T1>
    class TestClass<const T*, T1*>
    {
    public:
         TestClass()
         {
              cout<<"const T*, T1*"<<endl;
         }
    };
     
    int main()
    {
         TestClass<int, char> obj;
         TestClass<int *, char *> obj1;
         TestClass<const int *, char *> obj2;
     
         return 0;
    }

    特化与偏特化的调用顺序

    对于模板、模板的特化和模板的偏特化都存在的情况下,编译器在编译阶段进行匹配时,是如何抉择的呢?从哲学的角度来说,应该先照顾最特殊的,然后才是次特殊的,最后才是最普通的。编译器进行抉择也是尊从的这个道理

  • 相关阅读:
    IAR EWARM PRINTF/SCANF FORMATTER
    Windows Self Signed Driver
    Remove a Driver Package from the Driver Store
    CMSIS-DAP调试器
    CHM文件无法查看内容解决办法
    HRESULT 0x80131515 解决方法
    dmalloc 原文 翻译整理
    Linux错误代码
    Windows 错误代码
    调码王版本历史
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/6389046.html
Copyright © 2020-2023  润新知