You have basically two approaches:
1) What you say in the comment above, write (iterators pointing to) the results to the iterator container. It will look something like this:
template <typename ForwardIterator, typename OutputIterator, typename UnaryPredicate> void select_iterators(ForwardIterator first, ForwardIterator last, OutputIterator out, UnaryPredicate pred) { while (first != last) { if pred(*first) *out++ = first; ++first; } }
Then you call it like this:
vector<Foo> myfoos; vector<vector<Foo>::iterator> results; select_iterators(myfoos.begin(), myfoos.end(), std::back_inserter(results), some_comparator);
In fact, you define select_iterators in terms of other algorithms using copy_if and boost::counting_iterator , but I don't think it's worth it when the direct implementation is so simple. It will look like this:
template <typename ForwardIterator, typename OutputIterator, typename UnaryPredicate> void select_iterators(ForwardIterator first, ForwardIterator last, OutputIterator out, UnaryPredicate pred) { std::copy_if( boost::make_counting_iterator(first), boost::make_counting_iterator(last), out, [&](ForwardIterator it) { return pred(*it); } ); }
2) Instead of testing all the values ββin the front and writing the results somewhere, define an iterator that moves along the original range each time it increases until it finds the next match. Boost provides two ways to do this: boost::filter_iterator and boost::adaptors::filter . Therefore, you can write:
auto results = boost::adaptors::filter(myfoos, some_comparator);
Then, whatever you do with your results, you can iterate from results.begin() to results.end() , as if it were a container. This is not a container; it does not satisfy the entire interface of the container. It satisfies the interface defined by Boost, named Range, which is "can be repeated." This is actually just a filtered view of myfoos , so the Foo object is not copied or even moved.