• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-lift.hpp
6 
7     \brief  takes any function that will take a subscriber for this observable and produce a subscriber.
8             this is intended to allow externally defined operators, that use make_subscriber, to be connected into the expression.
9 
10     \tparam ResultType  the type of the emitted results.
11     \tparam Operator    the type of the operator.
12 
13     \return An observable that emitting the items from its source.
14  */
15 
16 #if !defined(RXCPP_OPERATORS_RX_LIFT_HPP)
17 #define RXCPP_OPERATORS_RX_LIFT_HPP
18 
19 #include "../rx-includes.hpp"
20 
21 namespace rxcpp {
22 
23 namespace detail {
24 
25 template<class V, class S, class F>
26 struct is_lift_function_for {
27 
28     struct tag_not_valid {};
29     template<class CS, class CF>
30     static auto check(int) -> decltype((*(CF*)nullptr)(*(CS*)nullptr));
31     template<class CS, class CF>
32     static tag_not_valid check(...);
33 
34     using for_type = rxu::decay_t<S>;
35     using func_type = rxu::decay_t<F>;
36     using detail_result = decltype(check<for_type, func_type>(0));
37 
38     static const bool value = rxu::all_true_type<
39         is_subscriber<detail_result>,
40         is_subscriber<for_type>,
41         std::is_convertible<V, typename rxu::value_type_from<detail_result>::type>>::value;
42 };
43 
44 }
45 
46 namespace operators {
47 
48 namespace detail {
49 
50 template<class ResultType, class SourceOperator, class Operator>
51 struct lift_traits
52 {
53     typedef rxu::decay_t<ResultType> result_value_type;
54     typedef rxu::decay_t<SourceOperator> source_operator_type;
55     typedef rxu::decay_t<Operator> operator_type;
56 
57     typedef typename source_operator_type::value_type source_value_type;
58 };
59 
60 template<class ResultType, class SourceOperator, class Operator>
61 struct lift_operator : public operator_base<typename lift_traits<ResultType, SourceOperator, Operator>::result_value_type>
62 {
63     typedef lift_traits<ResultType, SourceOperator, Operator> traits;
64     typedef typename traits::source_operator_type source_operator_type;
65     typedef typename traits::operator_type operator_type;
66     source_operator_type source;
67     operator_type chain;
68 
lift_operatorrxcpp::operators::detail::lift_operator69     lift_operator(source_operator_type s, operator_type op)
70         : source(std::move(s))
71         , chain(std::move(op))
72     {
73     }
74     template<class Subscriber>
on_subscriberxcpp::operators::detail::lift_operator75     void on_subscribe(Subscriber o) const {
76         auto lifted = chain(std::move(o));
77         trace_activity().lift_enter(source, chain, o, lifted);
78         source.on_subscribe(std::move(lifted));
79         trace_activity().lift_return(source, chain);
80     }
81 };
82 
83 template<class ResultType, class Operator>
84 class lift_factory
85 {
86     typedef rxu::decay_t<Operator> operator_type;
87     operator_type chain;
88 public:
lift_factory(operator_type op)89     lift_factory(operator_type op) : chain(std::move(op)) {}
90     template<class Observable>
operator ()(const Observable & source)91     auto operator()(const Observable& source)
92         -> decltype(source.template lift<ResultType>(chain)) {
93         return      source.template lift<ResultType>(chain);
94         static_assert(rxcpp::detail::is_lift_function_for<rxu::value_type_t<Observable>, subscriber<ResultType>, Operator>::value, "Function passed for lift() must have the signature subscriber<...>(subscriber<T, ...>)");
95     }
96 };
97 
98 }
99 
100 template<class ResultType, class Operator>
lift(Operator && op)101 auto lift(Operator&& op)
102     ->      detail::lift_factory<ResultType, Operator> {
103     return  detail::lift_factory<ResultType, Operator>(std::forward<Operator>(op));
104 }
105 
106 }
107 
108 }
109 
110 #endif
111