3 // Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org/libs/range/
11 #ifndef BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
12 #define BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
14 #include <boost/config.hpp>
16 #pragma warning( push )
17 #pragma warning( disable : 4355 )
20 #include <boost/range/adaptor/argument_fwd.hpp>
21 #include <boost/range/iterator_range.hpp>
22 #include <boost/range/begin.hpp>
23 #include <boost/range/end.hpp>
24 #include <boost/range/concepts.hpp>
25 #include <boost/iterator/iterator_adaptor.hpp>
26 #include <boost/next_prior.hpp>
31 namespace range_detail
33 template< class Iter, class Pred, bool default_pass >
35 : public boost::iterator_adaptor<
36 skip_iterator<Iter,Pred,default_pass>,
38 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
39 boost::forward_traversal_tag,
40 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
41 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
46 typedef boost::iterator_adaptor<
47 skip_iterator<Iter,Pred,default_pass>,
49 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
50 boost::forward_traversal_tag,
51 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
52 BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
59 skip_iterator() : m_last() {}
61 skip_iterator(iter_t it, iter_t last, const Pred& pred)
68 template<class OtherIter>
69 skip_iterator( const skip_iterator<OtherIter, pred_t, default_pass>& other )
70 : base_t(other.base())
72 , m_last(other.m_last)
78 iter_t& it = this->base_reference();
79 BOOST_ASSERT( it != m_last );
80 pred_t& bi_pred = *this;
87 while (it != m_last && !bi_pred(*prev, *it))
95 for (; it != m_last; ++it, ++prev)
97 if (bi_pred(*prev, *it))
109 template< class P, class R, bool default_pass >
110 struct adjacent_filtered_range
111 : iterator_range< skip_iterator<
112 BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
119 typedef skip_iterator<
120 BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
126 typedef iterator_range<skip_iter>
129 typedef BOOST_DEDUCED_TYPENAME range_iterator<R>::type raw_iterator;
132 adjacent_filtered_range( const P& p, R& r )
133 : base_range(skip_iter(boost::begin(r), boost::end(r), p),
134 skip_iter(boost::end(r), boost::end(r), p))
140 struct adjacent_holder : holder<T>
142 adjacent_holder( T r ) : holder<T>(r)
147 struct adjacent_excl_holder : holder<T>
149 adjacent_excl_holder( T r ) : holder<T>(r)
153 template< class ForwardRng, class BinPredicate >
154 inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
155 operator|( ForwardRng& r,
156 const adjacent_holder<BinPredicate>& f )
158 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
160 return adjacent_filtered_range<BinPredicate, ForwardRng, true>( f.val, r );
163 template< class ForwardRng, class BinPredicate >
164 inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
165 operator|( const ForwardRng& r,
166 const adjacent_holder<BinPredicate>& f )
168 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
170 return adjacent_filtered_range<BinPredicate,
171 const ForwardRng, true>( f.val, r );
174 template< class ForwardRng, class BinPredicate >
175 inline adjacent_filtered_range<BinPredicate, ForwardRng, false>
176 operator|( ForwardRng& r,
177 const adjacent_excl_holder<BinPredicate>& f )
179 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
180 return adjacent_filtered_range<BinPredicate, ForwardRng, false>( f.val, r );
183 template< class ForwardRng, class BinPredicate >
184 inline adjacent_filtered_range<BinPredicate, const ForwardRng, false>
185 operator|( const ForwardRng& r,
186 const adjacent_excl_holder<BinPredicate>& f )
188 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
189 return adjacent_filtered_range<BinPredicate,
190 const ForwardRng, false>( f.val, r );
195 // Bring adjacent_filter_range into the boost namespace so that users of
196 // this library may specify the return type of the '|' operator and
198 using range_detail::adjacent_filtered_range;
204 const range_detail::forwarder<range_detail::adjacent_holder>
206 range_detail::forwarder<range_detail::adjacent_holder>();
208 const range_detail::forwarder<range_detail::adjacent_excl_holder>
209 adjacent_filtered_excl =
210 range_detail::forwarder<range_detail::adjacent_excl_holder>();
213 template<class ForwardRng, class BinPredicate>
214 inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
215 adjacent_filter(ForwardRng& rng, BinPredicate filter_pred)
217 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
218 return adjacent_filtered_range<BinPredicate, ForwardRng, true>(filter_pred, rng);
221 template<class ForwardRng, class BinPredicate>
222 inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
223 adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred)
225 BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
226 return adjacent_filtered_range<BinPredicate, const ForwardRng, true>(filter_pred, rng);
234 #pragma warning( pop )