I have a method that takes a stl reverse iterator, does some work, erases the element, and returns an iterator pointing to the next element. For example:

#include <vector>
std::vector<int> int_vector;
using ReverseIteratorType = decltype(int_vector)::reverse_iterator;

void do_stuff();

ReverseIteratorType erase_with_reverse_iter(ReverseIteratorType iter)
{
    do_stuff();
    std::advance(iter, 1);
    int_vector.erase(iter.base());
    return iter;
}

This compiles without warnings and appears to work correctly. The problem is that when running this code with libstdc++ that verifies every iterator is valid when it is used, an exception is thrown if iter points to the last element of a collection because the iterator is treated as a singular iterator after erase, and calling the copy constructor of a singular iterator is disallowed. (There is a deeper explanation of the issue from another post here.).

godbolt example demonstrating the issue here

Two questions

  1. Is the disallowing of the copying of a singular iterator a violation of the standard, or is this a sanity check by libstdc++?
  2. How would you refactor this to avoid the issue?
1

There are 1 best solutions below

0
Ben Voigt On

You should not ignore the return value of erase().

erase() invalidates iterators (and pointers and references) to elements at and after the erased element (in container order, not iterator order. That includes the iterator passed in as a parameter.

You can use the iterator returned from erase(), but it isn't a reverse iterator. So you have to convert it back again.