Home | History | Annotate | Download | only in operators
      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:
     72     subscribe_factory(subscriber<T, I> s)
     73         : scrbr(std::move(s))
     74     {}
     75     template<class Observable>
     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>
     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>
     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 */
    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>
    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 */
    144 inline auto as_blocking()
    145     ->      detail::blocking_factory {
    146     return  detail::blocking_factory();
    147 }
    148 
    149 
    150 }
    151 
    152 }
    153 
    154 #endif
    155