Does the Standard explicitly forbid modifying a container within
std::for_each
?
No, not explicitly. At least for any sensible definition of "explicitly". The section on std::for_each
(§25.2.4) does not say anything at all about iterator invalidation or side effects that cause modification of the iterated range.
There are, however, plenty of implicit reasons for why your code cannot work. Consider how std::for_each
must be implemented. It's completely generic and therefore does not know anything about the std::list
it operates on; you gave it two iterators to form a range, which means that last
can be reached from first
. How should std::for_each
know that your function object has invalidated the local iterator object with which it goes from first
to last
?
And even if the function knew that invalidation has occurred, what should it do? In a hand-written loop, you'd take the result of erase
and continue iteration with it, but std::for_each
cannot do that, by definition.
Here's an old but still valid reference article: http://www.drdobbs.com/effective-standard-c-library-foreach-vs/184403769
It says:
For instance, invalidating the iterators or the sequences that the
algorithm works with is disastrous in any case. Even the function
object supplied to for_each must obey this common-sense rule, even if
the Standard does not say so.
Paraphrasing some wise words I once read:
The C++ standard is written by human beings; it's not always as perfect as we wish it to be.