algorithm.h中的distance函数原型如下:
template <class Iterator>
typename iterator_traints<Iterator>::difference_type distance(Iterator first,Iterator last){
typedef typename iterator_traints<Iterator>::iterator_category category;
return __distance(first,last,category());//category is a struct
}
靠iterator_traints而来的category来分别5种迭代器。
template <class T>
struct iterator_traints{
typedef typename T::iterator_category iterator_category;
typedef typename T::size_type size_type;
typedef typename T::difference_type difference_type;
};
iterator_traints其实是一个模板类,可以得到传入其中的类型的category,所以,迭代器中必须定义iterator_category,size_type,difference_type这三个东西。
iterator_category取值为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{};
所以,list的迭代器如下:
class __list_iterator{
public:
typedef bidirectional_iterator_tag iterator_category;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
__list_iterator(__list_node<T>* x):node(x){}
__list_iterator<T>& operator++(){//前置++
node=node->next;
return *this;
}
__list_iterator<T>& operator++(int){
__list_iterator<T>tmp=*this;
++*this;
return tmp;
}
__list_iterator<T>& operator--(){//前置++
node=node->pre;
return *this;
}
__list_iterator<T>& operator--(int){
__list_iterator<T>tmp=*this;
--*this;
return tmp;
}
T& operator*(){return node->data;}
bool operator==(const __list_iterator &x)const{return node==x.node;}
bool operator!=(const __list_iterator &x)const{return node!=x.node;}
__list_node<T>*node;
};
有上面可知,list的迭代器iterator_category为bidirectional_iterator_tag,传入distance之后,iterator_traints得到的category为bidirectional_iterator_tag,根据重载规则,会调用到
template <class InputIterator>
typename iterator_traints<InputIterator>::difference_type __distance(InputIterator first,InputIterator last,input_iterator_tag){
typename iterator_traints<InputIterator>::difference_type n=0;//here typename is not must need,because here difference must be a type
std::cout<<"inputIterator"<<std::endl;
while(first!=last){
++first;++n;
}
return n;
}
为什么不是调用到__distance(InputIterator first,InputIterator last,bidirectional_iterator_tag),因为bidirectional_iterator_tag继承input_iterator,
由于有些迭代器是指针,而不是类,无法通过iterator_traints得到category,所以,可以偏特化实现指针形的
template <class T>
struct iterator_traints<T*>{//偏特化,生成指针版本
typedef random_access_iterator_tag iterator_category;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
};