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 > 107 inline replaced_if_range<Pred, SinglePassRange> operator |(SinglePassRange & r,const replace_if_holder<Pred,BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type> & f)108 operator|( 109 SinglePassRange& r, 110 const replace_if_holder< 111 Pred, 112 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f) 113 { 114 BOOST_RANGE_CONCEPT_ASSERT(( 115 SinglePassRangeConcept<SinglePassRange>)); 116 117 return replaced_if_range<Pred, SinglePassRange>( 118 r, f.pred(), f.to()); 119 } 120 121 template< class Pred, class SinglePassRange > 122 inline replaced_if_range<Pred, const SinglePassRange> operator |(const SinglePassRange & r,const replace_if_holder<Pred,BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type> & f)123 operator|( 124 const SinglePassRange& r, 125 const replace_if_holder< 126 Pred, 127 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f) 128 { 129 BOOST_RANGE_CONCEPT_ASSERT(( 130 SinglePassRangeConcept<const SinglePassRange>)); 131 132 return replaced_if_range<Pred, const SinglePassRange>( 133 r, f.pred(), f.to()); 134 } 135 } // 'range_detail' 136 137 using range_detail::replaced_if_range; 138 139 namespace adaptors 140 { 141 namespace 142 { 143 const range_detail::forwarder2TU<range_detail::replace_if_holder> 144 replaced_if = 145 range_detail::forwarder2TU<range_detail::replace_if_holder>(); 146 } 147 148 template<class Pred, class SinglePassRange> 149 inline replaced_if_range<Pred, SinglePassRange> replace_if(SinglePassRange & rng,Pred pred,BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type to)150 replace_if(SinglePassRange& rng, Pred pred, 151 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type to) 152 { 153 BOOST_RANGE_CONCEPT_ASSERT(( 154 SinglePassRangeConcept<SinglePassRange>)); 155 156 return range_detail::replaced_if_range<Pred, SinglePassRange>( 157 rng, pred, to); 158 } 159 160 template<class Pred, class SinglePassRange> 161 inline replaced_if_range<Pred, const SinglePassRange> replace_if(const SinglePassRange & rng,Pred pred,BOOST_DEDUCED_TYPENAME range_value<const SinglePassRange>::type to)162 replace_if( 163 const SinglePassRange& rng, 164 Pred pred, 165 BOOST_DEDUCED_TYPENAME range_value<const SinglePassRange>::type to) 166 { 167 BOOST_RANGE_CONCEPT_ASSERT(( 168 SinglePassRangeConcept<const SinglePassRange>)); 169 170 return range_detail::replaced_if_range<Pred, const SinglePassRange>( 171 rng, pred, to); 172 } 173 } // 'adaptors' 174 175 } // 'boost' 176 177 #endif // include guard 178