33.2 Iterator Adaptors

advertisement
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:
Download