For some reason the following code fails. You can’t simply erase a reverse_iterator by using its base() method.
#include <set> #include <iostream> int main() { std::set<int> setOfInts; setOfInts.insert(1); setOfInts.insert(2); setOfInts.insert(3); std::set<int>::reverse_iterator rev_iter = setOfInts.rbegin(); std::set<int>::reverse_iterator nextRevIter = setOfInts.rbegin(); ++nextIter; while ( rev_iter != setOfInts.rend()) { // Find 3 and try to erase if (*rev_iter == 3) { // SEGFAULT HERE setOfInts.erase( rev_iter.base()); } rev_iter = nextRevIter; ++nextRevIter; } }
How does one go about correctly doing the above? Given a reverse_iterator that corresponds to something you want to erase, how do you erase it?
Note, erase won’t take reverse_iterators unfortunately. It wants the real thing.
Related Questions
No related questions found
Apparently the solution is what base() returns is 1 off. The following identity holds for a reverse_iterator:
Or in other words, the reverse_iterator is always one pass the regular iterator it is the base of. Not sure why.
In GCC
Simply change
to
I’m definitely curious though as to why the identity above makes sense.
In Visual Studio
Coming back into work and trying this in visual studio, I see the above solution doesn’t quite work. The ‘nextIter’ becomes invalid on the erase. Instead, you need to save away the temporary from the erase to get the next iterator instead of keeping around a nextIter like above.
So the final solution is
Note, associative containers do not return an iterator from erase. So this solution wouldn’t work for map, multimap, etc.