Accordint to this quite highly upvoted answer, the canonical way to iterate through a set erasing some elements is the following:
for (it = mySet.begin(); it != mySet.end(); ) {
if (conditionToDelete(*it)) {
mySet.erase(it++);
}
else {
++it;
}
}
This, of course, is a result of C++03's set erase not returning an iterator. Otherwise one could write it = mySet.erase(it);
It is also obvious that one can write
itToDelete = it++;
mySet.erase(itToDelete);
This question is not about how to delete elements while iterating. The question is why does the following line apparently not result in undefined behavior.
mySet.erase(it++);
At first I was sure this had to be UB, because I was thinking in the wrong way about postincrement. It is a common (but wrong) way to think of pre-increment as happening BEFORE rest of evaluation, and postincrement happening AFTER. Of course, this is wrong. Both postincrement and preincrement have the side effect of incrementing the variable. The difference is the value of those expressions.
That said, as far as I can remember, the C++ standard (at least the C++03 one) does not specify exactly when the side effect of postincrement will take place. So, unless we have a guarantee that if a function argument which is a postincrement expression will have its side effects in place before entering the function body, shouldn't this be UB? What exactly (standards-wise), if anything, prohibits the side-effect of it++ taking place after the iterator has been invalidated inside the function body?
Quotes from the standard would be very much welcome.
For an argument's sake let's also suppose that set's iterator is a built in type and this is actually operator ++, not the overloaded operator-function