Horizon
Loading...
Searching...
No Matches
exclusive_scan.hpp
Go to the documentation of this file.
1
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
14#ifndef RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
15#define RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
16
17#include <concepts/concepts.hpp>
18
20
26
27#include <range/v3/detail/prologue.hpp>
28
29namespace ranges
30{
31 // clang-format off
34 template(typename Rng, typename T, typename Fun)(
35 concept (exclusive_scan_constraints_)(Rng, T, Fun),
36 invocable<Fun &, T, range_reference_t<Rng>> AND
37 assignable_from<T &, invoke_result_t<Fun &, T, range_reference_t<Rng>>>
38 );
41 template<typename Rng, typename T, typename Fun>
42 CPP_concept exclusive_scan_constraints =
43 viewable_range<Rng> && input_range<Rng> &&
44 copy_constructible<T> &&
45 CPP_concept_ref(ranges::exclusive_scan_constraints_, Rng, T, Fun);
46 // clang-format on
47
50 template<typename Rng, typename T, typename Fun>
52 {
53 private:
54 friend range_access;
56
57 semiregular_box_t<T> init_;
58 semiregular_box_t<Fun> fun_;
60 using use_sentinel_t = meta::bool_<!common_range<Rng> || single_pass{}>;
61
62 template<bool IsConst>
63 struct adaptor : adaptor_base
64 {
65 private:
66 friend struct adaptor<!IsConst>;
67 using exclusive_scan_view_t = meta::const_if_c<IsConst, exclusive_scan_view>;
68 using CRng = meta::const_if_c<IsConst, Rng>;
69 semiregular_box_t<T> sum_;
70 exclusive_scan_view_t * rng_;
71
72 // clang-format off
73 auto CPP_auto_fun(move_or_copy_init)(std::false_type)
74 (
75 return (rng_->init_)
76 )
77
78 // If the base range is single-pass, we can move the init value.
79 auto CPP_auto_fun(move_or_copy_init)(std::true_type)
80 (
81 return std::move(rng_->init_)
82 )
83 // clang-format on
84 public : using single_pass = exclusive_scan_view::single_pass;
85 adaptor() = default;
86 adaptor(exclusive_scan_view_t * rng)
87 : rng_(rng)
88 {}
89 template(bool Other)(
90 requires IsConst AND CPP_NOT(Other)) //
91 adaptor(adaptor<Other> that)
92 : rng_(that.rng_)
93 {}
94 iterator_t<CRng> begin(exclusive_scan_view_t &)
95 {
96 sum_ = move_or_copy_init(single_pass{});
97 return ranges::begin(rng_->base());
98 }
99 T read(iterator_t<CRng> const &) const
100 {
101 return sum_;
102 }
103 void next(iterator_t<CRng> & it)
104 {
105 RANGES_EXPECT(it != ranges::end(rng_->base()));
106 sum_ = invoke(rng_->fun_, static_cast<T &&>(std::move(sum_)), *it);
107 ++it;
108 }
109 void prev() = delete;
110 };
111
112 adaptor<false> begin_adaptor()
113 {
114 return {this};
115 }
117 {
118 return {this};
119 }
120 CPP_member
121 auto begin_adaptor() const //
122 -> CPP_ret(adaptor<true>)(
124 {
125 return {this};
126 }
127 CPP_member
128 auto end_adaptor() const
129 -> CPP_ret(meta::if_<use_sentinel_t, adaptor_base, adaptor<true>>)(
131 {
132 return {this};
133 }
134
135 public:
136 exclusive_scan_view() = default;
137 constexpr exclusive_scan_view(Rng rng, T init, Fun fun)
138 : exclusive_scan_view::view_adaptor{std::move(rng)}
139 , init_(std::move(init))
140 , fun_(std::move(fun))
141 {}
142 CPP_auto_member
143 auto CPP_fun(size)()(const
144 requires sized_range<Rng const>)
145 {
146 return ranges::size(this->base());
147 }
148 CPP_auto_member
149 auto CPP_fun(size)()(
150 requires sized_range<Rng>)
151 {
152 return ranges::size(this->base());
153 }
154 };
155
156#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
157 template(typename Rng, typename T, typename Fun)(
158 requires copy_constructible<T> AND copy_constructible<Fun>)
159 exclusive_scan_view(Rng &&, T, Fun) //
161#endif
162
163 namespace views
164 {
165 struct exclusive_scan_base_fn
166 {
167 template(typename Rng, typename T, typename Fun = plus)(
169 constexpr exclusive_scan_view<all_t<Rng>, T, Fun> //
170 operator()(Rng && rng, T init, Fun fun = Fun{}) const
171 {
172 return {all(static_cast<Rng &&>(rng)), std::move(init), std::move(fun)};
173 }
174 };
175
176 struct exclusive_scan_fn : exclusive_scan_base_fn
177 {
178 using exclusive_scan_base_fn::operator();
179
180 template<typename T, typename Fun = plus>
181 constexpr auto operator()(T init, Fun fun = {}) const
182 {
183 return make_view_closure(
184 bind_back(exclusive_scan_base_fn{}, std::move(init), std::move(fun)));
185 }
186 };
187
190 RANGES_INLINE_VARIABLE(exclusive_scan_fn, exclusive_scan)
191 } // namespace views
193} // namespace ranges
194
195#include <range/v3/detail/epilogue.hpp>
196
197#endif // RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
The exclusive_scan_constraints_ concept.
The exclusive_scan_constraints concept.
The sized_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
defer< bind_back, Fn, Ts... > bind_back
Definition meta.hpp:994
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1247
Definition adaptor.hpp:110
Definition exclusive_scan.hpp:52
Definition arithmetic.hpp:25
Definition adaptor.hpp:475