之前已经完成了STL中容器的梳理,那么从语言的层面来看:
- 容器是class template
- 算法是function template
- 迭代器是class template
- 适配器是class template
- 分配器是class template
一般STL中的算法都是如下的两种形式(Algorithm代表一种泛指,可以替代其他的函数名称)
template<typename Iterator>
Algorithm (Iterator itr1, Iterator itr2)
{
..........
}
template<typename Iterator, typename Cmp>
Algorithm (Iterator itr1, Iterator itr2, Cmp comp)
{
..........
}
对于Algorithms来说,是不能直接看到Container的,对他的情况可谓一无所知。那么,他所需要的一切信息就必须要通过他们之间桥梁Iterators来获得了。然而Iterators(是由Container所提供的)必须能够回答Algorithms所提出的一些问题(比如类型等),才能够搭配对应的Algorithm的所有操作。
所谓算法的所提出的问题,其hi就是类型的确认过程,通过确认,来获取他所需要的,例如标记了五种iterator categories的类型
//5种iterator categories
struct input_iterator_tag{};
//
struct output_iterator_tag{};
//
struct forward_iterator_tag : public input_iterator_tag{};
//forward_list是单向链表
struct bidirectional_iterator_tag : public forward_iterator_tag{};
//list,rb_tree为底层的set,multiset、map、multimap是双向链表,iterator不能随机跳跃
struct random_access_iterator_tag : public bidirectional_iterator_tag{};
//对于连续空间的array、vector、deque
(虽然实际上不连续,但是iterator构造了连续的假象)
,这些迭代器可以随便跳跃的类型
![](http://upload-images.jianshu.io/upload_images/5688965-6c14db46c05364e8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
iterator categories的UML
这样设计的优势是在于,通过对象的方式就可以调用不同函数的重载,例如:
void _display_category(random_access_iterator_tag){
cout << "random_access_iterator" << endl;
}
void _display_category(bidirectional_iterator_tag){
cout << "bidirectional_iterator" << endl;
}
void _display_category(forward_iterator_tag){
cout << "forward_iterator" << endl;
}
void _display_category(input_iterator_tag){
cout << "input_iterator" << endl;
}
void _display_category(output_iterator_tag){
cout << "output_iterator" << endl;
}
template<typename I>
void display_category(I iter){
typename iterator_traits<I>::iterator_category cagy;
_display_category(cagy);
//根据对象类型,可以调用不同的函数重载
}
//.........
{
//通过iterator的临时对象来作为参数调用
display_category(set<int>::iterator());
}
- istream_iterator 的iterator_category
gnu2.9里面的istream_iterator
template <class T,
class Distance = ptrdiff_t>
class istream_iterator{
public:
typedef input_iterator_tag iterator_category;
// ............
};
gnu 3.3里面的istream_iterator
template<class _Tp,
class _CharT = char,
class _Traits = char_traits<_CharT>,
class _Dist = ptrdiff_t>
class istream_iterator{
public:
typedef input_iterator_tag iterator_category;
}
Gnu4.9里面的istream_iterator
template<typename _Category,
typename _Tp,
typename _Distance = ptrdiff_t,
typename _Pointer = _Tp*,
typename _Reference = _Tp&>
struct iterator{
typedef _Category iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Pointer pointer;
typedef _Reference reference;
}
template<typename _Tp,
typename _CharT = char,
typename _Traits = char_traits<_CharT>,
typename _Dist = ptrdiff_t>
class istream_iterator: public iterator<input_iterator_tag, _Tp, _Dist, const _*Tp, const _Tp&>
{...........}
- ostream_iterator 的iterator_category
gnu2.9里面的ostream_iterator
template <class T,
class Distance = ptrdiff_t>
class ostream_iterator{
public:
typedef output_iterator_tag iterator_category;
// ............
};
gnu 3.3里面的ostream_iterator
template<class _Tp,
class _CharT = char,
class _Traits = char_traits<_CharT>,
class _Dist = ptrdiff_t>
class ostream_iterator{
public:
typedef output_iterator_tag iterator_category;
}
Gnu4.9里面的ostream_iterator
template<typename _Category,
typename _Tp,
typename _Distance = ptrdiff_t,
typename _Pointer = _Tp*,
typename _Reference = _Tp&>
struct iterator{
typedef _Category iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Pointer pointer;
typedef _Reference reference;
}
template<typename _Tp,
typename _CharT = char,
typename _Traits = char_traits<_CharT>,
typename _Dist = ptrdiff_t>
class ostream_iterator: public iterator<output_iterator_tag, void, void, void, void>
{...........}
- iterator_category对算法的影响
template<class InputIterator>
inline iterator_trais<InputIterator>::diference_type __distance(InputIterator first, InputIterator last, input_iterator_tag){
//input_iterator_tag是forward_iteator_tag和bidirectional_iterator_tag的父类,
//所以遇到了会直接进入input_iterator_tag的重载部分
iterator_trais<InputIterator>::difference_type n = 0;
//由于不是RandomAccessIterator,所以迭代器不能直接相减,需要遍历了
while(first != last){
++first;
++n;
}
return n;
}
template<class RandomAccessIterator>
inline iterator_trais<RandomAccessIterator>::difference_type __distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag){
return last - first;
//只有连续空间才能迭代器想减
}
template<class InputIterator>
inline iterator_trais<InputIterator>::difference_type distance(InputIterator first, InputIterator last){
//根据trais获取iterator的category tag,如果编译不通过说明迭代器出问题
typedef typename iterator_trais<InputIterator>::iterator_category category;
return __distance(first,