File indexing completed on 2025-01-18 10:09:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
0015 #define RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
0016
0017 #include <concepts/concepts.hpp>
0018
0019 #include <range/v3/range_fwd.hpp>
0020
0021 #include <range/v3/functional/arithmetic.hpp>
0022 #include <range/v3/functional/bind_back.hpp>
0023 #include <range/v3/functional/invoke.hpp>
0024 #include <range/v3/view/adaptor.hpp>
0025 #include <range/v3/view/view.hpp>
0026
0027 #include <range/v3/detail/prologue.hpp>
0028
0029 namespace ranges
0030 {
0031
0032
0033
0034 template(typename Rng, typename T, typename Fun)(
0035 concept (exclusive_scan_constraints_)(Rng, T, Fun),
0036 invocable<Fun &, T, range_reference_t<Rng>> AND
0037 assignable_from<T &, invoke_result_t<Fun &, T, range_reference_t<Rng>>>
0038 );
0039
0040
0041 template<typename Rng, typename T, typename Fun>
0042 CPP_concept exclusive_scan_constraints =
0043 viewable_range<Rng> && input_range<Rng> &&
0044 copy_constructible<T> &&
0045 CPP_concept_ref(ranges::exclusive_scan_constraints_, Rng, T, Fun);
0046
0047
0048
0049
0050 template<typename Rng, typename T, typename Fun>
0051 struct exclusive_scan_view : view_adaptor<exclusive_scan_view<Rng, T, Fun>, Rng>
0052 {
0053 private:
0054 friend range_access;
0055 CPP_assert(exclusive_scan_constraints<Rng, T, Fun>);
0056
0057 semiregular_box_t<T> init_;
0058 semiregular_box_t<Fun> fun_;
0059 using single_pass = meta::bool_<single_pass_iterator_<iterator_t<Rng>>>;
0060 using use_sentinel_t = meta::bool_<!common_range<Rng> || single_pass{}>;
0061
0062 template<bool IsConst>
0063 struct adaptor : adaptor_base
0064 {
0065 private:
0066 friend struct adaptor<!IsConst>;
0067 using exclusive_scan_view_t = meta::const_if_c<IsConst, exclusive_scan_view>;
0068 using CRng = meta::const_if_c<IsConst, Rng>;
0069 semiregular_box_t<T> sum_;
0070 exclusive_scan_view_t * rng_;
0071
0072
0073 auto CPP_auto_fun(move_or_copy_init)(std::false_type)
0074 (
0075 return (rng_->init_)
0076 )
0077
0078
0079 auto CPP_auto_fun(move_or_copy_init)(std::true_type)
0080 (
0081 return std::move(rng_->init_)
0082 )
0083
0084 public : using single_pass = exclusive_scan_view::single_pass;
0085 adaptor() = default;
0086 adaptor(exclusive_scan_view_t * rng)
0087 : rng_(rng)
0088 {}
0089 template(bool Other)(
0090 requires IsConst AND CPP_NOT(Other))
0091 adaptor(adaptor<Other> that)
0092 : rng_(that.rng_)
0093 {}
0094 iterator_t<CRng> begin(exclusive_scan_view_t &)
0095 {
0096 sum_ = move_or_copy_init(single_pass{});
0097 return ranges::begin(rng_->base());
0098 }
0099 T read(iterator_t<CRng> const &) const
0100 {
0101 return sum_;
0102 }
0103 void next(iterator_t<CRng> & it)
0104 {
0105 RANGES_EXPECT(it != ranges::end(rng_->base()));
0106 sum_ = invoke(rng_->fun_, static_cast<T &&>(std::move(sum_)), *it);
0107 ++it;
0108 }
0109 void prev() = delete;
0110 };
0111
0112 adaptor<false> begin_adaptor()
0113 {
0114 return {this};
0115 }
0116 meta::if_<use_sentinel_t, adaptor_base, adaptor<false>> end_adaptor()
0117 {
0118 return {this};
0119 }
0120 CPP_member
0121 auto begin_adaptor() const
0122 -> CPP_ret(adaptor<true>)(
0123 requires exclusive_scan_constraints<Rng const, T, Fun const>)
0124 {
0125 return {this};
0126 }
0127 CPP_member
0128 auto end_adaptor() const
0129 -> CPP_ret(meta::if_<use_sentinel_t, adaptor_base, adaptor<true>>)(
0130 requires exclusive_scan_constraints<Rng const, T, Fun const>)
0131 {
0132 return {this};
0133 }
0134
0135 public:
0136 exclusive_scan_view() = default;
0137 constexpr exclusive_scan_view(Rng rng, T init, Fun fun)
0138 : exclusive_scan_view::view_adaptor{std::move(rng)}
0139 , init_(std::move(init))
0140 , fun_(std::move(fun))
0141 {}
0142 CPP_auto_member
0143 auto CPP_fun(size)()(const
0144 requires sized_range<Rng const>)
0145 {
0146 return ranges::size(this->base());
0147 }
0148 CPP_auto_member
0149 auto CPP_fun(size)()(
0150 requires sized_range<Rng>)
0151 {
0152 return ranges::size(this->base());
0153 }
0154 };
0155
0156 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0157 template(typename Rng, typename T, typename Fun)(
0158 requires copy_constructible<T> AND copy_constructible<Fun>)
0159 exclusive_scan_view(Rng &&, T, Fun)
0160 -> exclusive_scan_view<views::all_t<Rng>, T, Fun>;
0161 #endif
0162
0163 namespace views
0164 {
0165 struct exclusive_scan_base_fn
0166 {
0167 template(typename Rng, typename T, typename Fun = plus)(
0168 requires exclusive_scan_constraints<Rng, T, Fun>)
0169 constexpr exclusive_scan_view<all_t<Rng>, T, Fun>
0170 operator()(Rng && rng, T init, Fun fun = Fun{}) const
0171 {
0172 return {all(static_cast<Rng &&>(rng)), std::move(init), std::move(fun)};
0173 }
0174 };
0175
0176 struct exclusive_scan_fn : exclusive_scan_base_fn
0177 {
0178 using exclusive_scan_base_fn::operator();
0179
0180 template<typename T, typename Fun = plus>
0181 constexpr auto operator()(T init, Fun fun = {}) const
0182 {
0183 return make_view_closure(
0184 bind_back(exclusive_scan_base_fn{}, std::move(init), std::move(fun)));
0185 }
0186 };
0187
0188
0189
0190 RANGES_INLINE_VARIABLE(exclusive_scan_fn, exclusive_scan)
0191 }
0192
0193 }
0194
0195 #include <range/v3/detail/epilogue.hpp>
0196
0197 #endif