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

source code of boost/libs/iterator/include/boost/iterator/filter_iterator.hpp