You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.5KB

  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. RANGES_DISABLE_WARNINGS
  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. auto operator()(I const & i)
  55. -> CPP_ret(common_reference_t<unwrap_reference_t<Val const &>,
  56. iter_reference_t<I>>)( //
  57. requires(!invocable<Pred const &, iter_reference_t<I>>))
  58. {
  59. auto && x = *i;
  60. if(invoke(first(), (decltype(x) &&)x))
  61. return unwrap_reference(second());
  62. return (decltype(x) &&)x;
  63. }
  64. template<typename I>
  65. auto operator()(I const & i) const
  66. -> CPP_ret(common_reference_t<unwrap_reference_t<Val const &>,
  67. iter_reference_t<I>>)( //
  68. requires invocable<Pred const &, iter_reference_t<I>>)
  69. {
  70. auto && x = *i;
  71. if(invoke(first(), (decltype(x) &&)x))
  72. return unwrap_reference(second());
  73. return (decltype(x) &&)x;
  74. }
  75. template<typename I>
  76. auto operator()(move_tag, I const & i)
  77. -> CPP_ret(common_reference_t<unwrap_reference_t<Val const &>,
  78. iter_rvalue_reference_t<I>>)( //
  79. requires(!invocable<Pred const &, iter_rvalue_reference_t<I>>))
  80. {
  81. auto && x = iter_move(i);
  82. if(invoke(first(), (decltype(x) &&)x))
  83. return unwrap_reference(second());
  84. return (decltype(x) &&)x;
  85. }
  86. template<typename I>
  87. auto operator()(move_tag, I const & i) const
  88. -> CPP_ret(common_reference_t<unwrap_reference_t<Val const &>,
  89. iter_rvalue_reference_t<I>>)( //
  90. requires invocable<Pred const &, iter_rvalue_reference_t<I>>)
  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_fn
  105. {
  106. private:
  107. friend view_access;
  108. template<typename Pred, typename Val>
  109. static constexpr auto bind(replace_if_fn replace_if, Pred pred, Val new_value)
  110. {
  111. return make_pipeable(
  112. bind_back(replace_if, std::move(pred), std::move(new_value)));
  113. }
  114. public:
  115. template<typename Rng, typename Pred, typename Val>
  116. constexpr auto operator()(Rng && rng, Pred pred, Val new_value) const
  117. -> CPP_ret(replace_if_view<all_t<Rng>, Pred, Val>)( //
  118. requires viewable_range<Rng> && input_range<Rng> &&
  119. indirect_unary_predicate<Pred, iterator_t<Rng>> &&
  120. common_with<detail::decay_t<unwrap_reference_t<Val const &>>,
  121. range_value_t<Rng>> &&
  122. common_reference_with<unwrap_reference_t<Val const &>,
  123. range_reference_t<Rng>> &&
  124. common_reference_with<unwrap_reference_t<Val const &>,
  125. range_rvalue_reference_t<Rng>>)
  126. {
  127. return {all(static_cast<Rng &&>(rng)),
  128. {std::move(pred), std::move(new_value)}};
  129. }
  130. };
  131. /// \relates replace_if_fn
  132. /// \ingroup group-views
  133. RANGES_INLINE_VARIABLE(view<replace_if_fn>, replace_if)
  134. } // namespace views
  135. /// @}
  136. } // namespace ranges
  137. RANGES_RE_ENABLE_WARNINGS
  138. #endif