111 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| /*! \file rx-lift.hpp
 | |
| 
 | |
|     \brief  takes any function that will take a subscriber for this observable and produce a subscriber.
 | |
|             this is intended to allow externally defined operators, that use make_subscriber, to be connected into the expression.
 | |
| 
 | |
|     \tparam ResultType  the type of the emitted results.
 | |
|     \tparam Operator    the type of the operator.
 | |
| 
 | |
|     \return An observable that emitting the items from its source.
 | |
|  */
 | |
| 
 | |
| #if !defined(RXCPP_OPERATORS_RX_LIFT_HPP)
 | |
| #define RXCPP_OPERATORS_RX_LIFT_HPP
 | |
| 
 | |
| #include "../rx-includes.hpp"
 | |
| 
 | |
| namespace rxcpp {
 | |
| 
 | |
| namespace detail {
 | |
| 
 | |
| template<class V, class S, class F>
 | |
| struct is_lift_function_for {
 | |
| 
 | |
|     struct tag_not_valid {};
 | |
|     template<class CS, class CF>
 | |
|     static auto check(int) -> decltype((*(CF*)nullptr)(*(CS*)nullptr));
 | |
|     template<class CS, class CF>
 | |
|     static tag_not_valid check(...);
 | |
| 
 | |
|     using for_type = rxu::decay_t<S>;
 | |
|     using func_type = rxu::decay_t<F>;
 | |
|     using detail_result = decltype(check<for_type, func_type>(0));
 | |
| 
 | |
|     static const bool value = rxu::all_true_type<
 | |
|         is_subscriber<detail_result>,
 | |
|         is_subscriber<for_type>,
 | |
|         std::is_convertible<V, typename rxu::value_type_from<detail_result>::type>>::value;
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| namespace operators {
 | |
| 
 | |
| namespace detail {
 | |
| 
 | |
| template<class ResultType, class SourceOperator, class Operator>
 | |
| struct lift_traits
 | |
| {
 | |
|     typedef rxu::decay_t<ResultType> result_value_type;
 | |
|     typedef rxu::decay_t<SourceOperator> source_operator_type;
 | |
|     typedef rxu::decay_t<Operator> operator_type;
 | |
| 
 | |
|     typedef typename source_operator_type::value_type source_value_type;
 | |
| };
 | |
| 
 | |
| template<class ResultType, class SourceOperator, class Operator>
 | |
| struct lift_operator : public operator_base<typename lift_traits<ResultType, SourceOperator, Operator>::result_value_type>
 | |
| {
 | |
|     typedef lift_traits<ResultType, SourceOperator, Operator> traits;
 | |
|     typedef typename traits::source_operator_type source_operator_type;
 | |
|     typedef typename traits::operator_type operator_type;
 | |
|     source_operator_type source;
 | |
|     operator_type chain;
 | |
| 
 | |
|     lift_operator(source_operator_type s, operator_type op)
 | |
|         : source(std::move(s))
 | |
|         , chain(std::move(op))
 | |
|     {
 | |
|     }
 | |
|     template<class Subscriber>
 | |
|     void on_subscribe(Subscriber o) const {
 | |
|         auto lifted = chain(std::move(o));
 | |
|         trace_activity().lift_enter(source, chain, o, lifted);
 | |
|         source.on_subscribe(std::move(lifted));
 | |
|         trace_activity().lift_return(source, chain);
 | |
|     }
 | |
| };
 | |
| 
 | |
| template<class ResultType, class Operator>
 | |
| class lift_factory
 | |
| {
 | |
|     typedef rxu::decay_t<Operator> operator_type;
 | |
|     operator_type chain;
 | |
| public:
 | |
|     lift_factory(operator_type op) : chain(std::move(op)) {}
 | |
|     template<class Observable>
 | |
|     auto operator()(const Observable& source)
 | |
|         -> decltype(source.template lift<ResultType>(chain)) {
 | |
|         return      source.template lift<ResultType>(chain);
 | |
|         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, ...>)");
 | |
|     }
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| template<class ResultType, class Operator>
 | |
| auto lift(Operator&& op)
 | |
|     ->      detail::lift_factory<ResultType, Operator> {
 | |
|     return  detail::lift_factory<ResultType, Operator>(std::forward<Operator>(op));
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 |