replace.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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_HPP
  14. #define RANGES_V3_VIEW_REPLACE_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/utility/static_const.hpp>
  22. #include <range/v3/view/all.hpp>
  23. #include <range/v3/view/transform.hpp>
  24. #include <range/v3/view/view.hpp>
  25. #include <range/v3/detail/prologue.hpp>
  26. namespace ranges
  27. {
  28. /// \cond
  29. namespace detail
  30. {
  31. template<typename Val1, typename Val2>
  32. struct replacer_fn
  33. {
  34. private:
  35. Val1 old_value_;
  36. Val2 new_value_;
  37. public:
  38. replacer_fn() = default;
  39. constexpr replacer_fn(Val1 old_value, Val2 new_value)
  40. : old_value_(std::move(old_value))
  41. , new_value_(std::move(new_value))
  42. {}
  43. template<typename I>
  44. [[noreturn]] common_type_t<decay_t<unwrap_reference_t<Val2 const &>>,
  45. iter_value_t<I>> &
  46. operator()(copy_tag, I const &) const
  47. {
  48. RANGES_EXPECT(false);
  49. }
  50. template<typename I>
  51. common_reference_t<unwrap_reference_t<Val2 const &>, iter_reference_t<I>>
  52. operator()(I const & i) const
  53. {
  54. auto && x = *i;
  55. if(x == unwrap_reference(old_value_))
  56. return unwrap_reference(new_value_);
  57. return ((decltype(x) &&)x);
  58. }
  59. template<typename I>
  60. common_reference_t<unwrap_reference_t<Val2 const &>,
  61. iter_rvalue_reference_t<I>>
  62. operator()(move_tag, I const & i) const
  63. {
  64. auto && x = iter_move(i);
  65. if(x == unwrap_reference(old_value_))
  66. return unwrap_reference(new_value_);
  67. return ((decltype(x) &&)x);
  68. }
  69. };
  70. } // namespace detail
  71. /// \endcond
  72. /// \addtogroup group-views
  73. /// @{
  74. namespace views
  75. {
  76. struct replace_base_fn
  77. {
  78. template(typename Rng, typename Val1, typename Val2)(
  79. requires viewable_range<Rng> AND input_range<Rng> AND
  80. same_as<
  81. detail::decay_t<unwrap_reference_t<Val1>>,
  82. detail::decay_t<unwrap_reference_t<Val2>>> AND
  83. equality_comparable_with<
  84. detail::decay_t<unwrap_reference_t<Val1>>,
  85. range_value_t<Rng>> AND
  86. common_with<detail::decay_t<unwrap_reference_t<Val2 const &>>,
  87. range_value_t<Rng>> AND
  88. common_reference_with<unwrap_reference_t<Val2 const &>,
  89. range_reference_t<Rng>> AND
  90. common_reference_with<
  91. unwrap_reference_t<Val2 const &>,
  92. range_rvalue_reference_t<Rng>>)
  93. constexpr replace_view< //
  94. all_t<Rng>, //
  95. detail::decay_t<Val1>, //
  96. detail::decay_t<Val2>> //
  97. operator()(Rng && rng, Val1 && old_value,
  98. Val2 && new_value) const //
  99. {
  100. return {
  101. all(static_cast<Rng &&>(rng)),
  102. {static_cast<Val1 &&>(old_value), static_cast<Val2 &&>(new_value)}};
  103. }
  104. };
  105. struct replace_fn : replace_base_fn
  106. {
  107. using replace_base_fn::operator();
  108. template(typename Val1, typename Val2)(
  109. requires same_as<detail::decay_t<unwrap_reference_t<Val1>>,
  110. detail::decay_t<unwrap_reference_t<Val2>>>)
  111. constexpr auto operator()(Val1 old_value, Val2 new_value) const
  112. {
  113. return make_view_closure(bind_back(
  114. replace_base_fn{}, std::move(old_value), std::move(new_value)));
  115. }
  116. };
  117. /// \relates replace_fn
  118. /// \ingroup group-views
  119. RANGES_INLINE_VARIABLE(replace_fn, replace)
  120. } // namespace views
  121. /// @}
  122. } // namespace ranges
  123. #include <range/v3/detail/epilogue.hpp>
  124. #endif