forked from boostorg/iterator
filter_iterator
[SVN r850]
This commit is contained in:
@@ -693,6 +693,12 @@ namespace boost {
|
||||
}
|
||||
};
|
||||
|
||||
template <class BidirectionalIterator>
|
||||
reverse_iterator<BidirectionalIterator> make_reverse_iterator(BidirectionalIterator x)
|
||||
{
|
||||
return reverse_iterator<BidirectionalIterator>(x);
|
||||
}
|
||||
|
||||
//
|
||||
// TODO fix category
|
||||
//
|
||||
@@ -734,6 +740,8 @@ namespace boost {
|
||||
private:
|
||||
typename super_t::value_type dereference() const { return m_f(super_t::dereference()); }
|
||||
|
||||
// Probably should be the initial base class so it can be
|
||||
// optimized away via EBO if it is an empty class.
|
||||
AdaptableUnaryFunction m_f;
|
||||
};
|
||||
|
||||
@@ -744,7 +752,7 @@ namespace boost {
|
||||
//
|
||||
// Detection for whether a type has a nested `element_type'
|
||||
// typedef. Used to detect smart pointers. For compilers not
|
||||
// supporting mpl's has_xxx, we supply specialzations. However, we
|
||||
// supporting mpl's has_xxx, we supply specializations. However, we
|
||||
// really ought to have a specializable is_pointer template which
|
||||
// can be used instead with something like
|
||||
// boost/python/pointee.hpp to find the value_type.
|
||||
@@ -849,9 +857,9 @@ namespace boost {
|
||||
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||
# endif
|
||||
)
|
||||
|
||||
: super_t(y.base()) {}
|
||||
|
||||
: super_t(y.base())
|
||||
{}
|
||||
|
||||
private:
|
||||
typename super_t::reference dereference() const { return **this->base(); }
|
||||
|
||||
@@ -871,6 +879,90 @@ namespace boost {
|
||||
return indirect_iterator<Iter, Traits>(x);
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
struct filter_iterator_traits
|
||||
: detail::iterator_traits<Iterator>
|
||||
{
|
||||
typedef iterator_tag<
|
||||
typename return_category<Iterator>::type
|
||||
, forward_traversal_tag
|
||||
> iterator_category;
|
||||
};
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
class filter_iterator
|
||||
: public iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator,
|
||||
typename filter_iterator_traits<Iterator>::value_type,
|
||||
typename filter_iterator_traits<Iterator>::reference,
|
||||
typename filter_iterator_traits<Iterator>::pointer,
|
||||
typename filter_iterator_traits<Iterator>::iterator_category,
|
||||
typename filter_iterator_traits<Iterator>::difference_type
|
||||
>
|
||||
{
|
||||
typedef iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator,
|
||||
typename filter_iterator_traits<Iterator>::value_type,
|
||||
typename filter_iterator_traits<Iterator>::reference,
|
||||
typename filter_iterator_traits<Iterator>::pointer,
|
||||
typename filter_iterator_traits<Iterator>::iterator_category,
|
||||
typename filter_iterator_traits<Iterator>::difference_type > super_t;
|
||||
|
||||
friend class iterator_core_access;
|
||||
|
||||
public:
|
||||
filter_iterator() { }
|
||||
|
||||
filter_iterator(Predicate f, Iterator x, Iterator end = Iterator())
|
||||
: super_t(x), m_predicate(f), m_end(end)
|
||||
{
|
||||
satisfy_predicate();
|
||||
}
|
||||
|
||||
filter_iterator(Iterator x, Iterator end = Iterator())
|
||||
: super_t(x), m_predicate(), m_end(end)
|
||||
{
|
||||
satisfy_predicate();
|
||||
}
|
||||
|
||||
template<class OtherIterator>
|
||||
filter_iterator(
|
||||
filter_iterator<Predicate, OtherIterator> const& t
|
||||
# ifndef BOOST_NO_ENABLE_IF_CONSTRUCTORS
|
||||
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||
# endif
|
||||
)
|
||||
: super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {}
|
||||
|
||||
Predicate predicate() const { return m_predicate; }
|
||||
|
||||
Iterator end() const { return m_end; }
|
||||
|
||||
private:
|
||||
void increment()
|
||||
{
|
||||
super_t::increment();
|
||||
satisfy_predicate();
|
||||
}
|
||||
|
||||
void satisfy_predicate()
|
||||
{
|
||||
while (this->base() != this->m_end && !this->m_predicate(*this->base()))
|
||||
super_t::increment();
|
||||
}
|
||||
|
||||
// Probably should be the initial base class so it can be
|
||||
// optimized away via EBO if it is an empty class.
|
||||
Predicate m_predicate;
|
||||
Iterator m_end;
|
||||
};
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
filter_iterator<Predicate,Iterator>
|
||||
make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator())
|
||||
{
|
||||
return filter_iterator<Predicate,Iterator>(f,x,end);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
//
|
||||
|
@@ -4,5 +4,6 @@ run concept_tests.cpp ;
|
||||
run iterator_adaptor_cc.cpp ;
|
||||
run transform_iterator_test.cpp ;
|
||||
run indirect_iterator_test.cpp ;
|
||||
run filter_iterator_test.cpp ;
|
||||
compile-fail interoperable_fail.cpp ;
|
||||
compile-fail is_convertible_fail.cpp ;
|
81
test/filter_iterator_test.cpp
Normal file
81
test/filter_iterator_test.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/iterator/iterator_adaptors.hpp>
|
||||
#include <boost/iterator/new_iterator_tests.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
struct one_or_four {
|
||||
bool operator()(dummyT x) const {
|
||||
return x.foo() == 1 || x.foo() == 4;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<dummyT*>
|
||||
: ptr_iter_traits<dummyT> {};
|
||||
}}
|
||||
#endif
|
||||
|
||||
|
||||
// Test filter iterator
|
||||
int main()
|
||||
{
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
typedef boost::filter_iterator<one_or_four, dummyT*> filter_iter;
|
||||
|
||||
boost::forward_iterator_test(
|
||||
filter_iter(one_or_four(), array, array+N)
|
||||
, dummyT(1), dummyT(4));
|
||||
|
||||
# if 0
|
||||
BOOST_STATIC_ASSERT(
|
||||
(!boost::detail::is_bidirectional_traversal_iterator<
|
||||
boost::traversal_category<filter_iter>::type
|
||||
>::value) );
|
||||
# endif
|
||||
|
||||
// On compilers not supporting partial specialization, we can do more type
|
||||
// deduction with deque iterators than with pointers... unless the library
|
||||
// is broken ;-(
|
||||
std::deque<dummyT> array2;
|
||||
std::copy(array+0, array+N, std::back_inserter(array2));
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(
|
||||
one_or_four()
|
||||
, boost::make_reverse_iterator(array2.end())
|
||||
, boost::make_reverse_iterator(array2.begin())
|
||||
),
|
||||
dummyT(4), dummyT(1));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
filter_iter(array+0, array+N),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
boost::forward_iterator_test(
|
||||
filter_iter(one_or_four(), array, array + N),
|
||||
dummyT(1), dummyT(4));
|
||||
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user