tags:

views:

117

answers:

3

I had tried to test the erase function in list, but I can't succeed! The error message of my compiler is:

[Error]error: no matching function for call to
`std::list<int,std::allocator<int> >::erase(std::_List_const_iterator<int>&)'.

My code as follows:

#include <iostream>
#include <list>
using namespace std;

int main()
{
    int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
    list<int> ilst(ia, ia + 11);

    list<int>::const_iterator iter2 = ilst.begin();
    for(; iter2 != ilst.end(); ++iter2)
    {
     if(*iter2 % 2 != 0)
     { 
      iter2 = ilst.erase(iter2); //error!
      --iter2;
     }
    }
    iter2 = ilst.begin(); 
    for(; iter2 != ilst.end(); ++iter2)
    {
     cout << *iter << " ";
    } 
    cout << endl;
}

Thank you for your guide!

+6  A: 

Looking at this sample I think you can shift without trouble to list::iterator instead of list::const_iterator. In this way code compiled without errors

Dewfy
+1. What is the logic behind trying to use a const_iterator. A const_iterator "cannot be used to modify the value of an element". I'd say deleting an element is modifying its value ...
Goz
Same logic as `delete`ing an object through a `const T*`, and since that's allowed, for orthogonality this should be allowed too.
MSalters
A: 

You can also use:

list<int>::iterator new_end = 
        remove_if(ilst.begin(), ilst.end(), 
                  compose1(bind2nd(equal_to<int>(), 0),
                           bind2nd(modulus<int>(), 2)));
ilst.erase(new_end, ilst.end());
copy(ilst.begin(), ilst.end(), ostream_iterator<int>(cout, " "));
TimW
+1  A: 

The code actually smells bad. It should be possible that after erasing iter2 refers to the list's beginning (if you happened to remove the first item), in which case you shouldn't be decrementing it.

The correct form of erasing in a loop looks like this:

for(list<int>::iterator iter2 = ilst.begin(); iter2 != ilst.end(); )
{
    if(*iter2 % 2 != 0)
    {       
        iter2 = ilst.erase(iter2);      //no error, if not using const_iterator
    }
    else {
        ++iter2; //only increment if didn't erase
    }
}

I also recommend using remove_if like TimW, except one should use a member function over a free function if available (as is the case with std::list) and I don't think compose1 is in the standard library (yet?). Regarding the second point, fortunately in this case it doesn't need to be that complicated:

ilst.remove_if(bind2nd(modulus<int>(), 2));
UncleBens