Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently remove last element from std::list

Tags:

c++

list

std

c++11

stl

This seems like a simple problem, and it is certainly doable, but I'd like to do it efficiently.

The Objective:
Remove the last element from a std::list if it meets a condition.

The Problem:
My compiler (MSVC++ 10) is unhappy about casting a reverse iterator to a const iterator for a method call to std::list.erase(). The message is:

error C2664: 'std::_List_iterator<_Mylist>
 std::list<_Ty>::erase(std::_List_const_iterator<_Mylist>)' : cannot
 convert parameter 1 from 'std::reverse_iterator<_RanIt>' to
 'std::_List_const_iterator<_Mylist>'

The Code I Tried:

std::list<mytype> mylist;

// lots of code omitted for clarity
bool ends_badly = true;

while(ends_badly && mylist.size() > 0)
{
    auto pos = mylist.crbegin(); // Last element in the list
    if ((*pos)->Type() == unwanted)
    {
        mylist.erase(pos); // Here is where the compiler complains
    }
    else
    {
        ends_badly = false;
    }
}

I can get around this by using forward iterators and looping through the list to the end, but that's so cumbersome. The compiler is OK with a forward iterator in this context, and I tried casting a the reverse iterator to a const iterator but the compiler didn't like that either.

Erasing a list element from a bidirectional list using a reverse iterator seems like a reasonable thing. Is there something obvious I'm missing here?

like image 735
vacuumhead Avatar asked Apr 22 '16 22:04

vacuumhead


People also ask

How to remove the last element from a list in C#?

This post will discuss how to remove the last element from a List in C#. 1. Using List<T>.RemoveAt () Method The RemoveAt () method removes the element present at the specified position in a list. To remove the last element, you can pass the index of it to the RemoveAt () method.

How to delete elements in C++ STL list?

Delete elements in C++ STL list. Using list::erase (): The purpose of this function is to remove the elements from list. Single or multiple contiguous elements in range can be removed using this function. This function takes 2 arguments, start iterator and end iterator. Time complexity : O (n) where (n is size of list).

How to remove an element from a list in Python?

Pass the index of the element you want to remove as the argument. It modifies the list in place and returns the element removed (or “popped”). To remove the last element from a list, pass the index of the last element in the list (you can also use a negative index, -1) as an argument to the list pop () function. Here’s an example –

How to delete an element from a list without iterating?

Also, u can't delete element from list by value, without iterating it. If you think about it, it doesn't even make sense, because pointers inside the list have to be updated. remove actually removes in this case. This wont compile as it returns void due to that.


2 Answers

I suppose that you can simplify your code snippet doing it the next way:

while (!mylist.empty() && mylist.back()->Type() == unwanted) {
    mylist.pop_back();
}
like image 138
Edgar Rokjān Avatar answered Oct 13 '22 19:10

Edgar Rokjān


To fix the specific error in your code Can I convert a reverse iterator to a forward iterator?

mylist.erase((pos+1).base()); 

Using std::reverse_iterator::base

The base iterator refers to the element that is next (from the std::reverse_iterator::iterator_type perspective) to the element the reverse_iterator is currently pointing to.

Anyway, pop_back is the best choice in your case.

like image 22
gdlmx Avatar answered Oct 13 '22 19:10

gdlmx