codeJack
codeJack

Reputation: 2503

boost Filter iterator with different predicates

I'm trying to implement a method which returns a boost::filter_iterator pair (begin, end).

I would like this method to be customizable in terms of filtering, but I don't know how I could sort this out since when I typedef the filter iterator range I have to hardcode the predicate I want to use and I cannot choose it depending on the parameter the method receives in input.

I would like to have something like this :

enum FilterType
{
    FilterOnState = 0,
    FilterOnValue,
    FilterOnSize,
    FilterOnWhatever...
}

typedef boost::filter_iterator<PredicateStruct, std::list<Object>::iterator> filter_iterator;

std::pair<filter_iterator, filter_iterator> filterObjects(FilterType filterType);

I thought about a possible template solution as well, but I would need the client to access predicates implementation and instance the one suiting his needs before calling the filter, he'd almost do all the job himself : that's why I'd like best the enum based solution.

template<typename P>
std::pair<boost::filter_iterator<P, std::list<Object>::iterator>, 
          boost::filter_iterator<P, std::list<Object>::iterator>> filterObjects(P& predicate);

Would a predicate "base class" be a possible solution for the enum based implementation ?

Thanks a lot in advance! Giacomo

Upvotes: 2

Views: 2399

Answers (1)

Xeo
Xeo

Reputation: 131799

Why not simply provide predefined predicates instead of enum values?

struct predef_predicate{  
  predef_predicate(FilterType f)
    : filt(f) {}

  template<class T>
  bool operator()(T const& v) const{
    // filter in whatever way...
  }

private:
  FilterType filt;
};

namespace { // guard against ODR violations
predef_predicate const filter_state(FilterOnState);
predef_predicate const filter_values(FilterOnValue);
// ...
}

And then, instead of reinventing the wheel, just use Boost.Range's filtered adaptor.

#include <vector>
#include <iterator>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorith/copy.hpp>

int main(){
  std::vector<int> v;
  // fill v
  std::vector<int> filtered;
  boost::copy(v | boost::adaptors::filtered(filter_values),
      std::back_inserter(filtered));
}

And with C++11, the act of creating a predicate becomes even easier thanks to lambdas.

Upvotes: 2

Related Questions