rwallace
rwallace

Reputation: 33375

Functional versions of C++ copy_if, transform etc

A non-iterator version of e.g. all_of can be written:

template <class Container, class UnaryPredicate>
bool all_of(Container s, UnaryPredicate f) {
  return all_of(s.begin(), s.end(), f);
}

But I don't think you can do the same with algorithms that return containers?

template <class Container, class UnaryPredicate>
Container copy_if(Container, UnaryPredicate);

The closest I got to an implementation got as far as using a vector to hold an intermediate result, but tripped over the lack of any way to supply a template parameter for the vector. Is there something I'm missing?

Upvotes: 2

Views: 340

Answers (2)

Holt
Holt

Reputation: 37606

You should use std::insert_iterator instead of using a vector to hold your temporary:

template <class Container, class UnaryPredicate>
Container copy_if(Container const& input, UnaryPredicate const& up) {
    Container tmp;
    std::copy_if(input.begin(), input.end(),
                 std::insert_iterator<Container>(tmp, tmp.begin()), up);
    return tmp;
}

std::insert_iterator needs your container to have an insert() method, which is a not a requirement of Container but a requirement of both SequenceContainer and AssociativeContainer (table is not complete, but [associative.reqmts] requires it (Table 102)).


If you really want to use a vector and all your Container respect the Container concept, then you can access their value type using:

typename Container::value_type

E.g.:

std::vector<typename Container::value_type>

Upvotes: 4

bolov
bolov

Reputation: 75688

I think the best way is to take the type of (assuming Container c):

*std::begin(c)

either via decltype:

using T = decltype(*std::begin(c));

or via auto:

auto elem = *std::begin(c);

Upvotes: 1

Related Questions