首页 > 代码库 > STL 之 iterator traits 备忘

STL 之 iterator traits 备忘

//5种迭代器,为了激活重载机制,定义的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{};


为了定义自己的迭代器,可以继承自下面的iterator类,避免迭代器型别的未定义。

//Base class for iterator class
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;
};


iterator_traits类,就是一些typedef,相当于就是将迭代器的最本质的类型忠实的呈现出来。这里值得注意的是,要使得这个迭代器忠实的完成这项工作,那么各个迭代器的定义就必须定义相应的5个性别。value_type difference_type  iterator_category pointer reference .

template<class Iterator>
struct iterator_traits
{
    typedef typename 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;
};


然而这对于指针而言是不可行的,因为指针没有结构体,我们无法在其中定义这5个型别,于是针对指针,我们定义了iterator_traits的特化版本。

template<class T>
struct iterator_traits<T*>
{
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef T & reference;
};


template<class T>
struct iterator_traits<const T*>
{
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef const T* pointer;
    typedef const T & reference;
    
};

注:根据指针指向 的内容是否可以改变,定义了上述的两种特化版本。


下面的函数则是直接返回各个型别的类型:

template<class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&)
{
  typedef typename iterator_traits<Iterator>::iterator_category category;
  return category(); //random_access_iterator_tag or bidirectional_iterator_tag ...
}


//pointer to the difference_type
template< class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type (const Iterator &)
{
  return static_cast<typename iterator_traits<Iterator>::difference_type *>(0);
}


template< class Iterator>
inline typename iterator_traits<Iterator>::value_type *
distance_type (const Iterator &)
{
  return static_cast<typename iterator_traits<Iterator>::value_type* > (0);
}



distance函数在上述traits下的实现代码:

//distance function


template<class InputIterator>
inline iterator_traits<InputIterator>::difference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag)
{
  iterator_traits<InputIterator>::difference_type n=0;
  while(first != last)
  {
      ++first;++n;
  }
  return n;
}
template<class RandomIterator>
inline typename iterator_traits<RandomIterator>::difference_type
__distance(RandomIterator first, RandomIterator last, random_access_iterator_tag)
{
    return last-first;
}


//user 
template<class InputIterator>
inline iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last)
{
    typedef typename iterator_traits<InputIterator>::iterator_category category;
    return __distance(first,last,category());//category()构造一个临时对象,进行参数推导,决定重载函数。
}

参考:STL源码剖析