Team LiB   Previous Section   Next Section

13.31 <iterator>

The <iterator> header declares classes and templates for defining and using iterators. (See Chapter 10.) Iterators are especially important when using the standard algorithms in <algorithm>.

An iterator gives a program access to the contents of a container or other sequence, such as an I/O stream. You can think of an iterator as an abstraction of a pointer; the syntax for using iterators resembles that of pointers. Conceptually, an iterator points to a single element in a container or sequence and can be advanced to the next element with the ++ (increment) operator. The unary * (dereference) operator returns the element that the iterator points to. Iterators (except for output iterators) can be compared: two iterators are equal if they point to the same position in the same sequence, or if they both point to one position past the end of the same sequence.

There are five categories of iterators:

Input iterators

Permit one pass to read a sequence. The increment operator advances to the next element, but there is no decrement operator. The dereference operator does not return an lvalue, so you can read elements but not modify them.

Output iterators

Permit one pass to write a sequence. The increment operator advances to the next element, but there is no decrement operator. You can dereference an element only to assign a value to it. You cannot compare output iterators.

Forward iterators

Are like a combination of an input and an output iterator. You can use a forward iterator anywhere an input iterator is required or where an output iterator is required. A forward iterator, as its name implies, permits unidirectional access to a sequence. You can refer to a single element and modify it multiple times before advancing the iterator.

Bidirectional iterators

Are like forward iterators but also support the decrement operator (--) to move the iterator backward by one position.

Random access iterators

Are like bidirectional iterators but also support the [] (subscript) operator to access any index in the sequence. Also, you can add or subtract an integer to move a random access iterator by more than one position at a time. Subtracting two random access iterators yields an integer distance between them. Thus, a random access iterator is most like a conventional pointer, and, in fact, a pointer can be used as a random access iterator.

An input, forward, bidirectional, or random access iterator can be a const_iterator. Dereferencing a const_iterator yields a constant (an rvalue or a const lvalue). Chapter 10 discusses const_iterators in more depth.

An iterator can point to any element in a sequence or to one position past the end. You cannot dereference an iterator that points to one past the end, but you can compare it with other iterators (provided it is not an output iterator) or, if it is a bidirectional or random access iterator, decrease its position so it points to a valid element of the sequence.

Iterators are often used in ranges. A range has two iterators: a starting point and an ending point. The end iterator typically points to one position past the last element in the range. Thus, a range is often written using the mathematical notation of [first, last), in which the square bracket means first is included in the range, and the parenthesis means last is excluded from the range.

Like ordinary pointers, iterators can be uninitialized or otherwise have invalid values, such as x.begin( ) - 1, in which x is any container. It is your responsibility to ensure that you dereference only valid iterators, that you don't let iterators run past their valid end-points, and so on.

To create your own iterator class, see the iterator class template.

advance function template Moves iterator forward or backward

template <typename InputIterator, typename Distance>
  void advance(InputIterator& i, Distance n);

The advance function template advances an input iterator i by a distance n. If the iterator is bidirectional or random access, n can be negative. If the iterator is random access, the advance function is specialized as i + n; other iterators apply the ++ operator n times (or -- for a bidirectional iterator when n is negative).

See Also

distance function template

back_insert_iterator class template Output iterator to push items back onto a container

template <typename 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);
};

The back_insert_iterator class template implements an output iterator that stores elements in a container by calling the container's push_back function. The most convenient way to create a back_insert_iterator object is to use the back_inserter function template.

The way back_insert_iterator works seems slightly unconventional, although it is perfectly reasonable for an output iterator: the * operator returns the iterator, not an element of the container. Thus, the expression *iter = value assigns value to the iterator itself. The iterator's assignment operator appends value to the underlying container by calling the container's push_back function. Thus, the iterator does not maintain any notion of a position, and the increment operator is a no-op.

The following are the member functions of back_insert_iterator:

explicit back_insert_iterator(Container& x)

Initializes the container member with &x.

back_insert_iterator<Container>& operator=(typename Container::const_reference value)

Calls container->push_back(value). The return value is *this.

back_insert_iterator<Container>& operator*( )

Returns *this.

back_insert_iterator<Container>& operator++( )
back_insert_iterator<Container> operator++(int)

Returns *this with no side effects.

See Also

back_inserter function template, front_insert_iterator class template, insert_iterator class template

back_inserter function template Creates a back_insert_iterator

template <typename Container>
  back_insert_iterator<Container> back_inserter(Container& x);

The back_inserter function template constructs a back_insert_iterator object for the container x. Example 13-18 shows how to use back_inserter to read integers from a file into a vector.

Example

Example 13-18. Using back_inserter to add numbers to a vector
std::ifstream in("experiment.dat");
std::vector<int> data;
std::copy(std::istream_iterator<int>(in),
          std::istream_iterator<int>(  ),
          std::back_inserter(data));

See Also

back_insert_iterator class template, front_inserter function template, inserter function template

bidirectional_iterator_tag class Tag for a bidirectional iterator

struct bidirectional_iterator_tag :
  public forward_iterator_tag {};

Use the bidirectional_iterator_tag class as the iterator category when declaring a new bidirectional iterator class. When writing a generic algorithm or similar function, you can use the iterator's category to write specialized implementations for different kinds of iterators. See Example 13-19 (under the distance function template).

See Also

bidirectional_iterator_tag class, forward_iterator_tag class, input_iterator_tag class, iterator class template, output_iterator_tag class, random_access_iterator_tag class

distance function template Counts elements between two iterators

template<typename InputIterator>
  typename iterator_traits<InputIterator>::difference_type
    distance(InputIterator first, InputIterator last);

The distance function returns the number of elements between first and last. The function is specialized for random access iterators to use the - operator; for other input iterators, the function applies the ++ operator to first until first == last. The behavior is undefined if first and last refer to different containers or if last points to an element earlier than first.

Example 13-19 shows a simple implementation of the distance function. The first specialized implementation works for any iterator (except output iterators, which do not support comparison with the != operator). The second one works only with random access iterators and uses the subtraction operator to compute the distance in constant time. The compiler picks the more specialized function when it can, so random access iterators can compute distances in constant time, compared to linear time for other iterators.

Example

Example 13-19. A simple implementation of distance
namespace std {
  template<typename InputIter>
  typename iterator_traits<InputIter>::difference_type
  specialize_distance(InputIter first, InputIter last, ...)
  {
    typename iterator_traits<InputIter>::difference_type n;
    for (n = 0; first != last; ++first)
      ++n;
    return n;
  }
   
  template<typename InputIter>
  typename iterator_traits<InputIter>::difference_type
  specialize_distance(InputIter first, InputIter last,
                      random_access_iterator_tag)
  {
    return last - first;
  }
   
  template<typename InputIter>
  typename iterator_traits<InputIter>::difference_type
  distance(InputIter first, InputIter last)
  {
    return specialize_distance(first, last,
      iterator_traits<InputIter>::iterator_category(  ));
  }
}

See Also

advance function template

forward_iterator_tag class Tag for a forward iterator

struct forward_iterator_tag : public input_iterator_tag {};

Use the forward_iterator_tag class as the iterator category when declaring a new forward iterator class. When writing a generic algorithm or similar function, you can use the iterator's category to write specialized implementations for different kinds of iterators. See Example 13-19 (under the distance function template).

See Also

bidirectional_iterator_tag class, forward_iterator_tag class, input_iterator_tag class, iterator class template, output_iterator_tag class, random_access_iterator_tag class

front_insert_iterator class template Iterator to insert elements at the front of a container

template <typename 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);
};

The front_insert_iterator class template implements an output iterator that stores elements in a container by calling the container's push_front function. The most convenient way to create a front_insert_iterator object is to use the front_inserter function template.

The way front_insert_iterator works seems slightly unconventional, although it is perfectly reasonable for an output iterator: the * operator returns the iterator, not an element of the container. Thus, the expression *iter = value assigns value to the iterator itself. The iterator's assignment operator adds value to the underlying container by calling the container's push_front function. Thus, the iterator does not maintain any notion of a position, and the increment operator is a no-op.

The following are the member functions of front_insert_iterator:

explicit front_insert_iterator(Container& x)

Initializes the container member with &x.

front_insert_iterator<Container>& operator=(typename Container::const_reference value)

Calls container->push_front(value). The return value is *this.

front_insert_iterator<Container>& operator*( )

Returns *this.

front_insert_iterator<Container>& operator++( )
front_insert_iterator<Container> operator++(int)

Returns *this with no side effects.

See Also

back_insert_iterator class template, front_inserter function template, insert_iterator class template

front_inserter function template Creates a front_insert_iterator

template <typename Container>
  front_insert_iterator<Container>
    front_inserter(Container& x);

The front_inserter function template constructs a front_insert_iterator object for the container x. Example 13-20 shows how to use front_inserter to read integers from a file into a list in reverse order.

Example

Example 13-20. Using a front_inserter to add numbers to a list
std::ifstream in("experiment.dat");
std::list<int> data;
std::copy(std::istream_iterator<int>(in),
          std::istream_iterator<int>(  ),
          std::front_inserter(data));

See Also

back_inserter function template, front_insert_iterator class template, inserter function template

input_iterator_tag class Tag for an input iterator

struct input_iterator_tag {};

Use the input_iterator_tag class as the iterator category when declaring a new input iterator class. When writing a generic algorithm or similar function, you can use the iterator's category to write specialized implementations for different kinds of iterators. See Example 13-19 (under the distance function template).

See Also

bidirectional_iterator_tag class, forward_iterator_tag class, iterator class template, output_iterator_tag class, random_access_iterator_tag class

insert_iterator class template Iterator to insert elements in a 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& cont, typename Container::iterator iter);
  insert_iterator<Container>&
    operator=(typename Container::const_reference value);
  insert_iterator<Container>& operator*(  );
  insert_iterator<Container>& operator++(  );
  insert_iterator<Container>& operator++(int);
};

The insert_iterator class template implements an output iterator that stores elements in a container by calling the container's insert function. The most convenient way to create a insert_iterator object is to use the inserter function template.

The way insert_iterator works seems slightly unconventional, although it is perfectly reasonable for an output iterator: the * operator returns the iterator, not an element of the container. Thus, the expression *iter = value assigns value to the iterator itself. The iterator's assignment operator adds value to the underlying container by calling the container's insert function. Thus, the iterator does not maintain any notion of a position, and the increment operator is a no-op.

The following are the member functions of insert_iterator:

insert_iterator(Container& x, typename Container::iterator i)

Initializes the container member with &x and iter with i. Thus, the elements to be inserted in the container will be inserted at position i.

insert_iterator<Container>& operator=(typename Container::const_reference value)

Assigns a value to an element in the iterator's container, performing the equivalent of the following:

iter = container->insert(iter, value);
++iter;
return *this;
insert_iterator<Container>& operator*( )

Returns *this.

insert_iterator<Container>& operator++( )
insert_iterator<Container> operator++(int)

Returns *this with no side effects.

See Also

back_insert_iterator class template, front_insert_iterator class template, inserter function template

inserter function template Creates an insert_iterator

template <typename Container, typename Iterator>
  insert_iterator<Container>
    inserter(Container& x, Iterator i);

The inserter function template constructs an insert_iterator object for the container x to insert items starting at position i. Figure 13-22 illustrates a simple use of the inserter function.

Figure 13-22. Using inserter to insert a vector in the middle of another vector
figs/cppn_1322.gif

See Also

back_inserter function template, front_inserter function template, insert_iterator class template

istream_iterator class template Input iterator to read items from an istream

template <typename T, typename charT = char, 
          typename traits = char_traits<charT>, typename 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& stream);
  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);
};

The istream_iterator class template wraps an input iterator around an input stream (an instance of basic_istream), making the stream appear to be a sequence of items, each of type T.

Example 13-20 (under the front_inserter function template) shows how an istream_iterator can be used to read a series of integers from a file.

The following are the member functions of istream_iterator:

istream_iterator( )

Constructs an istream_iterator that denotes the end of the stream. End-of-stream iterators are equal to each other and are not equal to any other istream_iterator.

istream_iterator(istream_type& stream)

Constructs an istream_iterator to read from a stream. The constructor might read the first item from the stream. An istream_iterator that wraps a stream is equal to an end-of-stream iterator when stream.eof( ) is true.

istream_iterator(const istream_iterator<T,charT,traits,Distance>& iter)

Constructs a copy of iter. Note that two istream_iterator objects are the same (operator== is true) if they point to the same stream object.

const T& operator*( ) const

Returns the item that was read most recently from the stream.

const T* operator->( ) const istream_iterator<T,charT,traits,Distance>& operator++( )

Returns a pointer to the item that was read most recently from the stream.

istream_iterator<T,charT,traits,Distance>operator++(int)

Reads the next item from the stream using operator>>. The return value is *this.

See Also

istreambuf_iterator class template, ostream_iterator class template, basic_istream in <istream>

istreambuf_iterator class template Input iterator to read characters from a streambuf

template<typename charT, typename 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

  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) const;
};

The istreambuf_iterator class template wraps a stream buffer object (instance of basic_streambuf) as an input iterator to read characters from the stream buffer. Example 13-21 shows how to use streambuf_iterators to copy files.

Examples

Example 13-21. Copying files using streambuf iterators
void copyfile(const char* from, const char* to)
{
  std::ifstream in(from);
  std::ofstream out(to);
   
  std::copy(std::istreambuf_iterator<char>(in),
            std::istreambuf_iterator<char>(  ),
            std::ostreambuf_iterator<char>(out));
}

The post-increment operator (++) returns a proxy object, which is an object that stands in for the istreambuf_iterator object. Its use is largely transparent, and you rarely need to think about it. The definition and name of the proxy class are implementation-defined, but the class has at least the capability to return the input character and the underlying stream buffer. This section assumes that the class name is proxy. Example 13-22 shows a prototypical implementation of proxy.

Example 13-22. A trivial implementation of the proxy class
template<typename charT, typename traits=char_traits<charT> >
class istreambuf_iterator<charT, traits>::proxy
{
  friend template<typename charT, typename traits>
    class istreambuf_iterator<charT,traits>;
  charT keep;
  basic_streambuf<charT,traits>* sbuf;
  proxy(charT c, basic_streambuf<charT,traits>* sbuf);
    : keep(c), sbuf(sbuf) {}
public:
  charT operator*(  ) { return keep; }
};

In the following descriptions of the member functions of istreambuf_iterator, the data member sbuf is a pointer to the iterator's stream buffer. The sbuf member serves only to keep the function descriptions clear and simple; the class is not required to have such a member, nor is the class required to have a member with that name.

istreambuf_iterator( ) throw( )

Constructs the end-of-stream iterator.

istreambuf_iterator(istream_type& s) throw( )
istreambuf_iterator(streambuf_type* sb) throw( )
istreambuf_iterator (const proxy& p) throw( )

Constructs an istreambuf_iterator and initializes sbuf to s.rdbuf( ), sb, or p.sbuf. If sb == 0, an end-of-stream iterator is constructed.

charT operator*( ) const

Returns sbuf->sgetc( ).

istreambuf_iterator<charT,traits>& operator++( )

Calls sbuf->sbumpc( ) and returns *this.

proxy operator++ (int)

Returns proxy(sbuf->sbumpc( ), sbuf).

bool equal(istreambuf_iterator& b) const

Returns true if both iterators are end-of-stream iterators or if neither iterator is an end-of-stream iterator. The iterators do not have to use the same stream buffer.

See Also

istream_iterator class template, ostreambuf_iterator class template, basic_streambuf in <streambuf>

iterator class template Iterator base-class template

template<typename Category, typename T, typename Difference = ptrdiff_t,
         typename Pointer = T*, typename Reference = T&>
struct iterator{
  typedef T value_type;
  typedef Difference difference_type;
  typedef Pointer pointer;
  typedef Reference reference;
  typedef Category iterator_category;
};

The iterator class template is a convenient base-class template to use when implementing your own iterator.

The following are the template parameters, which are all type parameters:

Category

Must be one of the five iterator category tags: bidirectional_iterator_tag, forward_iterator_tag, input_iterator_tag, output_iterator_tag, or random_access_iterator_tag.

T

The element type. It can be void for an output iterator because you cannot dereference an output iterator.

Difference

An integral type that represents the distance between two iterators. It can be void for an output iterator because you cannot measure the distance between two output iterators. This parameter is optional; the default is ptrdiff_t, which is suitable for typical pointer-like iterators.

Pointer

The pointer-to-element type. This parameter is optional; the default is T*, which is correct for most iterators.

Reference

The reference-to-element type. This parameter is optional; the default is T&, which is correct for most iterators.

See Also

iterator_traits class template, reverse_iterator class template

iterator_traits class template Iterator traits

template<typename 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;
};

The iterator_traits class template declares traits for an iterator. If you use the iterator class template as the base for your custom iterator, you don't need to specialize iterator_traits. If you are writing a custom container or algorithm, you should always use iterator_traits to obtain the traits of an iterator. If you use a plain pointer as an iterator, the standard library specializes iterator_traits for you. See the next subsection.

If you write your own specialization, the iterator_category type must be one of the five iterator tag classes. (See the iterator class template.) For an output iterator, difference_type and value_type are void.

When writing a generic algorithm or other function that uses iterators, you can use iterator_traits to specialize the behavior for certain kinds of iterators. See Example 13-19 (under distance), which shows how iterator traits can be used to improve the performance of a function.

See Also

iterator class template

iterator_traits<T*> template specialization Iterator traits specialized for pointers

template<typename  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;
};

The iterator_traits class template is specialized for pointers. This specialization lets you use a pointer as a random access iterator.

See Also

iterator_traits class template

iterator_traits<const T*> template specialization Iterator traits specialized for pointers to const

template<typename  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;
};

The iterator_traits class template is specialized for pointers to const. This specialization lets you use a pointer as a random access iterator.

See Also

iterator_traits class template

ostream_iterator class template Output iterator to write items to an ostream

template <typename T, typename charT = char,  
          typename 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);
};

The ostream_iterator class template wraps an output iterator around an output stream (instance of basic_ostream), making the stream appear to be a sequence of items, each of type T. For example, suppose you have a vector of data. You can print the data, one number per line, by using an ostream_iterator:

std::vector<int> data;
 . . .  // Acquire data.
std::copy(data.begin(  ), data.end(  ), 
          std::ostream_iterator(std::cout, "\n"));

The following are the member functions of ostream_iterator:

ostream_iterator(ostream_type& stream)
ostream_iterator(ostream_type& stream, const charT* delimiter)
ostream_iterator(const ostream_iterator<T,charT,traits>& x)

Prepares to write items to stream. If delimiter is present, it will be written after each item. The copy constructor copies the reference to the stream and to the delimiter from x.

ostream_iterator<T,charT,traits>& operator=(const T& value)

Writes value to the stream using operator<<. If the ostream_iterator has a delimiter, it is written after value. The return value is *this.

ostream_iterator<T,charT,traits>& operator*( )

Returns *this.

ostream_iterator<T,charT,traits>& operator++( )
ostream_iterator<T,charT,traits>& operator++(int)

Returns *this with no side effects.

See Also

istream_iterator class template, ostreambuf_iterator class template, basic_ostream in <ostream>

ostreambuf_iterator class template Output iterator to write characters to a streambuf

template<typename charT, typename 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;

  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(  );
};

The ostreambuf_iterator class template wraps a basic_streambuf object as an output iterator to write characters to the stream buffer. Example 13-21 (under istreambuf_iterator) shows how to use streambuf iterators to copy files.

In the following descriptions of the member functions of ostreambuf_iterator, the data member sbuf is a pointer to the iterator's stream buffer. The sbuf member serves only to keep the function descriptions clear and simple; the class is not required to have such a member, or a member with that name.

ostreambuf_iterator(ostream_type& s) throw( )
ostreambuf_iterator(streambuf_type* sb) throw( )

Saves the stream buffer s.rdbuf( ) or sb in sbuf.

ostreambuf_iterator& operator=(charT c)

Calls sbuf->sputc(c) (only if failed( ) returns false) and returns *this.

ostreambuf_iterator& operator*( )

Returns *this.

ostreambuf_iterator& operator++( )
ostreambuf_iterator& operator++(int)

Returns *this.

bool failed( ) const throw( )

Returns true if sbuf->sputc( ) ever returned traits::eof( ). Otherwise, it returns false.

See Also

istreambuf_iterator class template, ostream_iterator class template, basic_streambuf in <streambuf>

output_iterator_tag class Tag for an output iterator

struct output_iterator_tag {};

Use the output_iterator_tag class as the iterator category when declaring a new output iterator class. When writing a generic algorithm or similar function, you can use the iterator's category to write specialized implementations for different kinds of iterators. See Example 13-19 (under the distance function template).

See Also

bidirectional_iterator_tag class, forward_iterator_tag class, input_iterator_tag class, iterator class template, random_access_iterator_tag class

random_access_iterator_tag class Tag for a random access iterator

struct random_access_iterator_tag :
  public bidirectional_iterator_tag {};

Use the random_access_iterator_tag class as the iterator category when declaring a new random access iterator class. When writing a generic algorithm or similar function, you can use the iterator's category to write specialized implementations for different kinds of iterators. See Example 13-19 (under the distance function template).

See Also

bidirectional_iterator_tag class, forward_iterator_tag class, input_iterator_tag class, iterator class template, output_iterator_tag class

reverse_iterator class template Iterator wrapper to reverse direction

template <typename 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 <typename 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;
};

The reverse_iterator class template is an adapter for a bidirectional or random access iterator to iterate the sequence in the opposite direction of the adapted iterator. In other words, if the adapted iterator advances from the first to the last item in a container, a reverse iterator starts with the last items and "advances" to the first item. In addition to the reverse_iterator template, there are also several function templates for the comparison and arithmetic (+ and -) operators.

The standard containers return reverse_iterator objects from the rbegin( ) and rend( ) functions. The following example shows a simple implementation of these functions:

reverse_iterator rbegin(  ) { return reverse_iterator(end(  )); }
reverse_iterator rend(  ) { return reverse_iterator(begin(  )); }

Because an iterator can point to one past the last item in a container but cannot point to one item before the first, a reverse iterator conceptually points to one item before the position to which the adapted iterator points. In other words, given an iterator, iter, which points to 42 in Example 13-23, if you construct a reverse iterator that adapts iter, the reverse iterator appears to point to 29. When you increment the reverse iterator, it decrements the adapted iterator. Thus, the "next" element in the sequence of the reverse iterator is 12. (The adapted iterator points to 29.) The adapted iterator is also called the base iterator. See Chapter 10 for a discussion of some of the interesting ramifications of using reverse_iterator.

Figure 13-23. How a reverse iterator works
figs/cppn_1323.gif

The following member functions of reverse_iterator refer to adapted as the data member that stores the base( ) iterator. The adapted member is purely a convenience for the function descriptions and is not necessarily part of any real implementation of reverse_iterator:

reverse_iterator( )

Initializes the adapted data member with its default constructor.

explicit reverse_iterator(Iterator iter)

Initializes the adapted data member to iter.

template <typename U> reverse_iterator(const reverse_iterator<U>& ri)

Initializes the adapted data member to ri.base( ).

Iterator base( ) const

Returns the adapted iterator, adapted. Note that the adapted iterator points to one position after the reverse iterator's logical position.

reference operator*( ) const

Returns a reference to the item that the reverse iterator logically points to, which is one item before the item to which base( ) points. Thus, you can think of the dereference function working as follows:

reference operator*(  ) const {
  iterator_type tmp = base(  );
  --tmp;
  return *tmp;
}
pointer operator->( ) const

Returns a pointer to the item that the reverse iterator logically points to, that is, &(operator*( )).

reverse_iterator& operator++( )

Decrements adapted and returns *this.

reverse_iterator operator++(int)

Saves a copy of the current item (operator*( )), decrements adapted, and returns the saved item.

reverse_iterator& operator--( )

Increments adapted and returns *this.

reverse_iterator operator--(int)

Saves a copy of the current item (operator*( )), increments adapted, and returns the saved item.

reverse_iterator operator+(difference_type n) const

Returns reverse_iterator(base( ) - n).

reverse_iterator& operator+=(difference_type n)

Subtracts n from adapted and returns *this.

reverse_iterator operator-(difference_type n) const

Returns reverse_iterator(base( ) + n).

reverse_iterator& operator-=(difference_type n)

Adds n to adapted and returns *this.

reference operator[](difference_type n) const

Returns base( )[-n-1].

The following are several nonmember functions that compare reverse iterators and perform basic arithmetic such as finding the distance between two reverse iterators and advancing a reverse iterator by an integer:

template <typename Iterator>
bool operator==(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when the base iterators are equal, that is, x.base( ) == y.base( ).

template <typename Iterator>
bool operator!=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when x and y have different base iterators, that is, x.base( ) != y.base( ).

template <typename Iterator>
bool operator<(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when x is closer than y to the beginning of the sequence. Because x and y are reverse iterators, the function returns y.base( ) < x.base( ).

template <typename Iterator>
bool operator>(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when x is farther than y from the beginning of the sequence. Because x and y are reverse iterators, the function returns y.base( ) > x.base( ).

template <typename Iterator>
bool operator>=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when x is farther than y from the beginning of the sequence or x equals y. Because x and y are reverse iterators, the function returns y.base( ) >= x.base( ).

template <typename Iterator>
bool operator<=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns true when x is closer than y to the beginning of the sequence or x equals y. Because x and y are reverse iterators, the function returns y.base( ) <= x.base( ).

template <typename Iterator>
typename reverse_iterator<Iterator>::difference_type
operator-(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)

Returns the distance between two reverse iterators, that is, y.base( ) - x.base( ).

template <typename Iter>
reverse_iterator<Iter>
operator+(typename reverse_iterator<Iter>::difference_type n, constreverse_iterator<Iter>& ri)

Advances a reverse iterator ri by n. This function is a counterpart to the operator+ member function, allowing you to write ri + n and n + ri, which yield the same result.

See Also

iterator class template, Chapter 10

    Team LiB   Previous Section   Next Section