结论: std::iterator_traits 用于Iterator类型dom
好比有这么一个需求,给随意的一个迭代器移动距离 , 伪代码:ide
template <typename Iter, typename Distance> void move_iter(Iter& iter, Distance d) { if( iter is std::random_access_iterator_tag) //随机迭代器随意加减 iter +=d; else //别的迭代器 .... }
问题是如何判断一个迭代器类型 ,使用 iterator_traits;code
前提 , 5种迭代器是继承关系 ,随意看一眼便可:继承
struct input_iterator_tag { // identifying tag for input iterators }; struct _Mutable_iterator_tag { // identifying tag for mutable iterators }; struct forward_iterator_tag : input_iterator_tag, _Mutable_iterator_tag { // identifying tag for forward iterators }; ....
看一下iterator_traits:rem
template<class _Iter> struct iterator_traits { // get traits from iterator _Iter typedef typename _Iter::iterator_category iterator_category; ... 还有一堆typedef的东西, 省略 }
iterator_traits 和 remove_reference 内部实现差很少, 只是一堆typedef ,主要用于获取类型;
先简单看一下iterator_traits 怎么用:get
//太长了? // iterator_traits<迭代器类型>::iterator_category //iterator_category 就是一个被typedef 的 5个结构体中的其中一个 cout << typeid(std::iterator_traits<list<int>::iterator>::iterator_category).name() << endl; cout << typeid(std::iterator_traits<deque<int>::iterator>::iterator_category).name() << endl; /* 输出: struct std::bidirectional_iterator_tag struct std::random_access_iterator_tag */
用于判断迭代器类型的就是iterator_category ,而他自己就是5种迭代器的其中一个;input
接下来就能够修改第一份伪代码了 . 大体是这样:it
template <typename Iter, typename Distance> void move_iter(Iter& iter, Distance d) { if(typeid(std::random_access_iterator_tag) == typeid(std::iterator_traits<Iter>::iterator_category)) iter += d; else if ... ... }
用RTTI这类东西老是以为,原本就能够在编译的时候完成的,干吗非等到运行时;io
在修改一下 , 下面代码用了哑元 , 3个重载的template function:编译
template <typename Iter , typename Dist> void do_move_iter(Iter & iter, Dist d , std::random_access_iterator_tag) //随机迭代 { iter += d; } template <typename Iter , typename Dist> void do_move_iter(Iter & iter, Dist d , std::bidirectional_iterator_tag) //双向 { if( d>= 0){ while(d--) ++iter; } else { while(d++) --iter; } } template <typename Iter , typename Dist> void do_move_iter(Iter & iter, Dist d , std::input_iterator_tag) // forward继承了input; { if( d < 0) throw std::out_of_range("d < 0"); while(d--) ++iter; } template <typename Iter, typename Distance> void move_iter(Iter& iter, Distance d) { do_move_iter(iter,d, std::iterator_traits<Iter>::iterator_category()); } int main() { vector<int> vi{1,2,3,4}; vector<int>::iterator iter = vi.begin(); //随机迭代器 move_iter(iter,2); //移动2个距离 cout << *iter << endl; //3. ok的 }