top | item 44156675

(no title)

maattdd | 9 months ago

Obviously you can delete than iterate. He means delete while iterating.

discuss

order

OskarS|9 months ago

Ah, ok. But then: you kinda can't do that at all. You certainly shouldn't.

For unordered_map (and every hash table in the known universe) erasing anything invalidates all iterators, so you can't iterate while erasing. For std::map, you can if you're very, very careful (erasing invalidates the iterator you're currently on, but if you cache the next iterator, THEN erase the current one, it'll probably work, but be very fiddly). Most languages forbid this entirely: e.g. Rust's ownership model doesn't allow it, Python throws an exception, etc. It's just a very bad idea in general.

tom_|9 months ago

Iterator-based std::unordered_map::erase and std::map::erase return a new iterator, one past the range erased, specifically so that you can erase while iterating. Along these untested lines:

    for(decltype(cont)::const_iterator it=cont.begin();it!=cont.end();++it){
        if(Keep(it.first)){
            ++it;
        }else{
            it=cont.erase(it);
        }
    }
There's an argument to be made that maybe you should do something else, but if you want to do the above, you can!

incrudible|9 months ago

What is the use case for that? Seems more like a footgun, at least for a generic container interface.

simonask|9 months ago

Surely you must be kidding? Inserting/removing in a container while iterating through it is one of the all time greatest and most iconic bugs. People do it because they want to do it.

In reality, very few real-life containers can support this pattern, which is why this is a headline case for Rust, because it statically prevents this bug.

But yes, for removal the correct thing is always to use `std::erase_if` (C++) or `retain()` (Rust). For insertions, the only real solution is to build up a separate collection while iterating and then merging it into the original container when done. Yucky, but won't crash.

gpderetta|9 months ago

It happens surprisingly often.