zoukankan      html  css  js  c++  java
  • traits编程技巧

    template<class T>
    class iterator//表示迭代器针对泛型iterator_traits时的底层代码
    {
        typedef T value_type;
    }; 
    
    template<class Iterator>
    struct iterator_traits//泛化iterator_traits,作用多层间接性
    {
        typedef typname Iterator::value_type value_type;
    };
    
    
    template<class T>
    struct iterator_traits<T*>//特化iterator_traits,直接提取类型
    {
        typedef T value_type;
    };
    template<class T>
    struct iterator_traits<const T*>//特化iterator_traits,直接提取类型
    {
        typedef T value_type;
    };
    
    //typename iterator_traits<Iterator>调用的是泛化的或者特化的
    template<class Iterator>
    typename iterator_traits<Iterator>::value_type fun(Iterator ite)
    {
        return *ite;//迭代器基本类型,以及有解引用功能
    }
    //直接使用底层型别,如果是T*,则出问题,相当于value_type被解读为T*
    //同样用list<int>::iterator,则被解读为list<int>::iterator,而不会深度挖掘。
    //显然只是适合于传递T,才能达到目的
    template<class Iterator>
    typename Iterator::value_type fun(Iterator ite)
    {
        return *ite;
    }
    fun(list<int>::iterator ite);//显然是调用了iterator_traits模板
    //typename iterator_traits<list<int>::iterator>::value_type
    //typedef typname list<int>::iterator::value_type value_type;
    //这就调用了list相应的迭代器中value_type,则为int。
    //typedef typname list<int>::iterator::int value_type;
    //-------------------------------------------------------------上述是T类型,榨取---------------------------
    //stl-iterator头文件
    //具体的模板,可能需要的具体的5种型别不一样,有的模板直接可以确定下来。所以定义一个最高的母版为下
    template <class Category, class T, class Distance = ptrdiff_t,
              class Pointer = T*, class Reference = T&>
    struct iterator {
      typedef Category  iterator_category;
      typedef T         value_type;
      typedef Distance  difference_type;
      typedef Pointer   pointer;
      typedef Reference reference;
    };
    //例如<假象的>vector特化迭代器
    template<class T>
    struct vector_iterator:public iterator<random_access_iterator_tag,T>{
      typedef random_access_iterator_tag  iterator_category;//vector模板可以确定
      typedef T         value_type;
      typedef size_type  difference_type;//可以确定下来了
      typedef Pointer   pointer;
      typedef Reference reference;
    };
    
    
    
    //基础榨取机模板类----泛化
    template<class I>
    struct iterator_traits
    {
        typedef I::value_type value_type;//迭代器所指的类型
        typedef I::difference_type difference_type;//迭代器距离
        typedef I::pointer pointer;
        typedef I::reference reference;
        typedef I::iteratro_category iterator_category;//迭代器类型。
    };
    //特化版1
    template<class T>
    struct iterator_traits<T*>
    {
        typedef T value_type;//迭代器所指的类型
        typedef ptrdiff_t difference_type;//迭代器距离
        typedef T* pointer;
        typedef T& reference;
        typedef random_access_iterator_tag iterator_category;
        
    };
    //特化版2
    template<class T>
    struct iterator_traits<const T*>
    {
        typedef T value_type;//迭代器所指的类型
        typedef ptrdiff_t difference_type;//迭代器距离
        typedef T* pointer;
        typedef T& reference;
        typedef random_access_iterator_tag iterator_category;
    };
    
    //应用部分
    template<class I>
    typename iterator_traits<I>::difference_type f(I);//榨取其中的ptrdiff_t
    //如果I传入的是类型为list<vector<int>>则,会先看list迭代器,取出其中元素为vector<int>,细调用
    //vector的difference_type,此时就会调用int的difference_type,那此处就会有difference_type的类别名
    template<class I>
    typename iterator_traits<I>::value_type f();//榨取其中的T
    template<class I>
    typename iterator_traits<I>::pointer f();//榨取其中的T*
    template<class I>
    typename iterator_traits<I>::reference f();//榨取其中的T&
    template<class I>
    typename iterator_traits<I>::iterator_category f();//榨取其中的random_access_iterator_tag
    
    
    
    
    //------------------------------下述,产生iterator_category的型别因素---------------------------------
    //将5种类型迭代器,构造一个空类,其这样做目的是区分种类类型,而不需要任何数据成员。
    struct input_iterator_tag {};
    struct output_iterator_tag {};
    struct forward_iterator_tag : public input_iterator_tag {};
    struct bidirectional_iterator_tag : public forward_iterator_tag {};
    struct random_access_iterator_tag : public bidirectional_iterator_tag {};
    
    
    //输入迭代器---只读,单向
    template <class InputIterator, class Distance>
    inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
      while (n--) ++i;
    }
    //双向迭代器---可读写,双向
    template <class BidirectionalIterator, class Distance>
    inline void __advance(BidirectionalIterator& i, Distance n, 
                          bidirectional_iterator_tag) {
      if (n >= 0)
        while (n--) ++i;
      else
        while (n++) --i;
    }
    //随机迭代器---可读写,随机访问
    template <class RandomAccessIterator, class Distance>
    inline void __advance(RandomAccessIterator& i, Distance n, 
                          random_access_iterator_tag) {
      i += n;
    }
    //外口函数--客户端使用的,是2个参数的advance函数,是根据传入时的迭代器类型不同而定下采用哪个函数
    template <class InputIterator, class Distance>
    inline void advance(InputIterator& i, Distance n) {
      __advance(i, n, iterator_category(i));
    }
    //获取迭代器的 距离。----放回距离的指针,其值为0
    template <class Iterator>
    inline typename iterator_traits<Iterator>::difference_type*
    distance_type(const Iterator&) {
      return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
    }
    //获取迭代器所指元素类型---放回元素类型指针,其值为0
    template <class Iterator>
    inline typename iterator_traits<Iterator>::value_type*
    value_type(const Iterator&) {
      return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
    }
    //函数获取,迭代器种类型别,放回种类型别对象,初始化后的
    template <class Iterator>
    inline typename iterator_traits<Iterator>::iterator_category
    iterator_category(const Iterator&) {
      typedef typename iterator_traits<Iterator>::iterator_category category;//此处出来的最后是某个_tag类型
      return category();
    }
    
    
    
    //例如:
    advance(vector<int>::iterator,2);//通过传入的vector迭代器,则可以通过榨取机获得此类型为随机访问迭代器模型
    //因为它会调用vector模板中的iterator_category,而它则某个_bag,则显然会被定义为随机访问迭代器。而不会是
    //迭代器的I::iterator_category,故而和vector<list<int>>的迭代器类型应该是一致的。
    //---------------------------------------------------//
  • 相关阅读:
    1月6日 作业 穷举
    1.4 作业
    12月31日 作业
    12月29日-练习成果
    12月30日作业-<转>字符集编码
    1.22作业
    集合
    泛型
    CPU接口练习 (仅以此程序证明 某个同学真的有毒!有毒!!!)
    继承知识点总结
  • 原文地址:https://www.cnblogs.com/miner007/p/4162647.html
Copyright © 2011-2022 走看看