diff options
author | Grigoriy Chudnov <g.chudnov@gmail.com> | 2017-01-11 22:10:36 +0300 |
---|---|---|
committer | Kirk Shoop <kirk.shoop@microsoft.com> | 2017-01-11 11:10:36 -0800 |
commit | 5af562282f25a500d17da9c283541d7ab33d1785 (patch) | |
tree | 0974d1ef1107d658a1eefef809e2676d173c9d42 /Rx/v2/src | |
parent | 13d406282a025f799f7674513dc2222f68d15dd4 (diff) | |
download | platform_external_Reactive-Extensions_RxCpp-5af562282f25a500d17da9c283541d7ab33d1785.tar.gz platform_external_Reactive-Extensions_RxCpp-5af562282f25a500d17da9c283541d7ab33d1785.tar.bz2 platform_external_Reactive-Extensions_RxCpp-5af562282f25a500d17da9c283541d7ab33d1785.zip |
decouple scan from observable (#323)
* decouple scan from observable
* fix redefinition bug
Diffstat (limited to 'Rx/v2/src')
-rw-r--r-- | Rx/v2/src/rxcpp/operators/rx-reduce.hpp | 17 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/operators/rx-scan.hpp | 89 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-includes.hpp | 1 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-observable.hpp | 23 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-operators.hpp | 8 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-predef.hpp | 17 |
6 files changed, 87 insertions, 68 deletions
diff --git a/Rx/v2/src/rxcpp/operators/rx-reduce.hpp b/Rx/v2/src/rxcpp/operators/rx-reduce.hpp index eb86326..34cf210 100644 --- a/Rx/v2/src/rxcpp/operators/rx-reduce.hpp +++ b/Rx/v2/src/rxcpp/operators/rx-reduce.hpp @@ -64,23 +64,6 @@ struct reduce_invalid : public rxo::operator_base<reduce_invalid_arguments<AN... template<class... AN> using reduce_invalid_t = typename reduce_invalid<AN...>::type; -template<class T, class Seed, class Accumulator> -struct is_accumulate_function_for { - - typedef rxu::decay_t<Accumulator> accumulator_type; - typedef rxu::decay_t<Seed> seed_type; - typedef T source_value_type; - - struct tag_not_valid {}; - template<class CS, class CV, class CRS> - static auto check(int) -> decltype((*(CRS*)nullptr)(*(CS*)nullptr, *(CV*)nullptr)); - template<class CS, class CV, class CRS> - static tag_not_valid check(...); - - typedef decltype(check<seed_type, source_value_type, accumulator_type>(0)) type; - static const bool value = std::is_same<type, seed_type>::value; -}; - template<class Seed, class ResultSelector> struct is_result_function_for { diff --git a/Rx/v2/src/rxcpp/operators/rx-scan.hpp b/Rx/v2/src/rxcpp/operators/rx-scan.hpp index 24d2886..b03be30 100644 --- a/Rx/v2/src/rxcpp/operators/rx-scan.hpp +++ b/Rx/v2/src/rxcpp/operators/rx-scan.hpp @@ -2,6 +2,23 @@ #pragma once +/*! \file rx-scan.hpp + + \brief For each item from this observable use Accumulator to combine items into a value that will be emitted from the new observable that is returned. + + \tparam Seed the type of the initial value for the accumulator. + \tparam Accumulator the type of the data accumulating function. + + \param seed the initial value for the accumulator. + \param a an accumulator function to be invoked on each item emitted by the source observable, whose result will be emitted and used in the next accumulator call. + + \return An observable that emits the results of each call to the accumulator function. + + \sample + \snippet scan.cpp scan sample + \snippet output.txt scan sample +*/ + #if !defined(RXCPP_OPERATORS_RX_SCAN_HPP) #define RXCPP_OPERATORS_RX_SCAN_HPP @@ -13,6 +30,16 @@ namespace operators { namespace detail { +template<class... AN> +struct scan_invalid_arguments {}; + +template<class... AN> +struct scan_invalid : public rxo::operator_base<scan_invalid_arguments<AN...>> { + using type = observable<scan_invalid_arguments<AN...>, scan_invalid<AN...>>; +}; +template<class... AN> +using scan_invalid_t = typename scan_invalid<AN...>::type; + template<class T, class Observable, class Accumulator, class Seed> struct scan : public operator_base<rxu::decay_t<Seed>> { @@ -34,16 +61,11 @@ struct scan : public operator_base<rxu::decay_t<Seed>> }; scan_initial_type initial; - template<class CT, class CS, class CP> - static auto check(int) -> decltype((*(CP*)nullptr)(*(CS*)nullptr, *(CT*)nullptr)); - template<class CT, class CS, class CP> - static void check(...); - scan(source_type o, accumulator_type a, seed_type s) : initial(std::move(o), a, s) { - static_assert(std::is_convertible<decltype(check<T, seed_type, accumulator_type>(0)), seed_type>::value, "scan Accumulator must be a function with the signature Seed(Seed, T)"); } + template<class Subscriber> void on_subscribe(Subscriber o) const { struct scan_state_type @@ -79,38 +101,41 @@ struct scan : public operator_base<rxu::decay_t<Seed>> } }; -template<class Accumulator, class Seed> -class scan_factory -{ - typedef rxu::decay_t<Accumulator> accumulator_type; - typedef rxu::decay_t<Seed> seed_type; - - accumulator_type accumulator; - seed_type seed; -public: - scan_factory(accumulator_type a, Seed s) - : accumulator(std::move(a)) - , seed(s) - { - } - template<class Observable> - auto operator()(Observable&& source) - -> observable<rxu::decay_t<Seed>, scan<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, Accumulator, Seed>> { - return observable<rxu::decay_t<Seed>, scan<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, Accumulator, Seed>>( - scan<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, Accumulator, Seed>(std::forward<Observable>(source), accumulator, seed)); - } -}; - } -template<class Seed, class Accumulator> -auto scan(Seed s, Accumulator&& a) - -> detail::scan_factory<Accumulator, Seed> { - return detail::scan_factory<Accumulator, Seed>(std::forward<Accumulator>(a), s); +/*! @copydoc rx-scan.hpp +*/ +template<class... AN> +auto scan(AN&&... an) + -> operator_factory<scan_tag, AN...> { + return operator_factory<scan_tag, AN...>(std::make_tuple(std::forward<AN>(an)...)); } } +template<> +struct member_overload<scan_tag> +{ + template<class Observable, class Seed, class Accumulator, + class Enabled = rxu::enable_if_all_true_type_t< + is_observable<Observable>, + is_accumulate_function_for<rxu::value_type_t<Observable>, rxu::decay_t<Seed>, rxu::decay_t<Accumulator>>>, + class SourceValue = rxu::value_type_t<Observable>, + class Scan = rxo::detail::scan<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<Accumulator>, rxu::decay_t<Seed>>, + class Value = rxu::value_type_t<Scan>, + class Result = observable<Value, Scan>> + static Result member(Observable&& o, Seed s, Accumulator&& a) { + return Result(Scan(std::forward<Observable>(o), std::forward<Accumulator>(a), s)); + } + + template<class... AN> + static operators::detail::scan_invalid_t<AN...> member(AN...) { + std::terminate(); + return {}; + static_assert(sizeof...(AN) == 10000, "scan takes (Seed, Accumulator); Accumulator must be a function with the signature Seed(Seed, T)"); + } +}; + } #endif diff --git a/Rx/v2/src/rxcpp/rx-includes.hpp b/Rx/v2/src/rxcpp/rx-includes.hpp index 3af27f4..84561e6 100644 --- a/Rx/v2/src/rxcpp/rx-includes.hpp +++ b/Rx/v2/src/rxcpp/rx-includes.hpp @@ -206,6 +206,7 @@ #include "operators/rx-repeat.hpp" #include "operators/rx-retry.hpp" #include "operators/rx-sample_time.hpp" +#include "operators/rx-scan.hpp" #include "operators/rx-sequence_equal.hpp" #include "operators/rx-skip.hpp" #include "operators/rx-skip_last.hpp" diff --git a/Rx/v2/src/rxcpp/rx-observable.hpp b/Rx/v2/src/rxcpp/rx-observable.hpp index 81a626a..52acb15 100644 --- a/Rx/v2/src/rxcpp/rx-observable.hpp +++ b/Rx/v2/src/rxcpp/rx-observable.hpp @@ -1921,28 +1921,15 @@ public: static_assert(sizeof...(AN) == 0, "min() was passed too many arguments."); } - /*! For each item from this observable use Accumulator to combine items into a value that will be emitted from the new observable that is returned. - - \tparam Seed the type of the initial value for the accumulator - \tparam Accumulator the type of the data accumulating function - - \param seed the initial value for the accumulator - \param a an accumulator function to be invoked on each item emitted by the source observable, whose result will be emitted and used in the next accumulator call - - \return An observable that emits the results of each call to the accumulator function. - - \sample - \snippet scan.cpp scan sample - \snippet output.txt scan sample + /*! @copydoc rx-scan.hpp */ - template<class Seed, class Accumulator> - auto scan(Seed seed, Accumulator&& a) const + template<class... AN> + auto scan(AN... an) const /// \cond SHOW_SERVICE_MEMBERS - -> observable<Seed, rxo::detail::scan<T, this_type, Accumulator, Seed>> + -> decltype(observable_member(scan_tag{}, *(this_type*)nullptr, std::forward<AN>(an)...)) /// \endcond { - return observable<Seed, rxo::detail::scan<T, this_type, Accumulator, Seed>>( - rxo::detail::scan<T, this_type, Accumulator, Seed>(*this, std::forward<Accumulator>(a), seed)); + return observable_member(scan_tag{}, *this, std::forward<AN>(an)...); } /*! @copydoc rx-sample_time.hpp diff --git a/Rx/v2/src/rxcpp/rx-operators.hpp b/Rx/v2/src/rxcpp/rx-operators.hpp index e1f333f..bee493c 100644 --- a/Rx/v2/src/rxcpp/rx-operators.hpp +++ b/Rx/v2/src/rxcpp/rx-operators.hpp @@ -105,7 +105,6 @@ public: #include "operators/rx-publish.hpp" #include "operators/rx-ref_count.hpp" #include "operators/rx-replay.hpp" -#include "operators/rx-scan.hpp" #include "operators/rx-start_with.hpp" #include "operators/rx-subscribe.hpp" #include "operators/rx-subscribe_on.hpp" @@ -301,6 +300,13 @@ struct sample_with_time_tag { }; }; +struct scan_tag { + template<class Included> + struct include_header{ + static_assert(Included::value, "missing include: please #include <rxcpp/operators/rx-scan.hpp>"); + }; +}; + struct sequence_equal_tag { template<class Included> struct include_header{ diff --git a/Rx/v2/src/rxcpp/rx-predef.hpp b/Rx/v2/src/rxcpp/rx-predef.hpp index ee9372b..f833620 100644 --- a/Rx/v2/src/rxcpp/rx-predef.hpp +++ b/Rx/v2/src/rxcpp/rx-predef.hpp @@ -306,6 +306,23 @@ struct identity_for } }; +template<class T, class Seed, class Accumulator> +struct is_accumulate_function_for { + + typedef rxu::decay_t<Accumulator> accumulator_type; + typedef rxu::decay_t<Seed> seed_type; + typedef T source_value_type; + + struct tag_not_valid {}; + template<class CS, class CV, class CRS> + static auto check(int) -> decltype((*(CRS*)nullptr)(*(CS*)nullptr, *(CV*)nullptr)); + template<class CS, class CV, class CRS> + static tag_not_valid check(...); + + typedef decltype(check<seed_type, source_value_type, accumulator_type>(0)) type; + static const bool value = std::is_same<type, seed_type>::value; +}; + } #endif |