STL Samples : <iterator>
traits,tag
iterator_traits
- template<class Iterator> struct iterator_traits { typedef typename Iterator::difference_type difference_type; typedef typename Iterator::value_type value_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; typedef typename Iterator::iterator_category iterator_category; }; - template<class T> struct iterator_traits<T*> { typedef ptrdiff_t difference_type; typedef T value_type; typedef T* pointer; typedef T& reference; typedef random_access_iterator_tag iterator_category; }; - template<class T> struct iterator_traits<const T*> { typedef ptrdiff_t difference_type; typedef T value_type; typedef const T* pointer; typedef const T& reference; typedef random_access_iterator_tag iterator_category; };
input_iterator_tag
output_iterator_tag
forward_iterator_tag
bidirectional_iterator_tag
random_access_iterator_tag
#include <iostream> #include <list> #include <deque> #include <vector> #include <iterator> #include <algorithm> #include "to_string.h" using namespace std; template<class Iterator> void sort_any_(Iterator first, Iterator last, random_access_iterator_tag) { sort(first, last); } template<class Iterator> void sort_any_(Iterator first, Iterator last, forward_iterator_tag) { typedef iterator_traits<Iterator>::value_type value_type; vector<value_type> v; copy(first, last, back_inserter(v)); sort(v.begin(), v.end()); copy(v.begin(), v.end(), first); } template<class Iterator> void sort_any(Iterator first, Iterator last) { sort_any_(first, last, iterator_traits<Iterator>::iterator_category()); } void std_traits() { cout << "iterator_traits, input_iterator_tag, output_iterator_tag, " << "forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag" << endl; list<int> l; deque<int> d; int i; for ( i = 0; i < 10; ++i ) { l.push_back(i % 4); d.push_back(i % 4); } cout << "list: " << to_string(l.begin(), l.end()) << " をソート: "; sort_any(l.begin(), l.end()); cout << to_string(l.begin(), l.end()) << endl; cout << "deque: " << to_string(d.begin(), d.end()) << " をソート: "; sort_any(d.begin(), d.end()); cout << to_string(d.begin(), d.end()) << endl; }
iterator操作
advance
- template <class InputIterator, class Distance> void advance(InputIterator& i, Distance n);
iをn個進めます。InputIteratorがRandomAccessIteratorあるいはBidirectionalIteratorであればn<0でもかまいません。そのときは-n個戻ることになります。
distance
- template<class InputIterator> typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);
firstからlastまでの距離、すなわち範囲[first,last)にある要素の個数を返します。
#include <list> #include <iterator> #include "to_string.h" using namespace std; void std_iter_op() { cout << "advance, distance" << endl; list<int> l; for ( int i = 0; i < 10; ++i ) l.push_back(i); list<int>::iterator it = l.begin(); advance(it,4); cout << to_string(l.begin(), l.end()) << " の4番目の位置: " << to_string(l.begin(), it, l.end()) << endl; cout << "4番目以降の要素数: " << distance(it, l.end()) << endl; }
反転イテレータ
reverse_iterator
- template <class Iterator> class reverse_iterator : public iterator<typename iterator_traits<Iterator>::iterator_category, typename iterator_traits<Iterator>::value_type, typename iterator_traits<Iterator>::difference_type, typename iterator_traits<Iterator>::pointer, typename iterator_traits<Iterator>::reference> { protected: Iterator current; public: typedef Iterator iterator_type; typedef typename iterator_traits<Iterator>::difference_type difference_type; typedef typename iterator_traits<Iterator>::reference reference; typedef typename iterator_traits<Iterator>::pointer pointer; reverse_iterator(); explicit reverse_iterator(Iterator x); template <class U> reverse_iterator(const reverse_iterator<U>& u); Iterator base() const; // explicit reference operator*() const; pointer operator->() const; reverse_iterator& operator++(); reverse_iterator operator++(int); reverse_iterator& operator--(); reverse_iterator operator--(int); reverse_iterator operator+ (difference_type n) const; reverse_iterator& operator+=(difference_type n); reverse_iterator operator-(difference_type n) const; reverse_iterator& operator-=(difference_type n); reference operator[](difference_type n) const; };
BidirectionalIterator,RandomAccessIteratorから進行方向の逆転(operator++で後退/operator–で前進)したイテレータを作ります。
#include <iostream> #include <iterator> #include "to_string.h" using namespace std; void std_reverse_iter() { cout << "reverse_iterator" << endl; const int N = 6; int array[N] = { 0, 1, 2, 3, 4, 5 }; cout << to_string(array,array+N) << " を逆順に出力: "; reverse_iterator<int*,int> first(array+N); reverse_iterator<int*,int> last(array); while ( first != last ) { cout << *first << ' '; ++first; } cout << endl; }
挿入イテレータ
back_insert_iterator
back_inserter
- template <class Container> class back_insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; public: typedef Container container_type; explicit back_insert_iterator(Container& x); back_insert_iterator<Container>& operator=(typename Container::const_reference value); back_insert_iterator<Container>& operator*(); back_insert_iterator<Container>& operator++(); back_insert_iterator<Container> operator++(int); };
コンストラクト時にメンバ関数push_backの定義されたコンテナcを与えておけば、operator=(x)されるたびにc.push_back(x)します。
- template <class Container> back_insert_iterator<Container> back_inserter(Container& x);
back_insert_iterator<Container>(x) を返します。
front_insert_iterator
front_inserter
- template <class Container> class front_insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; public: typedef Container container_type; explicit front_insert_iterator(Container& x); front_insert_iterator<Container>& operator=(typename Container::const_reference value); front_insert_iterator<Container>& operator*(); front_insert_iterator<Container>& operator++(); front_insert_iterator<Container> operator++(int); };
コンストラクト時にメンバ関数push_frontの定義されたコンテナcを与えておけば、operator=(x)されるたびにc.push_front(x)します。
- template <class Container> front_insert_iterator<Container> front_inserter(Container& x);
front_insert_iterator<Container>(x) を返します。
insert_iterator
inserter
- template <class Container> class insert_iterator : public iterator<output_iterator_tag,void,void,void,void> { protected: Container* container; typename Container::iterator iter; public: typedef Container container_type; insert_iterator(Container& x, typename Container::iterator i); insert_iterator<Container>& operator=(typename Container::const_reference value); insert_iterator<Container>& operator*(); insert_iterator<Container>& operator++(); insert_iterator<Container>& operator++(int); };
コンストラクト時にメンバ関数insertの定義されたコンテナcとイテレータiを与えておけば、operator=(x)されるたびにc.insert(i++,x)します。
- template <class Container, class Iterator> insert_iterator<Container> inserter(Container& x, Iterator i);
insert_iterator<Container>(x,i)を返します。
#include <iostream> #include <list> #include "to_string.h" using namespace std; void std_insert_iter() { cout << "back_insert_iterator, front_insert_iterator, insert_iterator" << endl; list<char> l; for ( int i = 0; i < 4; ++i ) l.push_back(i+'0'); const int N = 3; const char front[] = "ABC"; const char mid[] = "DEF"; const char back[] = "GHI"; list<char>::iterator it = l.begin(); advance(it,2); cout << to_string(l.begin(), it, l.end()) << " に " << to_string(mid,mid+N) << " を挿入: "; insert_iterator< list<char> > m(l,it); copy(mid, mid+N, m); cout << to_string(l.begin(), l.end()) << endl; cout << to_string(l.begin(), l.end()) << " に " << to_string(front,front+N) << " をpush_front: "; front_insert_iterator< list<char> > f(l); copy(front, front+N, f); cout << to_string(l.begin(), l.end()) << endl; cout << to_string(l.begin(), l.end()) << " に " << to_string(back,back+N) << " をpush_back: "; back_insert_iterator< list<char> > b(l); copy(back, back+N, b); cout << to_string(l.begin(), l.end()) << endl; } void std_inserter() { cout << "back_inserter, front_inserter, inserter" << endl; list<char> l; for ( int i = 0; i < 4; ++i ) l.push_back(i+'0'); const int N = 3; const char front[] = "ABC"; const char mid[] = "DEF"; const char back[] = "GHI"; list<char>::iterator it = l.begin(); advance(it,2); cout << to_string(l.begin(), it, l.end()) << " に " << to_string(mid,mid+N) << " を挿入: "; copy(mid, mid+N, inserter(l,it)); cout << to_string(l.begin(), l.end()) << endl; cout << to_string(l.begin(), l.end()) << " に " << to_string(front,front+N) << " をpush_front: "; copy(front, front+N, front_inserter(l)); cout << to_string(l.begin(), l.end()) << endl; cout << to_string(l.begin(), l.end()) << " に " << to_string(back,back+N) << " をpush_back: "; copy(back, back+N, back_inserter(l)); cout << to_string(l.begin(), l.end()) << endl; }
ストリームイテレータ
istream_iterator
- template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> class istream_iterator: public iterator<input_iterator_tag,T,Distance,const T*,const T&> { public: typedef charT char_type typedef traits traits_type; typedef basic_istream<charT,traits> istream_type; istream_iterator(); istream_iterator(istream_type& s); istream_iterator(const istream_iterator<T,charT,traits,Distance>& x); ~istream_iterator(); const T& operator*() const; const T* operator->() const; istream_iterator<T,charT,traits,Distance>& operator++(); istream_iterator<T,charT,traits,Distance> operator++(int); };
入力ストリームをInputIterator化します。
ostream_iterator
- template <class T, class charT = char, class traits = char_traits<charT> > class ostream_iterator: public iterator<output_iterator_tag, void, void, void, void> { public: typedef charT char_type; typedef traits traits_type; typedef basic_ostream<charT,traits> ostream_type; ostream_iterator(ostream_type& s); ostream_iterator(ostream_type& s, const charT* delimiter); ostream_iterator(const ostream_iterator<T,charT,traits>& x); ~ostream_iterator(); ostream_iterator<T,charT,traits>& operator=(const T& value); ostream_iterator<T,charT,traits>& operator*(); ostream_iterator<T,charT,traits>& operator++(); ostream_iterator<T,charT,traits>& operator++(int); private: // basic_ostream<charT,traits>* out_stream; exposition only // const char* delim; exposition only };
出力ストリームをOutputiterator化します。
istreambuf_iterator
- template<class charT, class traits = char_traits<charT> > class istreambuf_iterator : public iterator<input_iterator_tag, charT, typename traits::off_type, charT*, charT&> { public: typedef charT char_type; typedef traits traits_type; typedef typename traits::int_type int_type; typedef basic_streambuf<charT,traits> streambuf_type; typedef basic_istream<charT,traits> istream_type; class proxy; // exposition only public: istreambuf_iterator() throw(); istreambuf_iterator(istream_type& s) throw(); istreambuf_iterator(streambuf_type* s) throw(); istreambuf_iterator(const proxy& p) throw(); charT operator*() const; istreambuf_iterator<charT,traits>& operator++(); proxy operator++(int); bool equal(istreambuf_iterator& b); private: streambuf_type* sbuf_; exposition only };
入力ストリームバッファをInputIterator化します。
ostreambuf_iterator
- template <class charT, class traits = char_traits<charT> > class ostreambuf_iterator: public iterator<output_iterator_tag, void, void, void, void> { public: typedef charT char_type; typedef traits traits_type; typedef basic_streambuf<charT,traits> streambuf_type; typedef basic_ostream<charT,traits> ostream_type; public: ostreambuf_iterator(ostream_type& s) throw(); ostreambuf_iterator(streambuf_type* s) throw(); ostreambuf_iterator& operator=(charT c); ostreambuf_iterator& operator*(); ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int); bool failed() const throw(); private: streambuf_type* sbuf_; exposition only };
出力入力ストリームバッファをOutputIterator化します。
#include <iostream> #include <sstream> #include <string> #include <iterator> #include <cctype> using namespace std; void std_stream_iter() { cout << "istream_iterator, ostream_iterator" << endl; istringstream is("this string is on istringstream"); istream_iterator<string> first(is); istream_iterator<string> last; ostream_iterator<int> result(cout," "); cout << '"' << is.str() << "\" の各単語の長さ :"; while ( first != last ) { *result = first->size(); ++result; ++first; } cout << endl; } void std_streambuf_iter() { cout << "istreambuf_iterator, ostreambuf_iterator" << endl; istringstream is("this string is on istringstream"); istreambuf_iterator<char> first(is); istreambuf_iterator<char> last; ostreambuf_iterator<char> result(cout); cout << '"' << is.str() << "\" の各文字を大文字に :"; ctype<char> ct; while ( first != last ) { *result = ct.toupper(*first); ++result; ++first; } cout << endl; }