960 STL Iterators Chapter 33 Iterator Operations (§iso.24.4.4) q=next(p,n) Like p+=n; p must be at least an input iterator Like x=q−p; p must be at least an input iterator Like q=p+n; p must be at least a forward iterator q=next(p) q=prev(p,n) q=next(p,1) Like q=p−n; p q=prev(p) q=prev(p,1) advance(p) x=distance(p,q) must be at least a bidirectional iterator In each case, if p is not a random-access iterator, the algorithm will take n steps. 33.2 Iterator Adaptors In <iterator>, the standard library provides adaptors to generate useful related iterator types from a given iterator type: Iterator Adaptors reverse_iterator back_insert_iterator front_inser t_iterator insert_iterator move_iterator raw_storage_iterator Iterate backward Insert at end Insert at beginning Insert anywhere Move rather than copy Write to uninitialized storage §33.2.1 §33.2.2 §33.2.2 §33.2.2 §33.2.3 §34.6.2. Iterators for iostreams are described in §38.5. 33.2.1 Reverse Iterator Using an iterator we can traverse a sequence [b:e) from b to e. If the sequence allows bidirectional access, we can also traverse the sequence in reverse order, from e to b. An iterator that does that is called a reverse_iterator. A reverse_iterator iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence. To get a half-open sequence, we must consider b−1 as one past the end and e−1 as the start of the sequence: [e−1,b−1). Thus, the fundamental relation between a reverse iterator and its corresponding iterator is &(reverse_iterator(p))==&(p−1). In particular, if v is a vector, v.rbegin() points to its last element, v[v.size()−1]. Consider: begin() end() A B C This sequence can be viewed like this using a reverse_iterator: Section 33.2.1 Reverse Iterator rbegin() 961 rend() C B A The definition of reverse_iterator looks something like this: template<typename Iter> class reverse_iterator : public iterator<Iterator_category<Iter>, Value_type<Iter>, Difference_type<Iter>, Pointer<Iter>, Reference<Iter>> { public: using iterator_type = Iter; reverse_iterator(): current{} { } explicit reverse_iterator(Iter p): current{p} { } template<typename Iter2> reverse_iterator(const reverse_iterator<Iter2>& p) :current(p.base()) { } Iter base() const { return current; } // current iterator value reference operator() const { tmp = current; return −−tmp; } pointer operator−>() const; reference operator[](difference_type n) const; reverse_iterator& operator++() { −−current; return this; } // note: not ++ reverse_iterator operator++(int) { reverse_iterator t = current; −−current; return t; } reverse_iterator& operator−−() { ++current; return this; } // note: not −− reverse_iterator operator−−(int) { reverse_iterator t = current; ++current; return t; } 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); // ... protected: Iterator current; // current points to the element after the one *this refers to private: // ... iterator tmp; // for temporaries that need to outlive a function scope }; A reverse_iterator<Iter> has the same member types and operations as Iter. In particular, if Iter is a random-access operator, its reverse_iterator<Iter> has [], +, and <. For example: