https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107850
--- Comment #4 from Charles-Henri Gros <chgros at synopsys dot com> --- Looking into it further, there may be an implicit requirement that the predicate does not modify its argument. https://eel.is/c++draft/algorithms.requirements#6 "When not otherwise constrained, the Predicate parameter is used whenever an algorithm expects a function object ([function.objects]) that, when applied to the result of dereferencing the corresponding iterator, returns a value testable as true. In other words, if an algorithm takes Predicate pred as its argument and first as its iterator argument with value type T, it should work correctly in the construct pred(*first) contextually converted to bool ([conv]). The function object pred shall not apply any non-constant function through the dereferenced iterator. Given a glvalue u of type (possibly const) T that designates the same object as *first, pred(u) shall be a valid expression that is equal to pred(*first)." I'm unfortunately not well-versed enough in C++ legalese to tell what "possibly const" means in that context, nor "apply any non-constant function". And while I understand that a "predicate" is generally meant to not do modification, there are fairly frequent use cases for "apply this potentially modifying operation, and depending on its result remove the element from the container". And in practice, this works (e.g. std::remove_if, your own earlier version of erase_if, other compilers' version...). Maybe I should go to LEWG and lobby to remove that limitation. In the meanwhile, I'll probably just keep my own, perhaps slightly less optimal removal algorithms.