Requirements on std::forward_list::remove_if predicates

Viewed 413

Consider this code:

struct T
{
bool status;
UsefulData data;
};

std::forward_list<T> lst;

lst.remove_if([](T &x) -> bool { return x.status= !x.status; });

i.e. switching the status and removing inactive elements in one go.

According to cppreference the above code seems to be undefined behavior (emphasis mine):

template< class UnaryPredicate >
void remove_if( UnaryPredicate p );

p - unary predicate which returns true if the element should be removed. The signature of the predicate function should be equivalent to the following:

bool pred(const Type &a);

The signature does not need to have const &, but the function must not modify the objects passed to it. The type Type must be such that an object of type forward_list<T,Allocator>::const_iterator can be dereferenced and then implicitly converted to Type.

However, the current working draft seems to be less restrictive (N4659 [forwardlist.ops]):

void remove(const T& value)
template <class Predicate> void remove_if(Predicate pred);

Effects:

Erases all the elements in the list referred by a list iterator i for which the following conditions hold: *i == value (for remove()), pred(*i) is true (for remove_if()). Invalidates only the iterators and references to the erased elements.

Throws:

Nothing unless an exception is thrown by the equality comparison or the predicate.

Remarks:

Stable (20.5.5.7).

Complexity:

Exactly distance(begin(), end()) applications of the corresponding predicate.

Are there additional restrictions on predicates in other parts of the Standard?

I have tested the above code on a number of compilers and it compiles and seems to work as intended. Do I really need to transverse the list twice?

2 Answers
Related