Boost logo

Boost Users :

From: Jean-Pierre Bergamin (james_at_[hidden])
Date: 2008-04-12 14:08:16


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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net