Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call erase with a reverse iterator

Tags:

c++

People also ask

How do you use reverse iterator?

C++ Iterators Reverse Iterators A reverse iterator is made from a bidirectional, or random access iterator which it keeps as a member which can be accessed through base() . To iterate backwards use rbegin() and rend() as the iterators for the end of the collection, and the start of the collection respectively.

What is erase return C++?

The list::erase() is a built-in function in C++ STL which is used to delete elements from a list container. This function can be used to remove a single element or a range of elements from the specified list container.


After some more research and testing I found the solution. Apparently according to the standard [24.4.1/1] the relationship between i.base() and i is:

&*(reverse_iterator(i)) == &*(i - 1)

(from a Dr. Dobbs article):

alt text

So you need to apply an offset when getting the base(). Therefore the solution is:

m_CursorStack.erase( --(i.base()) );

EDIT

Updating for C++11.

reverse_iterator i is unchanged:

m_CursorStack.erase( std::next(i).base() );

reverse_iterator i is advanced:

std::advance(i, 1);
m_CursorStack.erase( i.base() );

I find this much clearer than my previous solution. Use whichever you require.


Please note that m_CursorStack.erase( (++i).base()) may be a problem if used in a for loop (see original question) because it changes the value of i. Correct expression is m_CursorStack.erase((i+1).base())


Funny that there is no correct solution on this page yet. So, the following is the correct one:

In case of the forward iterator the solution is straight forward:

std::list< int >::iterator i = myList.begin();
while ( i != myList.end() ) {
  if ( *i == to_delete ) {
    i = myList.erase( i );
  } else {
    ++i;
  } 
}

In case of reverse iterator you need to do the same:

std::list< int >::reverse_iterator i = myList.rbegin();
while ( i != myList.rend() ) {
  if ( *i == to_delete ) {
    i = decltype(i)(myList.erase( std::next(i).base() ));
  } else {
    ++i;
  } 
}

Notes:

  • You can construct a reverse_iterator from an iterator
  • You can use the return value of std::list::erase

... or another way to remove this element from the list?

This requires the -std=c++11 flag (for auto):

auto it=vt.end();
while (it>vt.begin())
{
    it--;
    if (*it == pCursor) //{ delete *it;
        it = vt.erase(it); //}
}