ReactivePlusPlus
One more implementation of ReactiveX approach in C++ with care about performance and templates in mind
 
Loading...
Searching...
No Matches
dynamic_observer.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/observers/constraints.hpp> // wrapping constructor
14#include <rpp/observers/state_observer.hpp> // base
15#include <rpp/utils/function_traits.hpp> // extract function args
16#include <rpp/utils/functors.hpp> // default arguments
17#include <rpp/defs.hpp>
18
19
20#include <memory>
21
22namespace rpp::details
23{
24template<constraint::decayed_type T>
26{
27 virtual ~dynamic_observer_state_base() = default;
28
29 virtual void on_next(const T& v) const = 0;
30 virtual void on_next(T&& v) const = 0;
31 virtual void on_error(const std::exception_ptr& err) const = 0;
32 virtual void on_completed() const = 0;
33};
34
35template<constraint::decayed_type T, constraint::observer_of_type<T> TObserver>
37{
38public:
39 template<typename ...Args>
40 requires std::constructible_from<TObserver, Args...>
41 dynamic_observer_state(Args&& ...args)
42 : m_observer{ std::forward<Args>(args)... } {}
43
44 void on_next(const T& v) const override { m_observer.on_next(v); }
45 void on_next(T&& v) const override { m_observer.on_next(std::move(v)); }
46 void on_error(const std::exception_ptr& err) const override { m_observer.on_error(err); }
47 void on_completed() const override { m_observer.on_completed(); }
48
49private:
50 RPP_NO_UNIQUE_ADDRESS TObserver m_observer;
51};
52
53template<constraint::decayed_type T, constraint::observer_of_type<T> TObserver, typename ...Args>
54std::shared_ptr<dynamic_observer_state_base<T>> make_dynamic_observer_state(Args&& ...args) requires std::constructible_from<std::decay_t<TObserver>, Args...>
55{
56 return std::make_shared<dynamic_observer_state<T, std::decay_t<TObserver>>>(std::forward<Args>(args)...);
57}
58
59template<constraint::decayed_type T, typename ...Args>
60std::shared_ptr<dynamic_observer_state_base<T>> make_dynamic_observer_state_from_fns(Args&& ...args)
61{
62 return make_dynamic_observer_state<T, details::state_observer<T, std::decay_t<Args>...>>(std::forward<Args>(args)...);
63}
64
65template<constraint::decayed_type T, constraint::decayed_type ...States>
66class dynamic_state_observer : public state_observer<T, utils::forwarding_on_next_for_pointer,utils::forwarding_on_error_for_pointer, utils::forwarding_on_completed_for_pointer, std::shared_ptr<dynamic_observer_state_base<T>>>
67{
69public:
70 template<typename ...TStates>
71 requires (constraint::decayed_same_as<States, TStates> && ...)
72 dynamic_state_observer(std::invocable<T, States...> auto&& on_next,
73 std::invocable<std::exception_ptr, States...> auto&& on_error,
74 std::invocable<States...> auto&& on_completed,
75 TStates&& ... states)
76 : base{utils::forwarding_on_next_for_pointer{},
77 utils::forwarding_on_error_for_pointer{},
78 utils::forwarding_on_completed_for_pointer{},
79 make_dynamic_observer_state_from_fns<T>(std::forward<decltype(on_next)>(on_next),
80 std::forward<decltype(on_error)>(on_error),
81 std::forward<decltype(on_completed)>(on_completed),
82 std::forward<TStates>(states)...)} {}
83
85 : base{utils::forwarding_on_next_for_pointer{},
86 utils::forwarding_on_error_for_pointer{},
87 utils::forwarding_on_completed_for_pointer{},
88 std::move(state)} {}
89
90
91 template<constraint::observer_of_type<T> TObserver>
92 requires (!std::is_same_v<std::decay_t<TObserver>, dynamic_state_observer<T, States...>>)
93 dynamic_state_observer(TObserver&& obs)
94 : dynamic_state_observer{details::make_dynamic_observer_state<T, std::decay_t<TObserver>>(std::forward<TObserver>(obs))} {}
95};
96} // namespace rpp::details
97
98namespace rpp
99{
107template<constraint::decayed_type T>
109{
110public:
111 template<constraint::on_next_fn<T> OnNext = utils::empty_function_t<T>,
112 constraint::on_error_fn OnError = utils::rethrow_error_t,
113 constraint::on_completed_fn OnCompleted = utils::empty_function_t<>>
114 dynamic_observer(OnNext&& on_next = {}, OnError&& on_error = {}, OnCompleted&& on_completed = {})
115 : details::dynamic_state_observer<T>{std::forward<OnNext>(on_next),
116 std::forward<OnError>(on_error),
117 std::forward<OnCompleted>(on_completed)} {}
118
120 : details::dynamic_state_observer<T>{std::forward<decltype(on_next)>(on_next),
121 utils::rethrow_error_t{},
122 std::forward<decltype(on_completed)>(on_completed)} {}
123
124 template<constraint::observer_of_type<T> TObserver>
125 requires (!std::is_same_v<std::decay_t<TObserver>, dynamic_observer<T>>)
126 dynamic_observer(TObserver&& obs)
127 : details::dynamic_state_observer<T>{std::forward<TObserver>(obs)} {}
128
132 const dynamic_observer<T>& as_dynamic() const { return *this; }
133};
134
135template<constraint::observer TObserver>
136dynamic_observer(TObserver)->dynamic_observer<utils::extract_observer_type_t<TObserver>>;
137
138template<typename OnNext, typename ...Args>
139dynamic_observer(OnNext, Args...)->dynamic_observer<utils::decayed_function_argument_t<OnNext>>;
140} // namespace rpp
Definition: dynamic_observer.hpp:37
Definition: dynamic_observer.hpp:67
Special type of specific_observer which has some state which this observer stores and pass to each ca...
Definition: state_observer.hpp:34
void on_error(const std::exception_ptr &err) const
Observable calls this method to notify observer about some error during generation next data.
Definition: state_observer.hpp:72
Dynamic (type-erased) version of observer (comparing to specific_observer)
Definition: dynamic_observer.hpp:109
const dynamic_observer< T > & as_dynamic() const
Do nothing for rpp::dynamic_observer. Created only for unification of interfaces with rpp::specific_o...
Definition: dynamic_observer.hpp:132
Definition: fwd.hpp:27
Definition: fwd.hpp:25
Definition: dynamic_observer.hpp:26