-1

EDIT: This question refers specifically to std::lists - other similar questions on Stack Overflow refer to std::vectors

I'm using C++ and having trouble erasing an element from a std::list while iterating through it. I have a list of a custom class ('Objects' for the sake of this question), and my code looks like this:

for(auto i : Objects)
    if(i.EraseFlag == true)
        {
            i = Objects.erase(i);
        }

I'm getting the error: 'no matching function for call to std::list::erase(Object&)'

I believe this is the right way (as of C++11) to iterate through lists, erase an element and return an iterator that takes into account the erasure, but clearly I'm doing something wrong. Previously when using vectors I would use 'Objects.erase(Objects.begin() + i)' with i being an integer in a for loop, but given the access requirements of lists this won't work.

Help appreciated.

Thanks

nathanburns
  • 139
  • 7
  • erase() takes an iterator as its parameter –  Feb 27 '17 at 17:03
  • 1
    You shouldn't be altering the sequence during the range based `for` loop. – PaulMcKenzie Feb 27 '17 at 17:05
  • 1
    *I believe this is the right way (as of C++11) to iterate through lists, erase an element and return an iterator that takes into account the erasure,* -- Why erase things like this when you can do this using `erase / remove` idiom, where no loops are required? – PaulMcKenzie Feb 27 '17 at 17:08
  • Look, [no loops](http://ideone.com/drv4UC) – PaulMcKenzie Feb 27 '17 at 17:16
  • Thanks @PaulMcKenzie, remove_if looks like the right way to go about this - I've tried using your code, though I'm now getting an 'invalid use of auto' error - any ideas? – nathanburns Feb 27 '17 at 17:50
  • @nathanburns I think you need to use either C++14 compilation, or try [this without auto](http://ideone.com/Ejqz95) – PaulMcKenzie Feb 27 '17 at 19:47

1 Answers1

1

Member function erase deals with iterators.

For such a task it would be correctly to use an ordinary for loop. For example

for ( auto it = Objects.begin(); it != Objects.end(); )
{
    if ( it->EraseFlag ) it = Objects.erase( it );
    else ++it;
}

Another approach is to use member function remove_if. For example

Objects.remove_if( []( const auto &value ) { return value.EraseFlag; } );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thanks Vlad, your initial loop seems to work. It looks using remove_if would be the best practice way to do this, which you've also included so I'll mark this as the answer – nathanburns Feb 27 '17 at 17:55