summaryrefslogtreecommitdiff
path: root/Rx/v2/src/rxcpp/operators/rx-subscribe.hpp
blob: c3e39179a939cb14dfb02d7dbfa038c3bd38192d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

#pragma once

/*! \file rx-subscribe.hpp

    \brief Subscribe will cause the source observable to emit values to the provided subscriber.

    \tparam ArgN  types of the subscriber parameters

    \param an  the parameters for making a subscriber

    \return  A subscription with which the observer can stop receiving items before the observable has finished sending them.

    The arguments of subscribe are forwarded to rxcpp::make_subscriber function. Some possible alternatives are:

    - Pass an already composed rxcpp::subscriber:
    \snippet subscribe.cpp subscribe by subscriber
    \snippet output.txt subscribe by subscriber

    - Pass an rxcpp::observer. This allows subscribing the same subscriber to several observables:
    \snippet subscribe.cpp subscribe by observer
    \snippet output.txt subscribe by observer

    - Pass an `on_next` handler:
    \snippet subscribe.cpp subscribe by on_next
    \snippet output.txt subscribe by on_next

    - Pass `on_next` and `on_error` handlers:
    \snippet subscribe.cpp subscribe by on_next and on_error
    \snippet output.txt subscribe by on_next and on_error

    - Pass `on_next` and `on_completed` handlers:
    \snippet subscribe.cpp subscribe by on_next and on_completed
    \snippet output.txt subscribe by on_next and on_completed

    - Pass `on_next`, `on_error`, and `on_completed` handlers:
    \snippet subscribe.cpp subscribe by on_next, on_error, and on_completed
    \snippet output.txt subscribe by on_next, on_error, and on_completed
    .

    All the alternatives above also support passing rxcpp::composite_subscription instance. For example:
    \snippet subscribe.cpp subscribe by subscription, on_next, and on_completed
    \snippet output.txt subscribe by subscription, on_next, and on_completed

    If neither subscription nor subscriber are provided, then a new subscription is created and returned as a result:
    \snippet subscribe.cpp subscribe unsubscribe
    \snippet output.txt subscribe unsubscribe

    For more details, see rxcpp::make_subscriber function description.
*/

#if !defined(RXCPP_OPERATORS_RX_SUBSCRIBE_HPP)
#define RXCPP_OPERATORS_RX_SUBSCRIBE_HPP

#include "../rx-includes.hpp"

namespace rxcpp {

namespace operators {

namespace detail {

template<class Subscriber>
class subscribe_factory;

template<class T, class I>
class subscribe_factory<subscriber<T, I>>
{
    subscriber<T, I> scrbr;
public:
    subscribe_factory(subscriber<T, I> s)
        : scrbr(std::move(s))
    {}
    template<class Observable>
    auto operator()(Observable&& source)
        -> decltype(std::forward<Observable>(source).subscribe(std::move(scrbr))) {
        return      std::forward<Observable>(source).subscribe(std::move(scrbr));
    }
};

}

/*! @copydoc rx-subscribe.hpp
*/
template<class T, class... ArgN>
auto subscribe(ArgN&&... an)
    ->      detail::subscribe_factory<decltype  (make_subscriber<T>(std::forward<ArgN>(an)...))> {
    return  detail::subscribe_factory<decltype  (make_subscriber<T>(std::forward<ArgN>(an)...))>
                                                (make_subscriber<T>(std::forward<ArgN>(an)...));
}

namespace detail {

class dynamic_factory
{
public:
    template<class Observable>
    auto operator()(Observable&& source)
        ->      observable<rxu::value_type_t<rxu::decay_t<Observable>>> {
        return  observable<rxu::value_type_t<rxu::decay_t<Observable>>>(std::forward<Observable>(source));
    }
};

}

/*! Return a new observable that performs type-forgetting conversion of this observable.

    \return  The source observable converted to observable<T>.

    \note This operator could be useful to workaround lambda deduction bug on msvc 2013.

    \sample
    \snippet as_dynamic.cpp as_dynamic sample
    \snippet output.txt as_dynamic sample
*/
inline auto as_dynamic()
    ->      detail::dynamic_factory {
    return  detail::dynamic_factory();
}

namespace detail {

class blocking_factory
{
public:
    template<class Observable>
    auto operator()(Observable&& source)
        -> decltype(std::forward<Observable>(source).as_blocking()) {
        return      std::forward<Observable>(source).as_blocking();
    }
};

}

/*! Return a new observable that contains the blocking methods for this observable.

    \return  An observable that contains the blocking methods for this observable.

    \sample
    \snippet from.cpp threaded from sample
    \snippet output.txt threaded from sample
*/
inline auto as_blocking()
    ->      detail::blocking_factory {
    return  detail::blocking_factory();
}


}

}

#endif