1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
3 #pragma once
4
5 /*! \file rx-subscribe.hpp
6
7 \brief Subscribe will cause the source observable to emit values to the provided subscriber.
8
9 \tparam ArgN types of the subscriber parameters
10
11 \param an the parameters for making a subscriber
12
13 \return A subscription with which the observer can stop receiving items before the observable has finished sending them.
14
15 The arguments of subscribe are forwarded to rxcpp::make_subscriber function. Some possible alternatives are:
16
17 - Pass an already composed rxcpp::subscriber:
18 \snippet subscribe.cpp subscribe by subscriber
19 \snippet output.txt subscribe by subscriber
20
21 - Pass an rxcpp::observer. This allows subscribing the same subscriber to several observables:
22 \snippet subscribe.cpp subscribe by observer
23 \snippet output.txt subscribe by observer
24
25 - Pass an `on_next` handler:
26 \snippet subscribe.cpp subscribe by on_next
27 \snippet output.txt subscribe by on_next
28
29 - Pass `on_next` and `on_error` handlers:
30 \snippet subscribe.cpp subscribe by on_next and on_error
31 \snippet output.txt subscribe by on_next and on_error
32
33 - Pass `on_next` and `on_completed` handlers:
34 \snippet subscribe.cpp subscribe by on_next and on_completed
35 \snippet output.txt subscribe by on_next and on_completed
36
37 - Pass `on_next`, `on_error`, and `on_completed` handlers:
38 \snippet subscribe.cpp subscribe by on_next, on_error, and on_completed
39 \snippet output.txt subscribe by on_next, on_error, and on_completed
40 .
41
42 All the alternatives above also support passing rxcpp::composite_subscription instance. For example:
43 \snippet subscribe.cpp subscribe by subscription, on_next, and on_completed
44 \snippet output.txt subscribe by subscription, on_next, and on_completed
45
46 If neither subscription nor subscriber are provided, then a new subscription is created and returned as a result:
47 \snippet subscribe.cpp subscribe unsubscribe
48 \snippet output.txt subscribe unsubscribe
49
50 For more details, see rxcpp::make_subscriber function description.
51 */
52
53 #if !defined(RXCPP_OPERATORS_RX_SUBSCRIBE_HPP)
54 #define RXCPP_OPERATORS_RX_SUBSCRIBE_HPP
55
56 #include "../rx-includes.hpp"
57
58 namespace rxcpp {
59
60 namespace operators {
61
62 namespace detail {
63
64 template<class Subscriber>
65 class subscribe_factory;
66
67 template<class T, class I>
68 class subscribe_factory<subscriber<T, I>>
69 {
70 subscriber<T, I> scrbr;
71 public:
subscribe_factory(subscriber<T,I> s)72 subscribe_factory(subscriber<T, I> s)
73 : scrbr(std::move(s))
74 {}
75 template<class Observable>
operator ()(Observable && source)76 auto operator()(Observable&& source)
77 -> decltype(std::forward<Observable>(source).subscribe(std::move(scrbr))) {
78 return std::forward<Observable>(source).subscribe(std::move(scrbr));
79 }
80 };
81
82 }
83
84 /*! @copydoc rx-subscribe.hpp
85 */
86 template<class T, class... ArgN>
subscribe(ArgN &&...an)87 auto subscribe(ArgN&&... an)
88 -> detail::subscribe_factory<decltype (make_subscriber<T>(std::forward<ArgN>(an)...))> {
89 return detail::subscribe_factory<decltype (make_subscriber<T>(std::forward<ArgN>(an)...))>
90 (make_subscriber<T>(std::forward<ArgN>(an)...));
91 }
92
93 namespace detail {
94
95 class dynamic_factory
96 {
97 public:
98 template<class Observable>
operator ()(Observable && source)99 auto operator()(Observable&& source)
100 -> observable<rxu::value_type_t<rxu::decay_t<Observable>>> {
101 return observable<rxu::value_type_t<rxu::decay_t<Observable>>>(std::forward<Observable>(source));
102 }
103 };
104
105 }
106
107 /*! Return a new observable that performs type-forgetting conversion of this observable.
108
109 \return The source observable converted to observable<T>.
110
111 \note This operator could be useful to workaround lambda deduction bug on msvc 2013.
112
113 \sample
114 \snippet as_dynamic.cpp as_dynamic sample
115 \snippet output.txt as_dynamic sample
116 */
as_dynamic()117 inline auto as_dynamic()
118 -> detail::dynamic_factory {
119 return detail::dynamic_factory();
120 }
121
122 namespace detail {
123
124 class blocking_factory
125 {
126 public:
127 template<class Observable>
operator ()(Observable && source)128 auto operator()(Observable&& source)
129 -> decltype(std::forward<Observable>(source).as_blocking()) {
130 return std::forward<Observable>(source).as_blocking();
131 }
132 };
133
134 }
135
136 /*! Return a new observable that contains the blocking methods for this observable.
137
138 \return An observable that contains the blocking methods for this observable.
139
140 \sample
141 \snippet from.cpp threaded from sample
142 \snippet output.txt threaded from sample
143 */
as_blocking()144 inline auto as_blocking()
145 -> detail::blocking_factory {
146 return detail::blocking_factory();
147 }
148
149
150 }
151
152 }
153
154 #endif
155