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
|
// TODO fix category
|
||||||
//
|
//
|
||||||
@@ -734,6 +740,8 @@ namespace boost {
|
|||||||
private:
|
private:
|
||||||
typename super_t::value_type dereference() const { return m_f(super_t::dereference()); }
|
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;
|
AdaptableUnaryFunction m_f;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -744,7 +752,7 @@ namespace boost {
|
|||||||
//
|
//
|
||||||
// Detection for whether a type has a nested `element_type'
|
// Detection for whether a type has a nested `element_type'
|
||||||
// typedef. Used to detect smart pointers. For compilers not
|
// 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
|
// really ought to have a specializable is_pointer template which
|
||||||
// can be used instead with something like
|
// can be used instead with something like
|
||||||
// boost/python/pointee.hpp to find the value_type.
|
// boost/python/pointee.hpp to find the value_type.
|
||||||
@@ -849,8 +857,8 @@ namespace boost {
|
|||||||
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||||
# endif
|
# endif
|
||||||
)
|
)
|
||||||
|
: super_t(y.base())
|
||||||
: super_t(y.base()) {}
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typename super_t::reference dereference() const { return **this->base(); }
|
typename super_t::reference dereference() const { return **this->base(); }
|
||||||
@@ -871,6 +879,90 @@ namespace boost {
|
|||||||
return indirect_iterator<Iter, Traits>(x);
|
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
|
} // namespace boost
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@@ -4,5 +4,6 @@ run concept_tests.cpp ;
|
|||||||
run iterator_adaptor_cc.cpp ;
|
run iterator_adaptor_cc.cpp ;
|
||||||
run transform_iterator_test.cpp ;
|
run transform_iterator_test.cpp ;
|
||||||
run indirect_iterator_test.cpp ;
|
run indirect_iterator_test.cpp ;
|
||||||
|
run filter_iterator_test.cpp ;
|
||||||
compile-fail interoperable_fail.cpp ;
|
compile-fail interoperable_fail.cpp ;
|
||||||
compile-fail is_convertible_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