迭代器-iterator

__iterator_traits技法用于提起迭代器iterator的相应类型

先看下面是一个例子:

template <class I, class T>
void func_impl(I iter, T t)
{
	// ...
}

template<class I>
inline void func(I iter)
{
	func_impl(iter, *iter);
	// ...
}

int main()
{
	int i;
	func(&i);
	return 0;
}

这里利用了function template的参数推导机制。“template参数推导技术”只是推出参数,无法推导返回值,怎么办?我们可以在迭代器里内嵌一个型别声明。如下:

template<class T>
struct MyIter
{
	typedef T value_type;
	// ....
};

template<class I>
typename I::value_type func(T iter)
{
	return *iter;
}

通过在迭代器类里面嵌入一个声明,解决了推导返回值的问题(注意:上面要用typename,因为MyIter是个模板,编译器对T模板参数一无所知)!但问题又来了,并不是所有类型(如int *)都是calss type,所以无法为它定义内嵌型别,template partial specialization(模板偏特化)可以做到,但要用另一个模板作为中间层进而偏特化(这里就是__iterator_traits技法了),如下:

//__iterator_traits
template<class I>
struct iterator_traits
{
	typedef typename I::value_type value_type;
};
//__iterator_traits偏特化版本,准确接受内置指针类型
template<class I>
struct iterator_traits<T*>
{
	typedef T value_type;
};
//接受指向const类型数据的指针
template<class I>
struct iterator_traits<const T*>
{
	typedef T value_type;
};
所以,STL里的算法模板都是这样实现,如果我们要设计与STL水乳交融的类,那就要符合STL的一些基本要求了。
1.设计类
2.设计类的迭代器
迭代器要满足STL的要求,那么你的迭代器就能用在STL算法。


STL中有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{};
Iuput iterator,只读
Output iterator,只写
Forward iterator,可读写
Bidirection iterator,可双向移动

Random Access iterator,前四种提供基本操作(operator++,第四种在加上operator--),这种包含所有指针算术能力(p+n,p-n,p[n],p1<p2...)

为了定义自己的迭代器,可以继承自下面的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;
};
于是针对指针,我们定义了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 *
value_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()构造一个临时对象,进行参数推导,决定重载函数。
}

以下是advance

template<class InputIterator, class Distance>
inline void __advance(InputIterator &i, Distance n, input_iterator_tag)
{
	while (n--)++i;
}
template<class ForwardIterator, class Distance>
inline void __advance(ForwardIterator &i, Distance n, forward_iterator_tag)
{
	__advance(i, n, input_iterator_tag());
}

template<class BidirectionIterator, class Distance>
inline void __advance(BidirectionIterator &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;
}

template<class Iterator, class Distance>
inline void advance(Iterator &i, Distance n)
{
	__advance(i, n, iterator_traits<Iterator>::iterator_category());
}




来源:STL源码剖析




猜你喜欢

转载自blog.csdn.net/Alatebloomer/article/details/80654232