• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // (C) Copyright David Abrahams 2002.
2 // (C) Copyright Jeremy Siek    2002.
3 // (C) Copyright Thomas Witt    2002.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_FILTER_ITERATOR_23022003THW_HPP
8 #define BOOST_FILTER_ITERATOR_23022003THW_HPP
9 
10 #include <boost/iterator/iterator_adaptor.hpp>
11 #include <boost/iterator/iterator_categories.hpp>
12 
13 #include <boost/type_traits/is_class.hpp>
14 #include <boost/static_assert.hpp>
15 
16 namespace boost {
17 namespace iterators {
18 
19   template <class Predicate, class Iterator>
20   class filter_iterator;
21 
22   namespace detail
23   {
24     template <class Predicate, class Iterator>
25     struct filter_iterator_base
26     {
27         typedef iterator_adaptor<
28             filter_iterator<Predicate, Iterator>
29           , Iterator
30           , use_default
31           , typename mpl::if_<
32                 is_convertible<
33                     typename iterator_traversal<Iterator>::type
34                   , random_access_traversal_tag
35                 >
36               , bidirectional_traversal_tag
37               , use_default
38             >::type
39         > type;
40     };
41   }
42 
43   template <class Predicate, class Iterator>
44   class filter_iterator
45     : public detail::filter_iterator_base<Predicate, Iterator>::type
46   {
47       typedef typename detail::filter_iterator_base<
48           Predicate, Iterator
49       >::type super_t;
50 
51       friend class iterator_core_access;
52 
53    public:
filter_iterator()54       filter_iterator() { }
55 
filter_iterator(Predicate f,Iterator x,Iterator end_=Iterator ())56       filter_iterator(Predicate f, Iterator x, Iterator end_ = Iterator())
57           : super_t(x), m_predicate(f), m_end(end_)
58       {
59           satisfy_predicate();
60       }
61 
filter_iterator(Iterator x,Iterator end_=Iterator ())62       filter_iterator(Iterator x, Iterator end_ = Iterator())
63         : super_t(x), m_predicate(), m_end(end_)
64       {
65         // Pro8 is a little too aggressive about instantiating the
66         // body of this function.
67 #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
68           // Don't allow use of this constructor if Predicate is a
69           // function pointer type, since it will be 0.
70           BOOST_STATIC_ASSERT(is_class<Predicate>::value);
71 #endif
72           satisfy_predicate();
73       }
74 
75       template<class OtherIterator>
filter_iterator(filter_iterator<Predicate,OtherIterator> const & t,typename enable_if_convertible<OtherIterator,Iterator>::type * =0)76       filter_iterator(
77           filter_iterator<Predicate, OtherIterator> const& t
78           , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
79           )
80           : super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {}
81 
predicate() const82       Predicate predicate() const { return m_predicate; }
83 
end() const84       Iterator end() const { return m_end; }
85 
86    private:
increment()87       void increment()
88       {
89           ++(this->base_reference());
90           satisfy_predicate();
91       }
92 
decrement()93       void decrement()
94       {
95         while(!this->m_predicate(*--(this->base_reference()))){};
96       }
97 
satisfy_predicate()98       void satisfy_predicate()
99       {
100           while (this->base() != this->m_end && !this->m_predicate(*this->base()))
101               ++(this->base_reference());
102       }
103 
104       // Probably should be the initial base class so it can be
105       // optimized away via EBO if it is an empty class.
106       Predicate m_predicate;
107       Iterator m_end;
108   };
109 
110   template <class Predicate, class Iterator>
111   inline filter_iterator<Predicate,Iterator>
make_filter_iterator(Predicate f,Iterator x,Iterator end=Iterator ())112   make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator())
113   {
114       return filter_iterator<Predicate,Iterator>(f,x,end);
115   }
116 
117   template <class Predicate, class Iterator>
118   inline filter_iterator<Predicate,Iterator>
make_filter_iterator(typename iterators::enable_if<is_class<Predicate>,Iterator>::type x,Iterator end=Iterator ())119   make_filter_iterator(
120       typename iterators::enable_if<
121           is_class<Predicate>
122         , Iterator
123       >::type x
124     , Iterator end = Iterator())
125   {
126       return filter_iterator<Predicate,Iterator>(x,end);
127   }
128 
129 } // namespace iterators
130 
131 using iterators::filter_iterator;
132 using iterators::make_filter_iterator;
133 
134 } // namespace boost
135 
136 #endif // BOOST_FILTER_ITERATOR_23022003THW_HPP
137