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 14 #ifndef RANGES_V3_VIEW_PARTIAL_SUM_HPP 15 #define RANGES_V3_VIEW_PARTIAL_SUM_HPP 16 17 #include <iterator> 18 #include <type_traits> 19 #include <utility> 20 21 #include <meta/meta.hpp> 22 23 #include <range/v3/range_fwd.hpp> 24 25 #include <range/v3/functional/arithmetic.hpp> 26 #include <range/v3/functional/bind_back.hpp> 27 #include <range/v3/functional/invoke.hpp> 28 #include <range/v3/range/access.hpp> 29 #include <range/v3/range/primitives.hpp> 30 #include <range/v3/range/traits.hpp> 31 #include <range/v3/utility/addressof.hpp> 32 #include <range/v3/utility/semiregular_box.hpp> 33 #include <range/v3/utility/static_const.hpp> 34 #include <range/v3/view/all.hpp> 35 #include <range/v3/view/facade.hpp> 36 #include <range/v3/view/view.hpp> 37 38 #include <range/v3/detail/prologue.hpp> 39 40 namespace ranges 41 { 42 /// \cond 43 namespace detail 44 { 45 // clang-format off 46 template(typename Rng, typename Fun)( 47 concept (partial_sum_view_constraints_)(Rng, Fun), 48 copy_constructible<range_value_t<Rng>> AND 49 constructible_from<range_value_t<Rng>, range_reference_t<Rng>> AND 50 assignable_from<range_value_t<Rng> &, range_reference_t<Rng>> AND 51 indirectly_binary_invocable_<Fun &, iterator_t<Rng>, iterator_t<Rng>> AND 52 assignable_from< 53 range_value_t<Rng> &, 54 indirect_result_t<Fun &, iterator_t<Rng>, iterator_t<Rng>>> 55 ); 56 template<typename Rng, typename Fun> 57 CPP_concept partial_sum_view_constraints = 58 input_range<Rng> && 59 copy_constructible<Fun> && 60 CPP_concept_ref(detail::partial_sum_view_constraints_, Rng, Fun); 61 // clang-format on 62 } // namespace detail 63 /// \endcond 64 65 /// \addtogroup group-views 66 /// @{ 67 template<typename Rng, typename Fun> 68 struct partial_sum_view 69 : view_facade<partial_sum_view<Rng, Fun>, range_cardinality<Rng>::value> 70 { 71 private: 72 friend range_access; 73 CPP_assert(view_<Rng>); 74 CPP_assert(detail::partial_sum_view_constraints<Rng, Fun>); 75 76 RANGES_NO_UNIQUE_ADDRESS Rng base_{}; 77 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_; 78 79 template<bool IsConst> 80 struct cursor 81 { 82 private: 83 friend cursor<true>; 84 85 using Parent = meta::const_if_c<IsConst, partial_sum_view>; 86 using Base = meta::const_if_c<IsConst, Rng>; 87 88 Parent * parent_ = nullptr; 89 RANGES_NO_UNIQUE_ADDRESS iterator_t<Base> current_{}; 90 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<range_value_t<Rng>> sum_; 91 92 public: 93 using single_pass = meta::bool_<single_pass_iterator_<iterator_t<Base>>>; 94 95 cursor() = default; cursorranges::partial_sum_view::cursor96 constexpr explicit cursor(Parent * rng) 97 : parent_{rng} 98 , current_(ranges::begin(rng->base_)) 99 { 100 if(current_ != ranges::end(rng->base_)) 101 sum_ = *current_; 102 } 103 template(bool Other)( 104 /// \pre 105 requires IsConst AND CPP_NOT(Other) AND 106 convertible_to<iterator_t<Rng> const &, 107 iterator_t<Base>>) cursorranges::partial_sum_view::cursor108 constexpr cursor(cursor<Other> const & that) 109 : parent_{that.parent_} 110 , current_(that.current_) 111 , sum_(that.sum_) 112 {} 113 constexpr range_value_t<Rng> read() const 114 { 115 RANGES_EXPECT(current_ != ranges::end(parent_->base_)); 116 return sum_; 117 } nextranges::partial_sum_view::cursor118 constexpr void next() 119 { 120 auto last = ranges::end(parent_->base_); 121 RANGES_EXPECT(current_ != last); 122 if(++current_ != last) 123 { 124 auto & sum = static_cast<range_value_t<Rng> &>(sum_); 125 using F = meta::const_if_c<IsConst, Fun>; 126 auto & f = static_cast<F &>(parent_->fun_); 127 sum = invoke(f, sum, *current_); 128 } 129 } equalranges::partial_sum_view::cursor130 constexpr bool equal(default_sentinel_t) const 131 { 132 return current_ == ranges::end(parent_->base_); 133 } 134 CPP_auto_member CPP_funranges::partial_sum_view::cursor135 constexpr bool CPP_fun(equal)(cursor const & that)(const // 136 requires equality_comparable<iterator_t<Base>>) 137 { 138 RANGES_EXPECT(parent_ == that.parent_); 139 return current_ == that.current_; 140 } 141 }; 142 begin_cursorranges::partial_sum_view143 constexpr cursor<false> begin_cursor() 144 { 145 return cursor<false>{this}; 146 } 147 template(typename CRng = Rng const)( 148 /// \pre 149 requires detail::partial_sum_view_constraints<CRng, Fun const>) begin_cursorranges::partial_sum_view150 constexpr cursor<true> begin_cursor() const 151 { 152 return cursor<true>{this}; 153 } 154 155 public: 156 partial_sum_view() = default; partial_sum_viewranges::partial_sum_view157 constexpr partial_sum_view(Rng rng, Fun fun) noexcept( 158 std::is_nothrow_move_constructible<Rng>::value && 159 std::is_nothrow_move_constructible<Fun>::value) 160 : base_(std::move(rng)) 161 , fun_(std::move(fun)) 162 {} 163 CPP_auto_member CPP_funranges::partial_sum_view164 constexpr auto CPP_fun(size)()( 165 /// \pre 166 requires sized_range<Rng>) 167 { 168 return ranges::size(base_); 169 } 170 CPP_auto_member CPP_funranges::partial_sum_view171 constexpr auto CPP_fun(size)()(const // 172 requires sized_range<Rng const>) 173 { 174 return ranges::size(base_); 175 } 176 }; 177 178 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 179 template(typename Rng, typename Fun)( 180 /// \pre 181 requires copy_constructible<Fun>) 182 partial_sum_view(Rng &&, Fun) 183 -> partial_sum_view<views::all_t<Rng>, Fun>; 184 #endif 185 186 namespace views 187 { 188 struct partial_sum_base_fn 189 { 190 template(typename Rng, typename Fun = plus)( 191 /// \pre 192 requires detail::partial_sum_view_constraints<all_t<Rng>, Fun>) 193 constexpr partial_sum_view<all_t<Rng>, Fun> // operator ()ranges::views::partial_sum_base_fn194 operator()(Rng && rng, Fun fun = {}) const 195 { 196 return {all(static_cast<Rng &&>(rng)), std::move(fun)}; 197 } 198 }; 199 200 struct partial_sum_fn : partial_sum_base_fn 201 { 202 using partial_sum_base_fn::operator(); 203 204 template(typename Fun)( 205 /// \pre 206 requires (!range<Fun>)) 207 constexpr auto operator()(Fun && fun) const 208 { 209 return make_view_closure( 210 bind_back(partial_sum_base_fn{}, static_cast<Fun &&>(fun))); 211 } 212 template<typename Fun = plus> 213 RANGES_DEPRECATED( 214 "Use \"ranges::views::partial_sum\" instead of " 215 "\"ranges::views::partial_sum()\".") 216 constexpr auto 217 operator()() const 218 { 219 return make_view_closure(bind_back(partial_sum_base_fn{}, Fun{})); 220 } 221 }; 222 223 /// \relates partial_sum_fn 224 /// \ingroup group-views 225 RANGES_INLINE_VARIABLE(view_closure<partial_sum_fn>, partial_sum) 226 } // namespace views 227 /// @} 228 } // namespace ranges 229 230 #include <range/v3/detail/epilogue.hpp> 231 232 #include <range/v3/detail/satisfy_boost_range.hpp> 233 RANGES_SATISFY_BOOST_RANGE(::ranges::partial_sum_view) 234 235 #endif 236