summaryrefslogtreecommitdiff
path: root/Rx/v2
diff options
context:
space:
mode:
authorGrigoriy Chudnov <g.chudnov@gmail.com>2016-12-17 21:39:39 +0300
committerKirk Shoop <kirk.shoop@microsoft.com>2016-12-17 10:39:39 -0800
commitfa9428c65f09f76024f0f2acfb819f22f0875320 (patch)
tree87b965c6e028320e597f106a06dac0eae7253773 /Rx/v2
parenta5c54e7008395c86fb34a5544faf40405255a8fc (diff)
downloadRxCpp-fa9428c65f09f76024f0f2acfb819f22f0875320.tar.gz
decouple sequence_equal from observable (#295)
* decouple sequence_equal from observable * refactoring to fix msvc2013
Diffstat (limited to 'Rx/v2')
-rw-r--r--Rx/v2/src/rxcpp/operators/rx-sequence_equal.hpp141
-rw-r--r--Rx/v2/src/rxcpp/rx-includes.hpp1
-rw-r--r--Rx/v2/src/rxcpp/rx-observable.hpp106
-rw-r--r--Rx/v2/src/rxcpp/rx-operators.hpp8
-rw-r--r--Rx/v2/src/rxcpp/rx-util.hpp11
-rw-r--r--Rx/v2/test/operators/sequence_equal.cpp5
6 files changed, 125 insertions, 147 deletions
diff --git a/Rx/v2/src/rxcpp/operators/rx-sequence_equal.hpp b/Rx/v2/src/rxcpp/operators/rx-sequence_equal.hpp
index 32a0d30..06253b4 100644
--- a/Rx/v2/src/rxcpp/operators/rx-sequence_equal.hpp
+++ b/Rx/v2/src/rxcpp/operators/rx-sequence_equal.hpp
@@ -2,6 +2,25 @@
#pragma once
+/*! \file rx-sequence_equal.hpp
+
+ \brief Determine whether two Observables emit the same sequence of items.
+
+ \tparam OtherSource the type of the other observable.
+ \tparam BinaryPredicate the type of the value comparing function (optional). The signature should be equivalent to the following: bool pred(const T1& a, const T2& b);
+ \tparam Coordination the type of the scheduler (optional).
+
+ \param t the other Observable that emits items to compare.
+ \param pred the function that implements comparison of two values (optional).
+ \param cn the scheduler (optional).
+
+ \return Observable that emits true only if both sequences terminate normally after emitting the same sequence of items in the same order; otherwise it will emit false.
+
+ \sample
+ \snippet sequence_equal.cpp sequence_equal sample
+ \snippet output.txt sequence_equal sample
+*/
+
#if !defined(RXCPP_OPERATORS_RX_SEQUENCE_EQUAL_HPP)
#define RXCPP_OPERATORS_RX_SEQUENCE_EQUAL_HPP
@@ -13,6 +32,16 @@ namespace operators {
namespace detail {
+template<class... AN>
+struct sequence_equal_invalid_arguments {};
+
+template<class... AN>
+struct sequence_equal_invalid : public rxo::operator_base<sequence_equal_invalid_arguments<AN...>> {
+ using type = observable<sequence_equal_invalid_arguments<AN...>, sequence_equal_invalid<AN...>>;
+};
+template<class... AN>
+using sequence_equal_invalid_t = typename sequence_equal_invalid<AN...>::type;
+
template<class T, class Observable, class OtherObservable, class BinaryPredicate, class Coordination>
struct sequence_equal : public operator_base<bool>
{
@@ -173,60 +202,80 @@ struct sequence_equal : public operator_base<bool>
}
};
-template<class OtherObservable, class BinaryPredicate, class Coordination>
-class sequence_equal_factory
-{
- typedef rxu::decay_t<OtherObservable> other_source_type;
- typedef rxu::decay_t<Coordination> coordination_type;
- typedef rxu::decay_t<BinaryPredicate> predicate_type;
-
- other_source_type other_source;
- coordination_type coordination;
- predicate_type pred;
-
-public:
- sequence_equal_factory(other_source_type t, predicate_type p, coordination_type sf)
- : other_source(std::move(t))
- , coordination(std::move(sf))
- , pred(std::move(p))
- {
- }
-
- template<class Observable>
- auto operator()(Observable&& source)
- -> observable<bool, sequence_equal<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, other_source_type, BinaryPredicate, Coordination>> {
- return observable<bool, sequence_equal<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, other_source_type, BinaryPredicate, Coordination>>(
- sequence_equal<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, other_source_type, BinaryPredicate, Coordination>(std::forward<Observable>(source), other_source, pred, coordination));
- }
-};
-
}
-template<class OtherObservable>
-inline auto sequence_equal(OtherObservable&& t)
- -> detail::sequence_equal_factory<OtherObservable, rxu::equal_to<>, identity_one_worker> {
- return detail::sequence_equal_factory<OtherObservable, rxu::equal_to<>, identity_one_worker>(std::forward<OtherObservable>(t), rxu::equal_to<>(), identity_current_thread());
+/*! @copydoc rx-sequence_equal.hpp
+*/
+template<class... AN>
+auto sequence_equal(AN&&... an)
+ -> operator_factory<sequence_equal_tag, AN...> {
+ return operator_factory<sequence_equal_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
}
-template<class OtherObservable, class BinaryPredicate, class Check = typename std::enable_if<!is_coordination<BinaryPredicate>::value>::type>
-inline auto sequence_equal(OtherObservable&& t, BinaryPredicate&& pred)
- -> detail::sequence_equal_factory<OtherObservable, BinaryPredicate, identity_one_worker> {
- return detail::sequence_equal_factory<OtherObservable, BinaryPredicate, identity_one_worker>(std::forward<OtherObservable>(t), std::forward<BinaryPredicate>(pred), identity_current_thread());
}
-template<class OtherObservable, class Coordination, class Check = typename std::enable_if<is_coordination<Coordination>::value>::type>
-inline auto sequence_equal(OtherObservable&& t, Coordination&& cn)
- -> detail::sequence_equal_factory<OtherObservable, rxu::equal_to<>, Coordination> {
- return detail::sequence_equal_factory<OtherObservable, rxu::equal_to<>, Coordination>(std::forward<OtherObservable>(t), rxu::equal_to<>(), std::forward<Coordination>(cn));
-}
+template<>
+struct member_overload<sequence_equal_tag>
+{
+ template<class Observable, class OtherObservable,
+ class Enabled = rxu::enable_if_all_true_type_t<
+ is_observable<Observable>,
+ is_observable<OtherObservable>>,
+ class SourceValue = rxu::value_type_t<Observable>,
+ class SequenceEqual = rxo::detail::sequence_equal<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<OtherObservable>, rxu::equal_to<>, identity_one_worker>,
+ class Value = rxu::value_type_t<SequenceEqual>,
+ class Result = observable<Value, SequenceEqual>>
+ static Result member(Observable&& o, OtherObservable&& t) {
+ return Result(SequenceEqual(std::forward<Observable>(o), std::forward<OtherObservable>(t), rxu::equal_to<>(), identity_current_thread()));
+ }
-template<class OtherObservable, class BinaryPredicate, class Coordination>
-inline auto sequence_equal(OtherObservable&& t, BinaryPredicate&& pred, Coordination&& cn)
- -> detail::sequence_equal_factory<OtherObservable, BinaryPredicate, Coordination> {
- return detail::sequence_equal_factory<OtherObservable, BinaryPredicate, Coordination>(std::forward<OtherObservable>(t), std::forward<BinaryPredicate>(pred), std::forward<Coordination>(cn));
-}
+ template<class Observable, class OtherObservable, class BinaryPredicate,
+ class IsCoordination = is_coordination<BinaryPredicate>,
+ class Enabled = rxu::enable_if_all_true_type_t<
+ is_observable<Observable>,
+ is_observable<OtherObservable>,
+ rxu::negation<IsCoordination>>,
+ class SourceValue = rxu::value_type_t<Observable>,
+ class SequenceEqual = rxo::detail::sequence_equal<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<OtherObservable>, rxu::decay_t<BinaryPredicate>, identity_one_worker>,
+ class Value = rxu::value_type_t<SequenceEqual>,
+ class Result = observable<Value, SequenceEqual>>
+ static Result member(Observable&& o, OtherObservable&& t, BinaryPredicate&& pred) {
+ return Result(SequenceEqual(std::forward<Observable>(o), std::forward<OtherObservable>(t), std::forward<BinaryPredicate>(pred), identity_current_thread()));
+ }
-}
+ template<class Observable, class OtherObservable, class Coordination,
+ class Enabled = rxu::enable_if_all_true_type_t<
+ is_observable<Observable>,
+ is_observable<OtherObservable>,
+ is_coordination<Coordination>>,
+ class SourceValue = rxu::value_type_t<Observable>,
+ class SequenceEqual = rxo::detail::sequence_equal<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<OtherObservable>, rxu::equal_to<>, rxu::decay_t<Coordination>>,
+ class Value = rxu::value_type_t<SequenceEqual>,
+ class Result = observable<Value, SequenceEqual>>
+ static Result member(Observable&& o, OtherObservable&& t, Coordination&& cn) {
+ return Result(SequenceEqual(std::forward<Observable>(o), std::forward<OtherObservable>(t), rxu::equal_to<>(), std::forward<Coordination>(cn)));
+ }
+
+ template<class Observable, class OtherObservable, class BinaryPredicate, class Coordination,
+ class Enabled = rxu::enable_if_all_true_type_t<
+ is_observable<Observable>,
+ is_observable<OtherObservable>,
+ is_coordination<Coordination>>,
+ class SourceValue = rxu::value_type_t<Observable>,
+ class SequenceEqual = rxo::detail::sequence_equal<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<OtherObservable>, rxu::decay_t<BinaryPredicate>, rxu::decay_t<Coordination>>,
+ class Value = rxu::value_type_t<SequenceEqual>,
+ class Result = observable<Value, SequenceEqual>>
+ static Result member(Observable&& o, OtherObservable&& t, BinaryPredicate&& pred, Coordination&& cn) {
+ return Result(SequenceEqual(std::forward<Observable>(o), std::forward<OtherObservable>(t), std::forward<BinaryPredicate>(pred), std::forward<Coordination>(cn)));
+ }
+
+ template<class... AN>
+ static operators::detail::sequence_equal_invalid_t<AN...> member(const AN&...) {
+ std::terminate();
+ return {};
+ static_assert(sizeof...(AN) == 10000, "sequence_equal takes (OtherObservable, optional BinaryPredicate, optional Coordination)");
+ }
+};
}
diff --git a/Rx/v2/src/rxcpp/rx-includes.hpp b/Rx/v2/src/rxcpp/rx-includes.hpp
index 2feec7d..283793e 100644
--- a/Rx/v2/src/rxcpp/rx-includes.hpp
+++ b/Rx/v2/src/rxcpp/rx-includes.hpp
@@ -197,6 +197,7 @@
#include "operators/rx-map.hpp"
#include "operators/rx-on_error_resume_next.hpp"
#include "operators/rx-reduce.hpp"
+#include "operators/rx-sequence_equal.hpp"
#include "operators/rx-take_while.hpp"
#include "operators/rx-retry.hpp"
#include "operators/rx-with_latest_from.hpp"
diff --git a/Rx/v2/src/rxcpp/rx-observable.hpp b/Rx/v2/src/rxcpp/rx-observable.hpp
index 2ff85ae..ff68936 100644
--- a/Rx/v2/src/rxcpp/rx-observable.hpp
+++ b/Rx/v2/src/rxcpp/rx-observable.hpp
@@ -838,105 +838,15 @@ public:
return switch_if_empty(rxs::from(std::move(v)));
}
- /*! Determine whether two Observables emit the same sequence of items.
-
- \tparam OtherSource the type of the other observable.
- \tparam BinaryPredicate the type of the value comparing function. The signature should be equivalent to the following: bool pred(const T1& a, const T2& b);
- \tparam Coordination the type of the scheduler.
-
- \param t the other Observable that emits items to compare.
- \param pred the function that implements comparison of two values.
- \param cn the scheduler.
-
- \return Observable that emits true only if both sequences terminate normally after emitting the same sequence of items in the same order; otherwise it will emit false.
-
- \sample
- \snippet sequence_equal.cpp sequence_equal sample
- \snippet output.txt sequence_equal sample
- */
- template<class OtherSource, class BinaryPredicate, class Coordination>
- auto sequence_equal(OtherSource&& t, BinaryPredicate&& pred, Coordination&& cn) const
- /// \cond SHOW_SERVICE_MEMBERS
- -> typename std::enable_if<is_observable<OtherSource>::value,
- observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, Coordination>>>::type
- /// \endcond
- {
- return observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, Coordination>>(
- rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, Coordination>(*this, std::forward<OtherSource>(t), std::forward<BinaryPredicate>(pred), std::forward<Coordination>(cn)));
- }
-
-
- /*! Determine whether two Observables emit the same sequence of items.
-
- \tparam OtherSource the type of the other observable.
- \tparam BinaryPredicate the type of the value comparing function. The signature should be equivalent to the following: bool pred(const T1& a, const T2& b);
-
- \param t the other Observable that emits items to compare.
- \param pred the function that implements comparison of two values.
-
- \return Observable that emits true only if both sequences terminate normally after emitting the same sequence of items in the same order; otherwise it will emit false.
-
- \sample
- \snippet sequence_equal.cpp sequence_equal sample
- \snippet output.txt sequence_equal sample
- */
- template<class OtherSource, class BinaryPredicate>
- auto sequence_equal(OtherSource&& t, BinaryPredicate&& pred) const
- /// \cond SHOW_SERVICE_MEMBERS
- -> typename std::enable_if<is_observable<OtherSource>::value && !is_coordination<BinaryPredicate>::value,
- observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, identity_one_worker>>>::type
- /// \endcond
- {
- return observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, identity_one_worker>>(
- rxo::detail::sequence_equal<T, this_type, OtherSource, BinaryPredicate, identity_one_worker>(*this, std::forward<OtherSource>(t), std::forward<BinaryPredicate>(pred), identity_one_worker(rxsc::make_current_thread())));
- }
-
- /*! Determine whether two Observables emit the same sequence of items.
-
- \tparam OtherSource the type of the other observable.
- \tparam Coordination the type of the scheduler.
-
- \param t the other Observable that emits items to compare.
- \param cn the scheduler.
-
- \return Observable that emits true only if both sequences terminate normally after emitting the same sequence of items in the same order; otherwise it will emit false.
-
- \sample
- \snippet sequence_equal.cpp sequence_equal sample
- \snippet output.txt sequence_equal sample
- */
- template<class OtherSource, class Coordination>
- auto sequence_equal(OtherSource&& t, Coordination&& cn) const
- /// \cond SHOW_SERVICE_MEMBERS
- -> typename std::enable_if<is_observable<OtherSource>::value && is_coordination<Coordination>::value,
- observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, Coordination>>>::type
- /// \endcond
- {
- return observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, Coordination>>(
- rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, Coordination>(*this, std::forward<OtherSource>(t), rxu::equal_to<>(), std::forward<Coordination>(cn)));
- }
-
- /*! Determine whether two Observables emit the same sequence of items.
-
- \tparam OtherSource the type of the other observable.
-
- \param t the other Observable that emits items to compare.
-
- \return Observable that emits true only if both sequences terminate normally after emitting the same sequence of items in the same order; otherwise it will emit false.
-
- \sample
- \snippet sequence_equal.cpp sequence_equal sample
- \snippet output.txt sequence_equal sample
- */
- template<class OtherSource>
- auto sequence_equal(OtherSource&& t) const
- /// \cond SHOW_SERVICE_MEMBERS
- -> typename std::enable_if<is_observable<OtherSource>::value,
- observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, identity_one_worker>>>::type
- /// \endcond
+ /*! @copydoc rx-sequence_equal.hpp
+ */
+ template<class... AN>
+ auto sequence_equal(AN... an) const
+ /// \cond SHOW_SERVICE_MEMBERS
+ -> decltype(observable_member(sequence_equal_tag{}, *(this_type*)nullptr, std::forward<AN>(an)...))
+ /// \endcond
{
- return observable<bool, rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, identity_one_worker>>(
- rxo::detail::sequence_equal<T, this_type, OtherSource, rxu::equal_to<>, identity_one_worker>(*this, std::forward<OtherSource>(t), rxu::equal_to<>(), identity_one_worker(rxsc::make_current_thread())));
+ return observable_member(sequence_equal_tag{}, *this, std::forward<AN>(an)...);
}
/*! inspect calls to on_next, on_error and on_completed.
diff --git a/Rx/v2/src/rxcpp/rx-operators.hpp b/Rx/v2/src/rxcpp/rx-operators.hpp
index be4d485..975c4e6 100644
--- a/Rx/v2/src/rxcpp/rx-operators.hpp
+++ b/Rx/v2/src/rxcpp/rx-operators.hpp
@@ -114,7 +114,6 @@ public:
#include "operators/rx-replay.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"
#include "operators/rx-skip_until.hpp"
@@ -274,6 +273,13 @@ struct retry_tag {
};
};
+struct sequence_equal_tag {
+ template<class Included>
+ struct include_header{
+ static_assert(Included::value, "missing include: please #include <rxcpp/operators/rx-sequence_equal.hpp>");
+ };
+};
+
struct with_latest_from_tag {
template<class Included>
struct include_header{
diff --git a/Rx/v2/src/rxcpp/rx-util.hpp b/Rx/v2/src/rxcpp/rx-util.hpp
index 3ddc0b9..0e09301 100644
--- a/Rx/v2/src/rxcpp/rx-util.hpp
+++ b/Rx/v2/src/rxcpp/rx-util.hpp
@@ -780,6 +780,17 @@ namespace detail {
template <class T, class Decayed = decay_t<T>>
struct is_duration : detail::is_duration<Decayed> {};
+
+// C++17 negation
+namespace detail {
+ template<class T>
+ struct not_value : std::conditional<T::value, std::false_type, std::true_type>::type {
+ };
+}
+
+template <class T>
+struct negation : detail::not_value<T> {};
+
}
namespace rxu=util;
diff --git a/Rx/v2/test/operators/sequence_equal.cpp b/Rx/v2/test/operators/sequence_equal.cpp
index b1b5046..6ada320 100644
--- a/Rx/v2/test/operators/sequence_equal.cpp
+++ b/Rx/v2/test/operators/sequence_equal.cpp
@@ -1,4 +1,5 @@
#include "../test.h"
+#include "rxcpp/operators/rx-sequence_equal.hpp"
SCENARIO("sequence_equal - source never emits", "[sequence_equal][operators]"){
GIVEN("two sources"){
@@ -24,8 +25,8 @@ SCENARIO("sequence_equal - source never emits", "[sequence_equal][operators]"){
auto res = w.start(
[xs, ys]() {
return xs
- .sequence_equal(ys)
- .as_dynamic(); // forget type to workaround lambda deduction bug on msvc 2013
+ | rxo::sequence_equal(ys)
+ | rxo::as_dynamic(); // forget type to workaround lambda deduction bug on msvc 2013
}
);