1 // Boost.Range library
2 //
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)
7 //
8 // For more information, see http://www.boost.org/libs/range/
9 //
10 
11 #ifndef BOOST_RANGE_ADAPTOR_FILTERED_HPP
12 #define BOOST_RANGE_ADAPTOR_FILTERED_HPP
13 
14 #include <boost/range/adaptor/argument_fwd.hpp>
15 #include <boost/range/detail/default_constructible_unary_fn.hpp>
16 #include <boost/range/iterator_range.hpp>
17 #include <boost/range/concepts.hpp>
18 #include <boost/iterator/filter_iterator.hpp>
19 
20 namespace boost
21 {
22     namespace range_detail
23     {
24         template< class P, class R >
25         struct filtered_range :
26             boost::iterator_range<
27                 boost::filter_iterator<
28                     typename default_constructible_unary_fn_gen<P, bool>::type,
29                     typename range_iterator<R>::type
30                 >
31             >
32         {
33         private:
34             typedef boost::iterator_range<
35                 boost::filter_iterator<
36                     typename default_constructible_unary_fn_gen<P, bool>::type,
37                     typename range_iterator<R>::type
38                 >
39             > base;
40         public:
41             typedef typename default_constructible_unary_fn_gen<P, bool>::type
42                 pred_t;
43 
filtered_rangeboost::range_detail::filtered_range44             filtered_range(P p, R& r)
45             : base(make_filter_iterator(pred_t(p),
46                                         boost::begin(r), boost::end(r)),
47                    make_filter_iterator(pred_t(p),
48                                         boost::end(r), boost::end(r)))
49             { }
50         };
51 
52         template< class T >
53         struct filter_holder : holder<T>
54         {
filter_holderboost::range_detail::filter_holder55             filter_holder( T r ) : holder<T>(r)
56             { }
57         };
58 
59         template< class SinglePassRange, class Predicate >
60         inline filtered_range<Predicate, SinglePassRange>
operator |(SinglePassRange & r,const filter_holder<Predicate> & f)61         operator|(SinglePassRange& r,
62                   const filter_holder<Predicate>& f)
63         {
64             BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange>));
65             return filtered_range<Predicate, SinglePassRange>( f.val, r );
66         }
67 
68         template< class SinglePassRange, class Predicate >
69         inline filtered_range<Predicate, const SinglePassRange>
operator |(const SinglePassRange & r,const filter_holder<Predicate> & f)70         operator|(const SinglePassRange& r,
71                   const filter_holder<Predicate>& f )
72         {
73             BOOST_RANGE_CONCEPT_ASSERT((
74                 SinglePassRangeConcept<const SinglePassRange>));
75             return filtered_range<Predicate, const SinglePassRange>( f.val, r );
76         }
77 
78     } // 'range_detail'
79 
80     // Unusual use of 'using' is intended to bring filter_range into the boost namespace
81     // while leaving the mechanics of the '|' operator in range_detail and maintain
82     // argument dependent lookup.
83     // filter_range logically needs to be in the boost namespace to allow user of
84     // the library to define the return type for filter()
85     using range_detail::filtered_range;
86 
87     namespace adaptors
88     {
89         namespace
90         {
91             const range_detail::forwarder<range_detail::filter_holder>
92                     filtered =
93                        range_detail::forwarder<range_detail::filter_holder>();
94         }
95 
96         template<class SinglePassRange, class Predicate>
97         inline filtered_range<Predicate, SinglePassRange>
filter(SinglePassRange & rng,Predicate filter_pred)98         filter(SinglePassRange& rng, Predicate filter_pred)
99         {
100             BOOST_RANGE_CONCEPT_ASSERT((
101                 SinglePassRangeConcept<SinglePassRange>));
102 
103             return range_detail::filtered_range<
104                 Predicate, SinglePassRange>( filter_pred, rng );
105         }
106 
107         template<class SinglePassRange, class Predicate>
108         inline filtered_range<Predicate, const SinglePassRange>
filter(const SinglePassRange & rng,Predicate filter_pred)109         filter(const SinglePassRange& rng, Predicate filter_pred)
110         {
111             BOOST_RANGE_CONCEPT_ASSERT((
112                 SinglePassRangeConcept<const SinglePassRange>));
113 
114             return range_detail::filtered_range<
115                 Predicate, const SinglePassRange>( filter_pred, rng );
116         }
117     } // 'adaptors'
118 
119 }
120 
121 #endif
122