aboutsummaryrefslogtreecommitdiffstats
path: root/Rx/v2/src
diff options
context:
space:
mode:
authorGrigoriy Chudnov <g.chudnov@gmail.com>2017-01-11 22:10:36 +0300
committerKirk Shoop <kirk.shoop@microsoft.com>2017-01-11 11:10:36 -0800
commit5af562282f25a500d17da9c283541d7ab33d1785 (patch)
tree0974d1ef1107d658a1eefef809e2676d173c9d42 /Rx/v2/src
parent13d406282a025f799f7674513dc2222f68d15dd4 (diff)
downloadplatform_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.hpp17
-rw-r--r--Rx/v2/src/rxcpp/operators/rx-scan.hpp89
-rw-r--r--Rx/v2/src/rxcpp/rx-includes.hpp1
-rw-r--r--Rx/v2/src/rxcpp/rx-observable.hpp23
-rw-r--r--Rx/v2/src/rxcpp/rx-operators.hpp8
-rw-r--r--Rx/v2/src/rxcpp/rx-predef.hpp17
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