Hello again Steven Watanabe wrote:
AMDG
Jean-Pierre Bergamin wrote:
Hello everyone
Imagine a class "numbers" that contains some values and methods like getEvenValues(), getOddValues(), getValuesLarger100() etc. Those methods return an iterator range of filter_iterators. In the the code I posted below, I'd have to define a different iterator_range of filter_iterator types for all the different methods (numbers::EvenFilterRange, numbers::OddFilterRange etc.). Is there some way to "hide" the type of the predicate used in a filter_iterator, so that it would be possible to have a generic "NumberRange" type for the return values of all methods? Something like:
class numbers { typedef NumberRange ????; NumberRange getEvenValues() const; NumberRange getOddValues() const; NumberRange getValuesLarger100() const; }
Try using boost::function<bool(int)> for the predicate type.
Thank you Steven. Using boost::function as the predicate type does the trick. For the sake of completeness, I post some code at the bottom. I think this is a very useful method to provide filtered values to a user, without copying any elements. Regards James /*********************************************/ #include <vector> #include <iostream> #include <boost/iterator/filter_iterator.hpp> #include <boost/iterator/counting_iterator.hpp> #include <boost/range/iterator_range.hpp> #include <boost/function.hpp> #include <boost/bind.hpp> using namespace std; using namespace boost; /*********************************************/ template<typename T> struct is_even { bool operator()(const T &t) { return t % 2 == 0; } }; template<typename T> struct is_odd { bool operator()(const T &t) { return t % 2 != 0; } }; template<typename T> struct is_greater_then { is_greater_then(const T &t) :m_t(t) { } bool operator()(const T &t) { return t > m_t; } private: T m_t; }; /*********************************************/ template<typename T> class numbers { public: typedef T type; typedef vector<typename T> NumberContainer; typedef typename NumberContainer::const_iterator NumberIter; typedef boost::function<bool(T)> PredFunction; typedef iterator_range< filter_iterator< PredFunction, NumberIter> > NumberRange; numbers() { copy( counting_iterator<T>(0), counting_iterator<T>(100), back_inserter(m_numbers) ); } template<typename Pred> NumberRange getValues(const Pred &pred) { return make_iterator_range( make_filter_iterator(pred, m_numbers.begin(), m_numbers.end()), make_filter_iterator(pred, m_numbers.end(), m_numbers.end()) ); } NumberRange getEvenValues() { PredFunction pred = bind<bool>(is_even<T>(), _1); return getValues(pred); }; NumberRange getOddValues() { PredFunction pred = bind<bool>(is_odd<T>(), _1); return getValues(pred); }; private: NumberContainer m_numbers; }; /*********************************************/ template<typename T> struct print_number { void operator()(const T &t) { cout << "Number: " << t << endl; } }; /*********************************************/ int main() { typedef numbers<long> ints; print_number<ints::type> printer; ints my_ints; cout << "Even values" << endl; ints::NumberRange even_range = my_ints.getEvenValues(); for_each(begin(even_range), end(even_range), printer); cout << "Odd values" << endl; ints::NumberRange odd_range = my_ints.getOddValues(); for_each(begin(odd_range), end(odd_range), printer); cout << "> 50" << endl; ints::PredFunction pred = bind<bool>(is_greater_then<ints::type>(50), _1); ints::NumberRange greater_50_range = my_ints.getValues(pred); for_each(begin(greater_50_range), end(greater_50_range), printer); }