replaced_if.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. #ifndef BOOST_RANGE_ADAPTOR_REPLACED_IF_IMPL_HPP_INCLUDED
  11. #define BOOST_RANGE_ADAPTOR_REPLACED_IF_IMPL_HPP_INCLUDED
  12. #include <boost/config.hpp>
  13. #include <boost/range/adaptor/argument_fwd.hpp>
  14. #include <boost/range/iterator_range.hpp>
  15. #include <boost/range/begin.hpp>
  16. #include <boost/range/end.hpp>
  17. #include <boost/range/value_type.hpp>
  18. #include <boost/range/concepts.hpp>
  19. #include <boost/iterator/iterator_adaptor.hpp>
  20. #include <boost/iterator/transform_iterator.hpp>
  21. #include <boost/optional/optional.hpp>
  22. namespace boost
  23. {
  24. namespace range_detail
  25. {
  26. template< class Pred, class Value >
  27. class replace_value_if
  28. {
  29. public:
  30. typedef const Value& result_type;
  31. typedef const Value& first_argument_type;
  32. // Rationale:
  33. // required to allow the iterator to be default constructible.
  34. replace_value_if()
  35. {
  36. }
  37. replace_value_if(const Pred& pred, const Value& to)
  38. : m_impl(data(pred, to))
  39. {
  40. }
  41. const Value& operator()(const Value& x) const
  42. {
  43. return m_impl->m_pred(x) ? m_impl->m_to : x;
  44. }
  45. private:
  46. struct data
  47. {
  48. data(const Pred& p, const Value& t)
  49. : m_pred(p), m_to(t)
  50. {
  51. }
  52. Pred m_pred;
  53. Value m_to;
  54. };
  55. boost::optional<data> m_impl;
  56. };
  57. template< class Pred, class R >
  58. class replaced_if_range :
  59. public boost::iterator_range<
  60. boost::transform_iterator<
  61. replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
  62. BOOST_DEDUCED_TYPENAME range_iterator<R>::type > >
  63. {
  64. private:
  65. typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type > Fn;
  66. typedef boost::iterator_range<
  67. boost::transform_iterator<
  68. replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
  69. BOOST_DEDUCED_TYPENAME range_iterator<R>::type > > base_t;
  70. public:
  71. typedef BOOST_DEDUCED_TYPENAME range_value<R>::type value_type;
  72. replaced_if_range( R& r, const Pred& pred, value_type to )
  73. : base_t( make_transform_iterator( boost::begin(r), Fn(pred, to) ),
  74. make_transform_iterator( boost::end(r), Fn(pred, to) ) )
  75. { }
  76. };
  77. template< class Pred, class T >
  78. class replace_if_holder
  79. {
  80. public:
  81. replace_if_holder( const Pred& pred, const T& to )
  82. : m_pred(pred), m_to(to)
  83. { }
  84. const Pred& pred() const { return m_pred; }
  85. const T& to() const { return m_to; }
  86. private:
  87. Pred m_pred;
  88. T m_to;
  89. };
  90. template< class Pred, class SinglePassRange, class Value >
  91. inline replaced_if_range<Pred, SinglePassRange>
  92. operator|(SinglePassRange& r, const replace_if_holder<Pred, Value>& f)
  93. {
  94. BOOST_RANGE_CONCEPT_ASSERT((
  95. SinglePassRangeConcept<SinglePassRange>));
  96. return replaced_if_range<Pred, SinglePassRange>(
  97. r, f.pred(), f.to());
  98. }
  99. template< class Pred, class SinglePassRange, class Value >
  100. inline replaced_if_range<Pred, const SinglePassRange>
  101. operator|(const SinglePassRange& r, const replace_if_holder<Pred, Value>& f)
  102. {
  103. BOOST_RANGE_CONCEPT_ASSERT((
  104. SinglePassRangeConcept<const SinglePassRange>));
  105. return replaced_if_range<Pred, const SinglePassRange>(
  106. r, f.pred(), f.to());
  107. }
  108. } // 'range_detail'
  109. using range_detail::replaced_if_range;
  110. namespace adaptors
  111. {
  112. namespace
  113. {
  114. const range_detail::forwarder2TU<range_detail::replace_if_holder>
  115. replaced_if =
  116. range_detail::forwarder2TU<range_detail::replace_if_holder>();
  117. }
  118. template< class Pred, class SinglePassRange, class Value >
  119. inline replaced_if_range<Pred, SinglePassRange>
  120. replace_if(SinglePassRange& rng, Pred pred, Value to)
  121. {
  122. BOOST_RANGE_CONCEPT_ASSERT((
  123. SinglePassRangeConcept<SinglePassRange>));
  124. return range_detail::replaced_if_range<Pred, SinglePassRange>(
  125. rng, pred, to);
  126. }
  127. template< class Pred, class SinglePassRange, class Value >
  128. inline replaced_if_range<Pred, const SinglePassRange>
  129. replace_if(const SinglePassRange& rng, Pred pred, Value to)
  130. {
  131. BOOST_RANGE_CONCEPT_ASSERT((
  132. SinglePassRangeConcept<const SinglePassRange>));
  133. return range_detail::replaced_if_range<Pred, const SinglePassRange>(
  134. rng, pred, to);
  135. }
  136. } // 'adaptors'
  137. } // 'boost'
  138. #endif // include guard