Horizon
exclusive_scan.hpp
Go to the documentation of this file.
1 // 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 
19 #include <range/v3/range_fwd.hpp>
20 
25 #include <range/v3/view/view.hpp>
26 
27 #include <range/v3/detail/prologue.hpp>
28 
29 namespace 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>
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;
55  CPP_assert(exclusive_scan_constraints<Rng, T, Fun>);
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>)(
123  requires exclusive_scan_constraints<Rng const, T, Fun const>)
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>>)(
130  requires exclusive_scan_constraints<Rng const, T, Fun const>)
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  {
166  {
167  template(typename Rng, typename T, typename Fun = plus)(
168  requires exclusive_scan_constraints<Rng, T, Fun>)
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 
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 
191  } // namespace views
193 } // namespace ranges
194 
195 #include <range/v3/detail/epilogue.hpp>
196 
197 #endif // RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
CPP_concept exclusive_scan_constraints
\concept exclusive_scan_constraints
Definition: exclusive_scan.hpp:42
CPP_concept invocable
\concept invocable
Definition: concepts.hpp:48
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
_t< detail::_if_< list< Args... > >> if_
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1247
std::integral_constant< decltype(T::type::value+U::type::value), T::type::value+U::type::value > plus
An integral constant wrapper around the result of adding the two wrapped integers T::type::value and ...
Definition: meta.hpp:197
Definition: adaptor.hpp:110
Definition: exclusive_scan.hpp:52
Definition: adaptor.hpp:475
Definition: exclusive_scan.hpp:166
Definition: exclusive_scan.hpp:177