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
|