文章目录
前言
迭代器是一种抽象的设计概念,现实设计语言中并没有直接对应于这个概念的实物。
iterator模式定义:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该聚合物的内部表达方式。
迭代器是一种smart pointer
vector<int>::iterator
list<int>::iterator
deque<int>::iterator
auto_ptr
void func()
{
auto_ptr<string> ps(new string("jjhou));
cout << *ps << endl;
cout << ps->size() << endl;
// 离开前不需要delete
}
迭代器是对象,它需要重载operator*和operator->
// file: 3autoptr.cpp
template<class T>
class auto_ptr
{
public:
explicit auto_ptr(T *p = 0):pointee(p) {}
template<class U> auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {}
~auto_ptr() {delete pointee;}
template<class U>
auto_ptr<T>& operator=(auto_ptr<U>& rhs)
{
if (this != &rhs) reset(rhs.release());
return *this;
}
T& operator*() const {return *pointee;}
T* operator->() const {return pointee;} /* ????????????????????????? */
T* get() const {return pointee;}
// ...
private:
T *pointee;
};
// file: 3mylist.h
template<typename T>
class List
{
private:
void insert_front(T value);
void insert_end(T value);
void display(std::ostream &os = std::cout) const;
// ...
private:
ListItem<T>* _end;
ListItem<T>* _front;
long _size;
};
template<typename T>
class ListItem
{
public:
T value() const {return _value;}
ListItem* next() const {return _next;}
...
private:
T _value;
ListItem* _next;
};
// file : 3mylist-iter.h
#include "3mylist.h"
template<class Item>
struct ListIter
{
Item* ptr;
ListIter(Item* p = 0):ptr(p) {}
};
迭代器相应型别associated types
利用template参数推到机制获得迭代器所指对象的类型
template<class I, class T>
void func_impl(I iter, T t)
{
T tmp;
//...
}
template<class I>
inline void func(I iter)
{
func_impl(iter, *iter);
}
int main()
{
int i;
func(&i);
}
traits编程技法
迭代器所指对象的型别称为该迭代器的value type。
模板参数推导机制只能推导参数,无法推导函数的返回值类型。
template<class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p=0) : ptr(p) { }
T& operator*() const { return *ptr; }
// ...
};
template<class I>
//若I不是class则该方法失效,需要特例化该模板
typename iterator_traits<I>::value_type func(I ite)
// typename ::value_type func(I ite)
{ return *ite; }
// ...
MyIter<int> ite(new int(4));
cout << func(ite) << endl;
//特例化
//下面这个class template专门用来“萃取”迭代器的特性,而value type正是其一
template<class I>
struct iterator_traits //traits意味“特性”
{
typedef typename I::value_type value_type;
};
template<class T>
struct iterator_traits<T*> //特例化——迭代器是个原生指针
{
typedef T value_type;
};
//特例化版——当迭代器是个pointer-to-const时,萃取的是T,而非const T
template<class T>
struct iterator_traits<const T*>
{
typedef T value_type;
};
template<>
struct iterator_traits<double>
{
typedef int value_type;
};
traits
//常用的迭代器相应型别
template<class I>
struct iterator_traits{
typedef typename I::iterator_category iterator_category;
// 迭代器所指对象的类型
typedef typename I::value_type value_type;
// 表示两个迭代器之间的距离
typedef typename I::difference_type difference_type;
// pointer type
typedef typename I::pointer pointer;
// reference type
typedef typename I::reference reference;
};
// iterator_traits必须针对传入的pointer及pointer-to-const,设计特例化版本
// C++内建的ptrdiff_t定义于<cstddef>作为原生指针的difference type
template<class T>
struct iterator_traits<T*>{
typedef ptrdiff_t defference_type;
typedef T* pointer;
typedef T& reference;
};
template<class T>
struct iterator_traits<const T*>{
typedef ptrdiff_t defference_type;
typedef const T* pointer;
typedef const T& reference;
};
Item& operator*() const {return *ptr;}
Item* operator->() const {return ptr;}
Item&为 ListIter的reference type,而Item*为其pointer type
迭代器分类
根据移动特性与施行操作,迭代器被分为五类:
- input iterator:这种迭代器所指的对象,不允许外界改变。只读
- output iterator:只写
- forward iterator:允许“写入型”算法如replace在此中迭代器所形成的区间上进行读写操作
- bidirectional iterator:可双向移动
- random access iterator:涵盖所有指针算术能力,p+n, p-n, p[n], p1-p2, p1<p2
// 五个作为编辑用的类型 tag types
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 {};
distance
template<class InputIterator>
inline iterator_traits<InputIterator>::defference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag)
{
iterator_traits<InputIterator>::defference_type n = 0;
while (first != last){
++first; ++n;
}
return n;
}
template<class RandomAccessIterator>
inline iterator_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
{
return last - first;
}
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());
}
std::iterator
每个新设计的迭代器都应该继承下面的类,以保证与STL兼容
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;
};
新定义的迭代器应该有如下形式
template<class Item>
struct ListIter: public std::iterator<std::forward_iterator_tag, Item>
总结
iterator源代码完整重列
<stl_iterator.h>
SIG STL __type_traits
struct __true_type {};
struct __false_type {};
// 泛化版本
template<class type>
struct __type_traits
{
typedef __true_type this_dummy_member_must_be_first;
/* */
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_constructor;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};
// 自行设计一个__type_traits特例化版本
template<> struct __type_traits<自定义的类>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_constructor;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};