Why doesn't erase support for reverse iterators?

I just wrote the following code and was very surprised that it does not compile:

std::deque<int> container; // filling the container... for (auto it = container.rbegin(); it != container.rend(); ++it) if (*it == 5) { container.erase(it); break; } 

As you can see, I want to remove the last item that matches certain criteria, if any.

Mistake

there is no corresponding function to call std :: Deque :: Erase (std :: reverse_iterator ...

At first, I did not think that this was caused by a reverse iterator, but it really is, since rbegin / rend replaces rbegin with begin / end .

So, 2 questions:

  • Why is this not supported? Is this just one of those little things that the C ++ committee forgot to include in the standard, or is there no excuse for this overload?
  • What is the most elegant way to do what I want? Am I stuck with iterating over an index?
+7
c ++ containers erase
source share
1 answer

I cannot answer the question “why”, but answer “how” - you should call base() on your iterator. It is going to bring the correct iterator forward.

In doing so, consider the relationship between reverse and forward iterators. this may be confusing at first, but actually quite simple. If you have a std::vector containing the following elements:

 1, 2, 3, 4, 5 

And you have reverse_iterator rit, which when dereferenced gives you 3, then *(rit.base) will be 4. To understand why, just remember that in normal iterators begin() is dereferenced, but end() not. In reverse iterators, the property must be the same - rbegin() must be dereferenced, but rend() must not - that is, it must point outside the beginning of the container.

Since, by definition, rend.base() same as begin() (since rend can be constructed as reverse_iterator(begin()) , the only way this can be rend.base() if rend.base() returns the next right element one after the start - begin() . It is easy to see that the same symmetry holds for rend() .

+1
source share

All Articles