結論: 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的 }