ReactivePlusPlus
One more implementation of ReactiveX approach in C++ with care about performance and templates in mind
 
Loading...
Searching...
No Matches
reduce.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2022 - present.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// https://www.boost.org/LICENSE_1_0.txt)
7//
8// Project home: https://github.com/victimsnino/ReactivePlusPlus
9//
10
11#pragma once
12
13#include <rpp/observables/details/member_overload.hpp>
14
15namespace rpp::details
16{
17struct reduce_tag;
18}
19
20namespace rpp::details
21{
22// accepts Result and Type and returns Result
23template<typename Fn, typename Result, typename Type>
24concept reduce_accumulator = std::is_invocable_r_v<std::decay_t<Result>, Fn, std::decay_t<Result>, std::decay_t<Type>>;
25
26template<typename T>
27concept is_can_be_summed = requires(T t)
28{
29 { t + t } -> std::convertible_to<T>;
30};
31
32template<typename T, typename CastBeforeDrop>
33concept is_can_be_averaged = is_can_be_summed<T> && requires(CastBeforeDrop nt)
34{
35 { nt / size_t{} };
36};
37
38template<constraint::decayed_type Type, constraint::decayed_type Seed, reduce_accumulator<Seed, Type> AccumulatorFn, std::invocable<Seed&&> ResultSelectorFn>
39struct reduce_impl;
40
41template<constraint::decayed_type CastBeforeDivide, constraint::observable TObs>
42auto average_impl(TObs&& observable);
43
44template<constraint::observable TObs>
45auto sum_impl(TObs&& observable);
46
47template<constraint::observable TObs>
48auto count_impl(TObs&& observable);
49
50template<constraint::observable TObs, typename Comparator>
51auto min_impl(TObs&& observable, Comparator&& comparator);
52
53template<constraint::observable TObs, typename Comparator>
54auto max_impl(TObs&& observable, Comparator&& comparator);
55
56template<constraint::decayed_type Type, typename SpecificObservable>
57struct member_overload<Type, SpecificObservable, reduce_tag>
58{
93 template<typename Seed, reduce_accumulator<Seed, Type> AccumulatorFn, std::invocable<Seed&&> ResultSelectorFn = std::identity>
94 auto reduce(Seed&& initial_seed, AccumulatorFn&& accumulator, ResultSelectorFn&& result_selector = {}) const & requires is_header_included<reduce_tag, Seed, AccumulatorFn, ResultSelectorFn>
95 {
96 return static_cast<const SpecificObservable*>(this)->template lift<utils::decayed_invoke_result_t<ResultSelectorFn, std::decay_t<Seed>>>(
97 reduce_impl<Type, std::decay_t<Seed>, std::decay_t<AccumulatorFn>, std::decay_t<ResultSelectorFn>>{
98 std::forward<Seed>(initial_seed),
99 std::forward<AccumulatorFn>(accumulator),
100 std::forward<ResultSelectorFn>(result_selector)});
101 }
102
103 template<typename Seed, reduce_accumulator<Seed, Type> AccumulatorFn, std::invocable<Seed&&> ResultSelectorFn = std::identity>
104 auto reduce(Seed&& initial_seed, AccumulatorFn&& accumulator, ResultSelectorFn&& result_selector = {}) && requires is_header_included<reduce_tag, Seed, AccumulatorFn, ResultSelectorFn>
105 {
106 return std::move(*static_cast<SpecificObservable*>(this)).template lift<utils::decayed_invoke_result_t<ResultSelectorFn, std::decay_t<Seed>>>(
107 reduce_impl<Type, std::decay_t<Seed>, std::decay_t<AccumulatorFn>, std::decay_t<ResultSelectorFn>>{
108 std::forward<Seed>(initial_seed),
109 std::forward<AccumulatorFn>(accumulator),
110 std::forward<ResultSelectorFn>(result_selector)});
111 }
112
134 template<typename CastBeforeDivide = Type, typename ...Args>
135 auto average() const & requires (is_header_included<reduce_tag, CastBeforeDivide, Args...> && is_can_be_averaged<Type, CastBeforeDivide>)
136 {
137 return average_impl<CastBeforeDivide>(*static_cast<const SpecificObservable*>(this));
138 }
139
140 template<typename CastBeforeDivide = Type, typename ...Args>
141 auto average() && requires (is_header_included<reduce_tag, CastBeforeDivide, Args...> && is_can_be_averaged<Type, CastBeforeDivide>)
142 {
143 return average_impl<CastBeforeDivide>(std::move(*static_cast<SpecificObservable*>(this)));
144 }
145
146
167 template<typename ...Args>
168 auto sum() const & requires (is_header_included<reduce_tag, Args...> && is_can_be_summed<Type>)
169 {
170 return sum_impl(*static_cast<const SpecificObservable*>(this));
171 }
172
173 template<typename ...Args>
174 auto sum() && requires (is_header_included<reduce_tag, Args...> && is_can_be_summed<Type>)
175 {
176 return sum_impl(std::move(*static_cast<SpecificObservable*>(this)));
177 }
178
197 template<typename ...Args>
198 auto count() const & requires is_header_included<reduce_tag, Args...>
199 {
200 return count_impl(*static_cast<const SpecificObservable*>(this));
201 }
202
203 template<typename ...Args>
204 auto count() && requires is_header_included<reduce_tag, Args...>
205 {
206 return count_impl(std::move(*static_cast<SpecificObservable*>(this)));
207 }
208
230 template<std::strict_weak_order<Type, Type> Comparator = std::less<Type>, typename ...Args>
231 auto min(Comparator&& comparator = {}) const & requires is_header_included<reduce_tag, Comparator, Args...>
232 {
233 return min_impl(*static_cast<const SpecificObservable*>(this), std::forward<Comparator>(comparator));
234 }
235
236 template<std::strict_weak_order<Type, Type> Comparator = std::less<Type>, typename ...Args>
237 auto min(Comparator&& comparator = {}) && requires is_header_included<reduce_tag, Comparator, Args...>
238 {
239 return min_impl(std::move(*static_cast<SpecificObservable*>(this)), std::forward<Comparator>(comparator));
241
263 template<std::strict_weak_order<Type, Type> Comparator = std::less<Type>, typename ...Args>
264 auto max(Comparator&& comparator = {}) const & requires is_header_included<reduce_tag, Comparator, Args...>
265 {
266 return max_impl(*static_cast<const SpecificObservable*>(this), std::forward<Comparator>(comparator));
267 }
268
269 template<std::strict_weak_order<Type, Type> Comparator = std::less<Type>, typename ...Args>
270 auto max(Comparator&& comparator = {}) && requires is_header_included<reduce_tag, Comparator, Args...>
271 {
272 return max_impl(std::move(*static_cast<SpecificObservable*>(this)), std::forward<Comparator>(comparator));
273 }
274};
275} // namespace rpp::details
Definition: reduce.hpp:33
Definition: reduce.hpp:27
Definition: reduce.hpp:24
Definition: member_overload.hpp:19
Definition: reduce.hpp:67