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