• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Range library
2 //
3 //  Copyright Neil Groves 2007. 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_REPLACED_IF_IMPL_HPP_INCLUDED
12 #define BOOST_RANGE_ADAPTOR_REPLACED_IF_IMPL_HPP_INCLUDED
13 
14 #include <boost/config.hpp>
15 #include <boost/range/adaptor/argument_fwd.hpp>
16 #include <boost/range/iterator_range.hpp>
17 #include <boost/range/begin.hpp>
18 #include <boost/range/end.hpp>
19 #include <boost/range/value_type.hpp>
20 #include <boost/range/concepts.hpp>
21 #include <boost/iterator/iterator_adaptor.hpp>
22 #include <boost/iterator/transform_iterator.hpp>
23 #include <boost/optional/optional.hpp>
24 
25 namespace boost
26 {
27     namespace range_detail
28     {
29         template< class Pred, class Value >
30         class replace_value_if
31         {
32         public:
33             typedef const Value& result_type;
34             typedef const Value& first_argument_type;
35 
36             // Rationale:
37             // required to allow the iterator to be default constructible.
replace_value_if()38             replace_value_if()
39             {
40             }
41 
replace_value_if(const Pred & pred,const Value & to)42             replace_value_if(const Pred& pred, const Value& to)
43                 : m_impl(data(pred, to))
44             {
45             }
46 
operator ()(const Value & x) const47             const Value& operator()(const Value& x) const
48             {
49                 return m_impl->m_pred(x) ? m_impl->m_to : x;
50             }
51 
52         private:
53             struct data
54             {
databoost::range_detail::replace_value_if::data55                 data(const Pred& p, const Value& t)
56                     : m_pred(p), m_to(t)
57                 {
58                 }
59 
60                 Pred  m_pred;
61                 Value m_to;
62             };
63             boost::optional<data> m_impl;
64         };
65 
66         template< class Pred, class R >
67         class replaced_if_range :
68             public boost::iterator_range<
69                 boost::transform_iterator<
70                     replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
71                     BOOST_DEDUCED_TYPENAME range_iterator<R>::type > >
72         {
73         private:
74             typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type > Fn;
75 
76             typedef boost::iterator_range<
77                 boost::transform_iterator<
78                     replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
79                     BOOST_DEDUCED_TYPENAME range_iterator<R>::type > > base_t;
80 
81         public:
82             typedef BOOST_DEDUCED_TYPENAME range_value<R>::type value_type;
83 
replaced_if_range(R & r,const Pred & pred,value_type to)84             replaced_if_range( R& r, const Pred& pred, value_type to )
85                 : base_t( make_transform_iterator( boost::begin(r), Fn(pred, to) ),
86                           make_transform_iterator( boost::end(r), Fn(pred, to) ) )
87             { }
88         };
89 
90         template< class Pred, class T >
91         class replace_if_holder
92         {
93         public:
replace_if_holder(const Pred & pred,const T & to)94             replace_if_holder( const Pred& pred, const T& to )
95                 : m_pred(pred), m_to(to)
96             { }
97 
pred() const98             const Pred& pred() const { return m_pred; }
to() const99             const T& to() const { return m_to; }
100 
101         private:
102             Pred m_pred;
103             T m_to;
104         };
105 
106         template< class Pred, class SinglePassRange, class Value >
107         inline replaced_if_range<Pred, SinglePassRange>
operator |(SinglePassRange & r,const replace_if_holder<Pred,Value> & f)108         operator|(SinglePassRange& r, const replace_if_holder<Pred, Value>& f)
109         {
110             BOOST_RANGE_CONCEPT_ASSERT((
111                 SinglePassRangeConcept<SinglePassRange>));
112 
113             return replaced_if_range<Pred, SinglePassRange>(
114                 r, f.pred(), f.to());
115         }
116 
117         template< class Pred, class SinglePassRange, class Value >
118         inline replaced_if_range<Pred, const SinglePassRange>
operator |(const SinglePassRange & r,const replace_if_holder<Pred,Value> & f)119         operator|(const SinglePassRange& r, const replace_if_holder<Pred, Value>& f)
120         {
121             BOOST_RANGE_CONCEPT_ASSERT((
122                 SinglePassRangeConcept<const SinglePassRange>));
123 
124             return replaced_if_range<Pred, const SinglePassRange>(
125                 r, f.pred(), f.to());
126         }
127     } // 'range_detail'
128 
129     using range_detail::replaced_if_range;
130 
131     namespace adaptors
132     {
133         namespace
134         {
135             const range_detail::forwarder2TU<range_detail::replace_if_holder>
136                 replaced_if =
137                     range_detail::forwarder2TU<range_detail::replace_if_holder>();
138         }
139 
140         template< class Pred, class SinglePassRange, class Value >
141         inline replaced_if_range<Pred, SinglePassRange>
replace_if(SinglePassRange & rng,Pred pred,Value to)142         replace_if(SinglePassRange& rng, Pred pred, Value to)
143         {
144             BOOST_RANGE_CONCEPT_ASSERT((
145                 SinglePassRangeConcept<SinglePassRange>));
146 
147             return range_detail::replaced_if_range<Pred, SinglePassRange>(
148                 rng, pred, to);
149         }
150 
151         template< class Pred, class SinglePassRange, class Value >
152         inline replaced_if_range<Pred, const SinglePassRange>
replace_if(const SinglePassRange & rng,Pred pred,Value to)153         replace_if(const SinglePassRange& rng, Pred pred, Value to)
154         {
155             BOOST_RANGE_CONCEPT_ASSERT((
156                 SinglePassRangeConcept<const SinglePassRange>));
157 
158             return range_detail::replaced_if_range<Pred, const SinglePassRange>(
159                 rng, pred, to);
160         }
161     } // 'adaptors'
162 
163 } // 'boost'
164 
165 #endif // include guard
166