replace_if.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_REPLACE_IF_HPP
  14. #define RANGES_V3_VIEW_REPLACE_IF_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <concepts/concepts.hpp>
  19. #include <range/v3/range_fwd.hpp>
  20. #include <range/v3/functional/bind_back.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/utility/compressed_pair.hpp>
  23. #include <range/v3/utility/semiregular_box.hpp>
  24. #include <range/v3/utility/static_const.hpp>
  25. #include <range/v3/view/all.hpp>
  26. #include <range/v3/view/transform.hpp>
  27. #include <range/v3/view/view.hpp>
  28. #include <range/v3/detail/prologue.hpp>
  29. namespace ranges
  30. {
  31. /// \cond
  32. namespace detail
  33. {
  34. template<typename Pred, typename Val>
  35. struct replacer_if_fn : compressed_pair<semiregular_box_t<Pred>, Val>
  36. {
  37. private:
  38. using base_t = compressed_pair<semiregular_box_t<Pred>, Val>;
  39. using base_t::first;
  40. using base_t::second;
  41. public:
  42. replacer_if_fn() = default;
  43. constexpr replacer_if_fn(Pred pred, Val new_value)
  44. : base_t{std::move(pred), std::move(new_value)}
  45. {}
  46. template<typename I>
  47. [[noreturn]] common_type_t<decay_t<unwrap_reference_t<Val const &>>,
  48. iter_value_t<I>> &
  49. operator()(copy_tag, I const &) const
  50. {
  51. RANGES_EXPECT(false);
  52. }
  53. template(typename I)(
  54. requires (!invocable<Pred const &, iter_reference_t<I>>))
  55. common_reference_t<unwrap_reference_t<Val const &>, iter_reference_t<I>> //
  56. operator()(I const & i)
  57. {
  58. auto && x = *i;
  59. if(invoke(first(), (decltype(x) &&)x)) //
  60. return unwrap_reference(second());
  61. return (decltype(x) &&)x;
  62. }
  63. template(typename I)(
  64. requires invocable<Pred const &, iter_reference_t<I>>)
  65. common_reference_t<unwrap_reference_t<Val const &>, iter_reference_t<I>> //
  66. operator()(I const & i) const
  67. {
  68. auto && x = *i;
  69. if(invoke(first(), (decltype(x) &&)x)) //
  70. return unwrap_reference(second());
  71. return (decltype(x) &&)x;
  72. }
  73. template(typename I)(
  74. requires (!invocable<Pred const &, iter_rvalue_reference_t<I>>))
  75. common_reference_t<
  76. unwrap_reference_t<Val const &>, //
  77. iter_rvalue_reference_t<I>> //
  78. operator()(move_tag, I const & i)
  79. {
  80. auto && x = iter_move(i);
  81. if(invoke(first(), (decltype(x) &&)x)) //
  82. return unwrap_reference(second());
  83. return (decltype(x) &&)x;
  84. }
  85. template(typename I)(
  86. requires invocable<Pred const &, iter_rvalue_reference_t<I>>)
  87. common_reference_t< //
  88. unwrap_reference_t<Val const &>, //
  89. iter_rvalue_reference_t<I>> //
  90. operator()(move_tag, I const & i) const
  91. {
  92. auto && x = iter_move(i);
  93. if(invoke(first(), (decltype(x) &&)x)) //
  94. return unwrap_reference(second());
  95. return (decltype(x) &&)x;
  96. }
  97. };
  98. } // namespace detail
  99. /// \endcond
  100. /// \addtogroup group-views
  101. /// @{
  102. namespace views
  103. {
  104. struct replace_if_base_fn
  105. {
  106. template(typename Rng, typename Pred, typename Val)(
  107. requires viewable_range<Rng> AND input_range<Rng> AND
  108. indirect_unary_predicate<Pred, iterator_t<Rng>> AND
  109. common_with<detail::decay_t<unwrap_reference_t<Val const &>>,
  110. range_value_t<Rng>> AND
  111. common_reference_with<unwrap_reference_t<Val const &>,
  112. range_reference_t<Rng>> AND
  113. common_reference_with<unwrap_reference_t<Val const &>,
  114. range_rvalue_reference_t<Rng>>)
  115. constexpr replace_if_view<all_t<Rng>, Pred, Val> //
  116. operator()(Rng && rng, Pred pred, Val new_value) const
  117. {
  118. return {all(static_cast<Rng &&>(rng)),
  119. {std::move(pred), std::move(new_value)}};
  120. }
  121. };
  122. struct replace_if_fn : replace_if_base_fn
  123. {
  124. using replace_if_base_fn::operator();
  125. template<typename Pred, typename Val>
  126. constexpr auto operator()(Pred pred, Val new_value) const
  127. {
  128. return make_view_closure(bind_back(
  129. replace_if_base_fn{}, std::move(pred), std::move(new_value)));
  130. }
  131. };
  132. /// \relates replace_if_fn
  133. /// \ingroup group-views
  134. RANGES_INLINE_VARIABLE(replace_if_fn, replace_if)
  135. } // namespace views
  136. /// @}
  137. } // namespace ranges
  138. #include <range/v3/detail/epilogue.hpp>
  139. #endif