2.5.2 Iterator Successors and Predecessors

What was the problem

There are many kind of iterators: forward iterators, that can be incremented one step at a time with operator++, bidirectional iterators, that can additionally be decremented with operator-, and random access iterators, that can be incremented or decremented by any amount at once.

When writing a function taking an iterator whose type is templated, incrementing an iterator by more than one unit cannot be done directly, as it would fail for non-random iterators. Prior to C++11, this was done with std::advance().

template<typename Iterator, typename F> 
void every_n_items 
(Iterator it, std::size_t count, std::size_t step, F f) 
{ 
  for (; count > step; count -= step) 
  { 
    f(*it); 
    std::advance(it, step); 
  } 
}

std::advance() accepts a negative distance, in which case it will advance… hum… backwards. Note that the function modifies its argument, so using it to get another iterator from a given one is cumbersome:

template<typename Iterator> 
void inplace_adjacent_sums(Iterator first, const Iterator& last) 
{ 
  if (first == last) 
    return; 
 
  // Two steps to get an iterator on the second element. Ideally we 
  // would have wanted to limit its scope to the loop too. 
  Iterator second = first; 
  std::advance(second, 1); 
 
  for (; second != last; ) 
  { 
    *first += *second; 
    first = second; 
    std::advance(second, 1); 
  } 
}
How the Problem is Solved

PIC <iterator>

C++11 introduces the replacement functions std::prev() and std::next(), which are mostly here to make things clear and more convenient. The former is to be used to move the iterator backwards, while the latter is used to move it forward. If no distance is passed, then it defaults to one.

Note that they return a copy of the new iterator, instead of modifying its argument.

template<typename Iterator> 
void inplace_adjacent_sums(Iterator first, const Iterator& last) 
{ 
  if (first == last) 
    return; 
 
  // Here we can initialize the second iterator in the loop, reducing 
  // its scope. 
  for (Iterator second = std::next(first); second != last; ) 
  { 
    *first += *second; 
    first = second; 
    std::advance(second, 1); 
  } 
}