Question

I have a std::vector<std::shared_ptr<Foo>> from which I want to erase-remove items matching some predicate. The removed objects should have a method called which sets some status for use elsewhere.

Is there a reason I should not do this in the predicate function when true is returned? It feels a little like mixing concerns, but the only alternatives I can think of seem much uglier.

Was it helpful?

Solution

There are two reasons why this is probably not a good idea.

First, most standard library algorithms should not use predicates what modify the elements they act on.

Second, std::remove and std::remove_if don't give you a good set of "removed" elements*. You can only rely on the elements that are selected to keep. The "removed" elements might in fact be copies of the "good" ones. And since you are storing shared pointers, they could be pointing to the same objects as the "good" elements.

An alternative would be to use std::partition, then iterate over the relevant section of the partition, then use erase in a way similar to the erase-remove idiom.

auto p = std::partition(v.begin, v.end(), pred);
std::for_each(p, v.end(), call_method_functor);
v.erase(p, v.end());

* These algorithms should probably have been named keep and keep_if

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top