exclusive_scan.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Mitsutaka Takeda 2018-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_EXCLUSIVE_SCAN_HPP
  14. #define RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
  15. #include <concepts/concepts.hpp>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/functional/arithmetic.hpp>
  18. #include <range/v3/functional/bind_back.hpp>
  19. #include <range/v3/functional/invoke.hpp>
  20. #include <range/v3/view/adaptor.hpp>
  21. #include <range/v3/view/view.hpp>
  22. #include <range/v3/detail/prologue.hpp>
  23. namespace ranges
  24. {
  25. // clang-format off
  26. /// \concept exclusive_scan_constraints_
  27. /// \brief The \c exclusive_scan_constraints_ concept
  28. template(typename Rng, typename T, typename Fun)(
  29. concept (exclusive_scan_constraints_)(Rng, T, Fun),
  30. invocable<Fun &, T, range_reference_t<Rng>> AND
  31. assignable_from<T &, invoke_result_t<Fun &, T, range_reference_t<Rng>>>
  32. );
  33. /// \concept exclusive_scan_constraints
  34. /// \brief The \c exclusive_scan_constraints concept
  35. template<typename Rng, typename T, typename Fun>
  36. CPP_concept exclusive_scan_constraints =
  37. viewable_range<Rng> && input_range<Rng> &&
  38. copy_constructible<T> &&
  39. CPP_concept_ref(ranges::exclusive_scan_constraints_, Rng, T, Fun);
  40. // clang-format on
  41. /// \addtogroup group-views
  42. /// @{
  43. template<typename Rng, typename T, typename Fun>
  44. struct exclusive_scan_view : view_adaptor<exclusive_scan_view<Rng, T, Fun>, Rng>
  45. {
  46. private:
  47. friend range_access;
  48. CPP_assert(exclusive_scan_constraints<Rng, T, Fun>);
  49. semiregular_box_t<T> init_;
  50. semiregular_box_t<Fun> fun_;
  51. using single_pass = meta::bool_<single_pass_iterator_<iterator_t<Rng>>>;
  52. using use_sentinel_t = meta::bool_<!common_range<Rng> || single_pass{}>;
  53. template<bool IsConst>
  54. struct adaptor : adaptor_base
  55. {
  56. private:
  57. friend struct adaptor<!IsConst>;
  58. using exclusive_scan_view_t = meta::const_if_c<IsConst, exclusive_scan_view>;
  59. using CRng = meta::const_if_c<IsConst, Rng>;
  60. semiregular_box_t<T> sum_;
  61. exclusive_scan_view_t * rng_;
  62. // clang-format off
  63. auto CPP_auto_fun(move_or_copy_init)(std::false_type)
  64. (
  65. return (rng_->init_)
  66. )
  67. // If the base range is single-pass, we can move the init value.
  68. auto CPP_auto_fun(move_or_copy_init)(std::true_type)
  69. (
  70. return std::move(rng_->init_)
  71. )
  72. // clang-format on
  73. public : using single_pass = exclusive_scan_view::single_pass;
  74. adaptor() = default;
  75. adaptor(exclusive_scan_view_t * rng)
  76. : rng_(rng)
  77. {}
  78. template(bool Other)(
  79. requires IsConst AND CPP_NOT(Other)) //
  80. adaptor(adaptor<Other> that)
  81. : rng_(that.rng_)
  82. {}
  83. iterator_t<CRng> begin(exclusive_scan_view_t &)
  84. {
  85. sum_ = move_or_copy_init(single_pass{});
  86. return ranges::begin(rng_->base());
  87. }
  88. T read(iterator_t<CRng> const &) const
  89. {
  90. return sum_;
  91. }
  92. void next(iterator_t<CRng> & it)
  93. {
  94. RANGES_EXPECT(it != ranges::end(rng_->base()));
  95. sum_ = invoke(rng_->fun_, static_cast<T &&>(std::move(sum_)), *it);
  96. ++it;
  97. }
  98. void prev() = delete;
  99. };
  100. adaptor<false> begin_adaptor()
  101. {
  102. return {this};
  103. }
  104. meta::if_<use_sentinel_t, adaptor_base, adaptor<false>> end_adaptor()
  105. {
  106. return {this};
  107. }
  108. CPP_member
  109. auto begin_adaptor() const //
  110. -> CPP_ret(adaptor<true>)(
  111. requires exclusive_scan_constraints<Rng const, T, Fun const>)
  112. {
  113. return {this};
  114. }
  115. CPP_member
  116. auto end_adaptor() const
  117. -> CPP_ret(meta::if_<use_sentinel_t, adaptor_base, adaptor<true>>)(
  118. requires exclusive_scan_constraints<Rng const, T, Fun const>)
  119. {
  120. return {this};
  121. }
  122. public:
  123. exclusive_scan_view() = default;
  124. constexpr exclusive_scan_view(Rng rng, T init, Fun fun)
  125. : exclusive_scan_view::view_adaptor{std::move(rng)}
  126. , init_(std::move(init))
  127. , fun_(std::move(fun))
  128. {}
  129. CPP_auto_member
  130. auto CPP_fun(size)()(const
  131. requires sized_range<Rng const>)
  132. {
  133. return ranges::size(this->base());
  134. }
  135. CPP_auto_member
  136. auto CPP_fun(size)()(
  137. requires sized_range<Rng>)
  138. {
  139. return ranges::size(this->base());
  140. }
  141. };
  142. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  143. template(typename Rng, typename T, typename Fun)(
  144. requires copy_constructible<T> AND copy_constructible<Fun>)
  145. exclusive_scan_view(Rng &&, T, Fun) //
  146. -> exclusive_scan_view<views::all_t<Rng>, T, Fun>;
  147. #endif
  148. namespace views
  149. {
  150. struct exclusive_scan_base_fn
  151. {
  152. template(typename Rng, typename T, typename Fun = plus)(
  153. requires exclusive_scan_constraints<Rng, T, Fun>)
  154. constexpr exclusive_scan_view<all_t<Rng>, T, Fun> //
  155. operator()(Rng && rng, T init, Fun fun = Fun{}) const
  156. {
  157. return {all(static_cast<Rng &&>(rng)), std::move(init), std::move(fun)};
  158. }
  159. };
  160. struct exclusive_scan_fn : exclusive_scan_base_fn
  161. {
  162. using exclusive_scan_base_fn::operator();
  163. template<typename T, typename Fun = plus>
  164. constexpr auto operator()(T init, Fun fun = {}) const
  165. {
  166. return make_view_closure(
  167. bind_back(exclusive_scan_base_fn{}, std::move(init), std::move(fun)));
  168. }
  169. };
  170. /// \relates exclusive_scan_fn
  171. /// \ingroup group-views
  172. RANGES_INLINE_VARIABLE(exclusive_scan_fn, exclusive_scan)
  173. } // namespace views
  174. /// @}
  175. } // namespace ranges
  176. #include <range/v3/detail/epilogue.hpp>
  177. #endif // RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP