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 69 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> 75 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: 89 lift_factory(operator_type op) : chain(std::move(op)) {} 90 template<class Observable> 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> 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