First, everything except the condition for both can be done using std::remove_copy_if . Despite its name, remove_copy_if does not remove anything from the original collection. I think people would understand this more easily if it was called something like filtered_copy . It copies items from one collection to another. For each element, it calls a predicate, and the element is copied if and only if the predicate returns false for this element.
This leaves you with only one responsibility: implement a test function that looks at every X * and says whether to leave it outside the copy you are creating. Since you have one logic that you want to apply in two different ways, I would encapsulate the logic in a private function of the class. These two methods can be sent to the outside world as overloaded versions of operator() for a class:
class F { bool do_test(X const *x) const { return x.internal_stuff; } public: bool operator()(X const *x) const { return do_test(x); } bool operator()(std::pair<int, X const *> const &p) const { return do_test(p.second); } };
Since operator()(X const *) is pure thunk before do_test() , you can get rid of it, but IMO, which is likely to do more harm than good.
In any case, this completely eliminates your logic in one place ( F::do_test ). It also provides a simple, consistent syntax for creating a filtered copy of either list<X *> or std::map<int, X *> :
std::list<X *> result; std::remove_copy_if(coll.begin(), coll.end(), std:back_inserter(result), F());
As a final note: std::list is probably the most redesigned collection. Although it has its uses, they are indeed quite rare. std::vector and std::deque are often better.
source share