ReactivePlusPlus
ReactiveX implementation for C++20
Loading...
Searching...
No Matches
start_with.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2023 - 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/operators/fwd.hpp>
14
15#include <rpp/sources/concat.hpp>
16#include <rpp/sources/from.hpp>
17
18namespace rpp::operators::details
19{
20 template<rpp::constraint::observable... TObservables>
22 {
23 rpp::utils::tuple<TObservables...> observables{};
24
25 template<rpp::constraint::observable TObservable>
26 auto operator()(TObservable&& observable) const
27 {
28 static_assert(rpp::constraint::observables_of_same_type<TObservable, TObservables...>, "observables should be of same type");
29 return observables.apply(&apply<TObservable>, std::forward<TObservable>(observable));
30 }
31
32 private:
33 template<rpp::constraint::observable TObservable>
34 static auto apply(TObservable&& observable, const TObservables&... observables)
35 {
36 return rpp::source::concat(observables..., std::forward<TObservable>(observable));
37 }
38 };
39
40 template<rpp::constraint::decayed_type PackedContainer, rpp::schedulers::constraint::scheduler TScheduler>
41 struct start_with_values_t
42 {
43 RPP_NO_UNIQUE_ADDRESS PackedContainer container;
44 RPP_NO_UNIQUE_ADDRESS TScheduler scheduler;
45
46 template<typename... Args>
47 start_with_values_t(const TScheduler& scheduler, Args&&... args)
48 : container{std::forward<Args>(args)...}
49 , scheduler{scheduler}
50 {
51 }
52
53 template<rpp::constraint::observable TObservable>
54 auto operator()(TObservable&& observable) const
55 {
57 return rpp::source::concat(rpp::source::from_iterable(container, scheduler), std::forward<TObservable>(observable));
58 }
59 };
60} // namespace rpp::operators::details
61
62namespace rpp::operators
63{
85 * @see https://reactivex.io/documentation/operators/startwith.html
86 */
87 template<rpp::constraint::observable TObservable, rpp::constraint::observable... TObservables>
88 requires constraint::observables_of_same_type<std::decay_t<TObservable>, std::decay_t<TObservables>...>
89 auto start_with(TObservable&& observable, TObservables&&... observables)
90 {
91 return details::start_with_t<std::decay_t<TObservable>, std::decay_t<TObservables>...>{rpp::utils::tuple{std::forward<TObservable>(observable), std::forward<TObservables>(observables)...}};
92 }
93
112 * @snippet start_with.cpp start_with_values
113 * @snippet start_with.cpp start_with_observable_as_value
114 *
115 * @ingroup combining_operators
116 * @see https://reactivex.io/documentation/operators/startwith.html
117 */
118 template<constraint::memory_model MemoryModel /* = memory_model::use_stack */, typename T, typename... Ts>
120 auto start_with_values(T&& v, Ts&&... vals)
121 {
122 return start_with_values<MemoryModel>(rpp::schedulers::defaults::iteration_scheduler{}, std::forward<T>(v), std::forward<Ts>(vals)...);
123 }
124
137 * @param vals list of values which should be emitted before current observable
138 *
139 * @note `#include <rpp/operators/start_with.hpp>`
140 *
141 * @par Example
142 * @snippet start_with.cpp start_with_values
143 *
144 * @ingroup combining_operators
145 * @see https://reactivex.io/documentation/operators/startwith.html
146 */
147 template<constraint::memory_model MemoryModel /* = memory_model::use_stack */, rpp::schedulers::constraint::scheduler TScheduler, typename T, typename... Ts>
149 auto start_with_values(const TScheduler& scheduler, T&& v, Ts&&... vals)
150 {
151 using inner_container = std::array<std::decay_t<T>, sizeof...(Ts) + 1>;
152 using container = std::conditional_t<std::same_as<MemoryModel, rpp::memory_model::use_stack>, inner_container, rpp::details::shared_container<inner_container>>;
153
154 return details::start_with_values_t<container, TScheduler>{scheduler, std::forward<T>(v), std::forward<Ts>(vals)...};
155 }
156
157 template<constraint::memory_model MemoryModel /* = memory_model::use_stack*/, typename T, typename... Ts>
159 auto start_with(T&& v, Ts&&... vals)
160 {
161 return start_with_values<MemoryModel>(std::forward<T>(v), std::forward<Ts>(vals)...);
162 }
163
164 template<constraint::memory_model MemoryModel /* = memory_model::use_stack*/, rpp::schedulers::constraint::scheduler TScheduler, typename T, typename... Ts>
166 auto start_with(const TScheduler& scheduler, T&& v, Ts&&... vals)
167 {
168 return start_with_values<MemoryModel>(scheduler, std::forward<T>(v), std::forward<Ts>(vals)...);
169 }
170} // namespace rpp::operators
Definition from.hpp:30
Base class for any observable used in RPP. It handles core callbacks of observable.
Definition observable.hpp:38
Definition tuple.hpp:105
Definition constraints.hpp:19
Definition memory_model.hpp:31
Definition fwd.hpp:80
auto start_with_values(T &&v, Ts &&... vals)
Combines submissions from current observable with values into one but without overlapping and startin...
Definition start_with.hpp:112
auto start_with(TObservable &&observable, TObservables &&... observables)
Combines submissions from current observable with other observables into one but without overlapping ...
Definition start_with.hpp:85
auto concat(TObservable &&obs, TObservables &&... others)
Make observable which would merge emissions from underlying observables but without overlapping (curr...
Definition concat.hpp:168
auto from_iterable(Iterable &&iterable, const TScheduler &scheduler)
Creates observable that emits a items from provided iterable.
Definition from.hpp:175
Definition start_with.hpp:22