0

In this code snippet Update() returns a boolean, if it returns false I would like to delete the element from the vector.

However, this produces a run-time error of debug assertion failed. The expression is "vector iterator not incrementable".

The code:

for(auto iter = someVector.begin(); iter != someVector.end(); ++iter){
    if(!iter->get()->Update()) iter = someVector.erase(iter);
}

I have tried subtracting from the iterator as follows too:

for(auto iter = particles.begin(); iter != particles.end(); ++iter){
    if(!iter->get()->Update()) iter = --(particles.erase(iter));
}

...but this results in "vector iterator not decrementable".

How can I make my code works as intended; so that the vector element is deleted when the Update() function returns false?

1

2 Answers 2

5

Change the loop to this:

for(auto iter = someVector.begin(); iter != someVector.end();){
    if(!iter->get()->Update())
        iter = someVector.erase(iter);
    else
        ++it;
}

The reason for the assertion is that, after the call to erase, iter might be equal to end(). The iterator returned by erase is already "next", you're not supposed to increment it.

Sign up to request clarification or add additional context in comments.

3 Comments

this works perfectly, thank you! I didn't know you could omit the last part of the for loop either.
No problem. Do read @Dietmar's answer, too! As for loop, you can omit all three statements: for(;;) {}. This is how some people like to write their infinite loops.
I feel educated! Thank you again.
1

I'd recommend not using erase() as above in the first place but rather use it something like this:

someVector.erase(std::remove_if(someVector.begin(), someVector.end(),
                                [](decltype(*someVector.begin()) element){
                                    return !element.get()->update();
                                },
                 someVector.end());

When just one element needs to be erased it does roughly the same as using the one iterator version of erase(). When multiple elements need to be erased, it does less copyies/moves. Note that I use a lambda function just because it is easier to express but the same can be done with a suitable function object if lambda functions are not available.

5 Comments

+1 I was writing this only :D, should be return !element.get()->update()
Thank you, it's always nice to know more than one way to solve a problem. However, in my case I will extremely rarely need to erase more than 1 element at a time.
@JoshuaGerrard: Using the algorithm is no worse than erasing an element individually and works better in the rare case where there is more than 1 element. Thus, it is obviously the way to go! Not to mention that the algorithms could possibly wing a few extra performance improvements (e.g., suitable loop unrolling, due boundary checks just once in a debugging implementation, etc.): using std::remove_if() is a win!
Thanks again! I shall look into it more then, as the syntax looks rather confusing to me. If I can understand what is going on, I will use it. It's the [](decltype... that throws me. That said...google is my friend ;)
@JoshuaGerrard: This is just a C++11 lambda function and a somewhat awkward use of decltype() to determine the argument type. You could also use a function object like struct predicat { template <typename T> bool operator()(T& o) { return !o.get()->Update(); } }; and then use predicate() instead. If the indirection via get() wouldn't be needed it would be easy to use std::mem_fn(). Using std::bind() to compose things would also work but would probably be more confusing...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.