迭代器类型:iterator_category
迭代器根据移动特性和执行操作,可分为五类:
①Input iterator: 输入迭代器,只读,不写,单遍扫描,只能递增
②Output iterator: 输出迭代器,只写,不读,单遍扫描,只能递增
③Forward iterator: 前向迭代器,可读写,多遍扫描,只能递增
④Bidirectional iterator: 双向迭代器,可读写,多遍扫描,可递增递减
⑤Random Access Iterator: 随机访问迭代器,可读写,多遍扫描,支持全部迭代器运算
*前四种迭代器都只支持一部分指针算术能力,前三种支持operator++,第四种支持operator- -,第五种则支持指针所有算术能力,包括p+n, p-n, p[n], p1-p2, p1<p2。
这些迭代器的分类与从属关系:
(Input iterator, Output iterator)——强化——>Forward iterator——强化——>Bidirectional iterator——强化——>Random Access Iterator。
当定义算法时,输入参数为迭代器,因五种迭代器支持操作不同,而算法无法区分上述五种迭代器,如果执行时期才决定使用哪一种迭代器会影响效率,程序希望在编绎时期就选择正确的版本,此时重载函数机制可达成目标。
traits特性
traits可提取出迭代器的种类,作为算法参数,在编绎期决定使用相应迭代器的重载版本。
traits的iterator_category即为迭代器类型。
迭代器的设计
STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此独立设计。
容器和算法的泛型化,C++的class templates和function templates可分别达成目标。
迭代器扮演容器和算法之间的粘胶角色。
iterator模式定义为:提供一种方法,使之能够依序访问某个聚合物(容器)所含的每个元素,而又无需暴露该聚合物的内部表达方式。
迭代器是一种smart pointer
迭代器是一种行为类似指针的对象,指针行为中最常见的便是解引用和成员访问,因此迭代器最重要的编程工作就是对operator*和operator->进行重载工作。
namespace std _GLIBCXX_VISIBILITY(default)
{
//定义五种迭代器类型的tag,仅作为标记用,类中不需要任何成员
//iterator_traits<Iterator>::iterator_category()可得到以下五种tag类型
struct input_iterator_tag { }; //input iterators.
struct output_iterator_tag { }; //output iterators.
//Forward iterators support a superset of input iterator operations.
struct forward_iterator_tag : public input_iterator_tag { };
//Bidirectional iterators support a superset of forward iterator operations.
struct bidirectional_iterator_tag : public forward_iterator_tag { };
//Random-access iterators support a superset of bidirectional iterator operations.
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
//算法中使用迭代器时,可能会用到相应类型,例迭代器所指元素类型等
//函数模板形参可通过实参推断,但返回类型无法推断
//将返回类型等一应类型封装为类,类中声明各种类型,解决模板函数返回类型无法推断问题
//类中不含任何成员,后三个模板参数皆有默认值,新设计的迭代器继承自它,提供前两个模板参数即可
template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
typename _Pointer = _Tp*, typename _Reference = _Tp&>
struct iterator //iterator模板类
{
typedef _Category iterator_category; //迭代器的类型,不同的迭代器支持的操作不同
typedef _Tp value_type; //元素类型,即迭代器所指对象类型
typedef _Distance difference_type; //两迭代器之间的距离,足够表示容器最大容量,STL的count()的返回类型
typedef _Pointer pointer; //指向迭代器元素的指针,等同于value_type*
typedef _Reference reference; //元素的左值引用,与value_type&含义相同
};
template<typename _Iterator, typename = __void_t<>>
struct __iterator_traits { }; //__iterator_traits模板类一
template<typename _Iterator> //__iterator_traits模板类二
struct __iterator_traits<_Iterator,
__void_t<typename _Iterator::iterator_category,
typename _Iterator::value_type,
typename _Iterator::difference_type,
typename _Iterator::pointer,
typename _Iterator::reference>>
{
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;
};
//iterator_traits设计如下:
template<typename _Iterator> //iterator_traits模板类,继承__iterator_traits模板类
struct iterator_traits
: public __iterator_traits<_Iterator> { };
//内置指针类型不是class类型,无法内嵌类型,需定义特例化版本
//iterator_traits针对传入类型为pointer及const pointer设计特例化版本。
//特例化版本的指针类型是random_access_iterator_tag类型
template<typename _Tp>
struct iterator_traits<_Tp*>
{
typedef random_access_iterator_tag iterator_category; //指针类型为random_access_iterator_tag类型
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
template<typename _Tp>
struct iterator_traits<const _Tp*>
{
typedef random_access_iterator_tag iterator_category; //指针类型为random_access_iterator_tag类型
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
//返回迭代器的类型
//iterator_traits<Iterator>::iterator_category()返回上述定义的五种tag类型
template<typename _Iter>
inline _GLIBCXX_CONSTEXPR
typename iterator_traits<_Iter>::iterator_category
__iterator_category(const _Iter&)
{ return typename iterator_traits<_Iter>::iterator_category(); }
template<typename _InIter>
using _RequireInputIter = typename
enable_if<is_convertible<typename
iterator_traits<_InIter>::iterator_category,
input_iterator_tag>::value>::type;
} // namespace
namespace std _GLIBCXX_VISIBILITY(default)
{
template <typename> struct _List_iterator;
template <typename> struct _List_const_iterator;
//以下是整组distance函数
//__distance()只在内部使用,第三参数根据五种tag形成重载
//第三参数为input_iterator_tag时,迭代器循环累计距离
//output_iterator_tag、forward_iterator_tag、bidirectional_iterator_tag使用此版本
//STL算法命名规则,以算法所能接受之最低阶迭代器类型为迭代器类型参数命名
template<typename _InputIterator>
inline _GLIBCXX14_CONSTEXPR
typename iterator_traits<_InputIterator>::difference_type
__distance(_InputIterator __first, _InputIterator __last,
input_iterator_tag)
{
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
typename iterator_traits<_InputIterator>::difference_type __n = 0;
while (__first != __last)
{
++__first;
++__n;
}
return __n;
}
//第三参数为random_access_iterator_tag时,迭代器直接计算距离
template<typename _RandomAccessIterator>
inline _GLIBCXX14_CONSTEXPR
typename iterator_traits<_RandomAccessIterator>::difference_type
__distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
random_access_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_RandomAccessIteratorConcept<
_RandomAccessIterator>)
return __last - __first;
}
//_List_iterator和_List_const_iterator的特例化版本
template<typename _Tp>
ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
_GLIBCXX_STD_C::_List_iterator<_Tp>,
input_iterator_tag);
template<typename _Tp>
ptrdiff_t
__distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
input_iterator_tag);
//distance根据不同迭代器类型调用不同__distance
template<typename _InputIterator>
inline _GLIBCXX17_CONSTEXPR
typename iterator_traits<_InputIterator>::difference_type
distance(_InputIterator __first, _InputIterator __last)
{
//__iterator_category()获取迭代器类型调用相应版本
//根据迭代器类型重载不同版本__distance()
return std::__distance(__first, __last,
std::__iterator_category(__first));
}
//以下是整组的advance函数
//第三参数为input_iterator_tag时,迭代器单向,+1前进
template<typename _InputIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_assert(__n >= 0);
while (__n--)
++__i;
}
//第三参数为bidirectional_iterator_tag时,迭代器双向,+1或-1
template<typename _BidirectionalIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_BidirectionalIteratorConcept<
_BidirectionalIterator>)
if (__n > 0)
while (__n--)
++__i;
else
while (__n++)
--__i;
}
//第三参数为random_access_iterator_tag时,迭代器双向,跳跃前进
template<typename _RandomAccessIterator, typename _Distance>
inline _GLIBCXX14_CONSTEXPR void
__advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag)
{
// concept requirements
__glibcxx_function_requires(_RandomAccessIteratorConcept<
_RandomAccessIterator>)
if (__builtin_constant_p(__n) && __n == 1)
++__i;
else if (__builtin_constant_p(__n) && __n == -1)
--__i;
else
__i += __n;
}
//advance根据不同迭代器类型调用不同__advance
template<typename _InputIterator, typename _Distance>
inline _GLIBCXX17_CONSTEXPR void
advance(_InputIterator& __i, _Distance __n)
{
//__iterator_category()获取迭代器类型调用相应版本
//根据迭代器类型重载不同版本__advance()
typename iterator_traits<_InputIterator>::difference_type __d = __n;
std::__advance(__i, __d, std::__iterator_category(__i));
}
//单向迭代器,获取当前迭代器的后置
template<typename _InputIterator>
inline _GLIBCXX17_CONSTEXPR _InputIterator
next(_InputIterator __x, typename
iterator_traits<_InputIterator>::difference_type __n = 1)
{
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
std::advance(__x, __n);
return __x;
}
//双向迭代器,获取当前迭代器的前置
template<typename _BidirectionalIterator>
inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
prev(_BidirectionalIterator __x, typename
iterator_traits<_BidirectionalIterator>::difference_type __n = 1)
{
__glibcxx_function_requires(_BidirectionalIteratorConcept<
_BidirectionalIterator>)
std::advance(__x, -__n);
return __x;
}
} // namespace