Итератор буст-фильтра с разными предикатами - PullRequest
2 голосов
/ 24 февраля 2012

Я пытаюсь реализовать метод, который возвращает пару boost :: filter_iterator (начало, конец).

Мне бы хотелось, чтобы этот метод был настраиваемым с точки зрения фильтрации, но я не знаю, как я мог бы с этим разобраться, поскольку при вводе определения диапазона итератора фильтра мне приходится жестко задавать предикат, который я хочу использовать, и я не могу выбрать это зависит от параметра, который метод получает на входе.

Я бы хотел что-то вроде этого:

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);

Я также подумал о возможном шаблонном решении, но мне нужно, чтобы клиент получил доступ к реализации предикатов, и экземпляр, отвечающий его потребностям, перед вызовом фильтра, он почти сам сделает всю работу: вот почему я как лучше всего решение на основе enum.

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

Будет ли предикат "базовый класс" возможным решением для реализации на основе перечисления?

Большое спасибо заранее! Джакомо

1 Ответ

2 голосов
/ 24 февраля 2012

Почему бы просто не предоставить предопределенные предикаты вместо значений enum?

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);
// ...
}

И затем, вместо того, чтобы изобретать велосипед, просто используйте адаптер filtered Boost.Range .

#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));
}

А в C ++ 11 процесс создания предиката становится еще проще благодаря лямбдам.

...