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