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 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
#include
#include
#include
#include
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 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_numberints::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_thenints::type(50), _1);
ints::NumberRange greater_50_range = my_ints.getValues(pred);
for_each(begin(greater_50_range), end(greater_50_range), printer);
}