C++学习之深入理解迭代器——迭代器特性、迭代器标志-iterator_traits

Iterator Traits(迭代器特性)
迭代器可以区分为不同的类型,每个类型都有特定的迭代器功能。
根据迭代器类型,将操作行为重载,将会很有用,也很必要!
透过迭代器标志(tags)和迭代器特性(traits,由<iterator>提供)可以实现这样的重载.

STL为每周迭代器都提供了一个迭代器标志(iterator tags),用来作为迭代器的标签(label)
    namespace
    {
        struct output_iterator_tag
        {
        };
        struct input_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
        {
        };
    }
请注意,这里使用了继承,所有我们可以说:
任何Forward迭代器都是一种(is-a) input迭代器

STL提供了一种特殊的template结果来定义所谓的迭代器特性(traits)
其包含迭代器的相关特性,为迭代器应具备的所有类型定义(包括迭代器类型、元素类型等)提供一致的接口
    namespace std
    {
        template <class T>
        struct iterator_traits
        {
            typedef typename T::value_type        value_type;
            typedef typename T::difference_type   difference_type;
            typedef typename T::iterator_category iterator_category;
            typedef typename T::pointer           pointer;
            typedef typename T::reference         reference;
        };
    }

    这里,T表示迭代器类型。有了它,我们就可以写任何运用迭代器类型或者元素类型等特征
    的泛型程序代码:
    typename std::iterator_traits<T>::value_type;

   迭代器类型如下:

通过iterator_traits返回某个具体迭代器的value等,见下面

template <class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
  struct iterator {
    typedef T         value_type;
    typedef Distance  difference_type;
    typedef Pointer   pointer;
    typedef Reference reference;
    typedef Category  iterator_category;
  };

    这个iterator_traits有两个优点:
    1.能确保每一个迭代器提供所有必要的性别定义
    2.能针对特定的迭代器进行特化(specialization)
    如:以一般指针作为迭代器时的特化版本:
    namespace std
    {
        template <class T>
        struct iterator_traits<T*>
        {
            typedef T                          value_type;
            typedef ptrdiff_t                  difference_type;
            typedef random_access_iterator_tag iterator_category;
            typedef T*                         pointer;
            typedef T&                         reference;
        };
    }

    通过iterator_traits我们就可以编写这样的泛型函数:
    根据迭代器类型定义采用不同的功能实现

    如算法内部要定义一个临时变量tmp(其中T为迭代器类型):
   

    

    另一个例子,元素的环形移动:
    template <class ForwardIterator>
    void shift_left(ForwardIterator beg,ForwardIterator end)
    {
        if(beg != end)
        {
            value_type tmp(*beg);

            //我认为应该是  typename std::iterator_traits<ForwardIterator>::value_type tmp(*beg);
            //...
        }
    }

   

运用迭代器类型:
如果你希望针对不同的迭代器采用不同的实现方案,你需要按下面两步来走:
1.让你的template函数将迭代器类型作为附加参数,调用另一个函数:
    template <class iterator>
    inline void foo(intertor beg,intertor end)
    {
        foo(beg,end,
            std::iterators_traits<intertor>::iterator_category());
    }
2.针对不同的迭代器类型实现上述所调用的函数。
    template <class BIDirectionIterator>
    void foo(BIDirectionIterator beg,BIDirectionIterator end,
             std::bidirectional_iterator_tag)
    {
        //...
    }
    template <class RandomAccessIterator>
    void foo(RandomAccessIterator beg,RandomAccessIterator end,
             std::random_access_iterator_tag)
    {
        //...
    }

    实例:实现迭代器辅助函数 distance()
    对于随机迭代器,只是简单的运用operator-
    对其他类型的迭代器,必须一步一步的前进到区间终点
    (因此,必须保证其实迭代器前进一定能够到达终止迭代器)
    template <class iterator>
    typename std::iterators_traits<intertor>::difference_type
    distance(intertor pos1,intertor pos2)
    {
        return distance(pos1,pos2,
            std::iterators_traits<intertor>::iterator_category());
    }

    ///对随机迭代器的实现版本
    template <class RandomAccessIterator>
    typename std::iterators_traits<RandomAccessIterator>::difference_type
    void distance(RandomAccessIterator pos1,RandomAccessIterator pos2,
             std::random_access_iterator_tag)
    {
        return pos2-pos1;
    }

    ///对input迭代器的实现版本
    template <class InputIterator>
    typename std::iterators_traits<InputIterator>::difference_type
    void distance(InputIterator pos1,InputIterator pos2,
             std::input_iterator_tag)
    {
        typename std::iterators_traits<InputIterator>::difference_type dist;
        for(dist=0;pos1!=pos2;++pos1,++dist)
        {
        }
        return dist;
    }

    注意:第二个实现的distance函数使用的是input迭代器,
    所有该版本对Forward迭代器、BiDirectional迭代器都生效。

你可能感兴趣的:(C++,算法,迭代器,迭代器,容器,迭代器特性,iterator_traits)