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