How to make sure iterators do not overpass end()?

Wok picture Wok · Oct 4, 2010 · Viewed 10.9k times · Source

I have been using advance on some iterators, but I am afraid of a possible leapfrog above end(). I would like to make sure my iterators stay between the bounds, I thought of the distance but it seems it does not return what I would be expecting (non-positive values when iterators overpass end()). How would you make sure there is no leapfrog?

#include <iostream>
#include <iterator>
#include <list>
using namespace std;

int main () {
  list<int> mylist;
  for (int i=0; i<10; i++) mylist.push_back (i*10);

  list<int>::const_iterator first = mylist.begin();
  const list<int>::const_iterator last = mylist.end();

  cout << "The distance is: " << distance(first,last) << endl; // 10
  advance(first, 10);
  cout << "The distance is: " << distance(first,last) << endl; // 0
  advance(first, 1);
  cout << "The distance is: " << distance(first,last) << endl; // 10
  advance(first, 10);
  cout << "The distance is: " << distance(first,last) << endl; // 0

  return 0;
}

Here is the output:

The distance is: 10
The distance is: 0
The distance is: 10
The distance is: 0

Answer

Steve Townsend picture Steve Townsend · Oct 4, 2010

advance() past end() results in undefined behaviour. You are going to have to test as you go per this snippet:

  template <class Iter, class Incr>
  void safe_advance(Iter& curr, const Iter& end, Incr n)
  {
    size_t remaining(std::distance(curr, end));
    if (remaining < n)
    {
      n = remaining;
    }
    std::advance(curr, n);
  }

You need to think about what happens when you don't move the full amount (curr returned as end().