diff options
author | Grigoriy Chudnov <g.chudnov@gmail.com> | 2017-01-07 00:10:24 +0300 |
---|---|---|
committer | Kirk Shoop <kirk.shoop@microsoft.com> | 2017-01-06 14:44:03 -0800 |
commit | 36b3d8c855002fbfb4e1b17258bab4a0702d6e54 (patch) | |
tree | 28530e1e5fcb023b2599d5b8a7af320731e495f2 /Rx/v2 | |
parent | b343f852570a1808c083cc8f6901e6febb46d892 (diff) | |
download | RxCpp-36b3d8c855002fbfb4e1b17258bab4a0702d6e54.tar.gz |
decouple take_last from observable
Diffstat (limited to 'Rx/v2')
-rw-r--r-- | Rx/v2/src/rxcpp/operators/rx-take_last.hpp | 73 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-includes.hpp | 1 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-observable.hpp | 42 | ||||
-rw-r--r-- | Rx/v2/src/rxcpp/rx-operators.hpp | 8 | ||||
-rw-r--r-- | Rx/v2/test/operators/take_last.cpp | 5 |
5 files changed, 80 insertions, 49 deletions
diff --git a/Rx/v2/src/rxcpp/operators/rx-take_last.hpp b/Rx/v2/src/rxcpp/operators/rx-take_last.hpp index 7d1297d..d59b355 100644 --- a/Rx/v2/src/rxcpp/operators/rx-take_last.hpp +++ b/Rx/v2/src/rxcpp/operators/rx-take_last.hpp @@ -2,6 +2,21 @@ #pragma once +/*! \file rx-take_last.hpp + + \brief Emit only the final t items emitted by the source Observable. + + \tparam Count the type of the items counter. + + \param t the number of last items to take. + + \return An observable that emits only the last t items emitted by the source Observable, or all of the items from the source observable if that observable emits fewer than t items. + + \sample + \snippet take_last.cpp take_last sample + \snippet output.txt take_last sample +*/ + #if !defined(RXCPP_OPERATORS_RX_TAKE_LAST_HPP) #define RXCPP_OPERATORS_RX_TAKE_LAST_HPP @@ -13,6 +28,16 @@ namespace operators { namespace detail { +template<class... AN> +struct take_last_invalid_arguments {}; + +template<class... AN> +struct take_last_invalid : public rxo::operator_base<take_last_invalid_arguments<AN...>> { + using type = observable<take_last_invalid_arguments<AN...>, take_last_invalid<AN...>>; +}; +template<class... AN> +using take_last_invalid_t = typename take_last_invalid<AN...>::type; + template<class T, class Observable, class Count> struct take_last : public operator_base<T> { @@ -90,31 +115,41 @@ struct take_last : public operator_base<T> } }; -template<class T> -class take_last_factory -{ - typedef rxu::decay_t<T> count_type; - count_type count; -public: - take_last_factory(count_type t) : count(std::move(t)) {} - template<class Observable> - auto operator()(Observable&& source) - -> observable<rxu::value_type_t<rxu::decay_t<Observable>>, take_last<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, count_type>> { - return observable<rxu::value_type_t<rxu::decay_t<Observable>>, take_last<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, count_type>>( - take_last<rxu::value_type_t<rxu::decay_t<Observable>>, Observable, count_type>(std::forward<Observable>(source), count)); - } -}; - } -template<class T> -auto take_last(T&& t) - -> detail::take_last_factory<T> { - return detail::take_last_factory<T>(std::forward<T>(t)); +/*! @copydoc rx-take_last.hpp +*/ +template<class... AN> +auto take_last(AN&&... an) + -> operator_factory<take_last_tag, AN...> { + return operator_factory<take_last_tag, AN...>(std::make_tuple(std::forward<AN>(an)...)); } } +template<> +struct member_overload<take_last_tag> +{ + template<class Observable, + class Count, + class Enabled = rxu::enable_if_all_true_type_t< + is_observable<Observable>>, + class SourceValue = rxu::value_type_t<Observable>, + class TakeLast = rxo::detail::take_last<SourceValue, rxu::decay_t<Observable>, rxu::decay_t<Count>>, + class Value = rxu::value_type_t<TakeLast>, + class Result = observable<Value, TakeLast>> + static Result member(Observable&& o, Count&& c) { + return Result(TakeLast(std::forward<Observable>(o), std::forward<Count>(c))); + } + + template<class... AN> + static operators::detail::take_last_invalid_t<AN...> member(AN...) { + std::terminate(); + return {}; + static_assert(sizeof...(AN) == 10000, "take_last takes (Count)"); + } +}; + } #endif diff --git a/Rx/v2/src/rxcpp/rx-includes.hpp b/Rx/v2/src/rxcpp/rx-includes.hpp index 7155c09..cafcafd 100644 --- a/Rx/v2/src/rxcpp/rx-includes.hpp +++ b/Rx/v2/src/rxcpp/rx-includes.hpp @@ -209,6 +209,7 @@ #include "operators/rx-sequence_equal.hpp" #include "operators/rx-skip.hpp" #include "operators/rx-take.hpp" +#include "operators/rx-take_last.hpp" #include "operators/rx-take_while.hpp" #include "operators/rx-time_interval.hpp" #include "operators/rx-timeout.hpp" diff --git a/Rx/v2/src/rxcpp/rx-observable.hpp b/Rx/v2/src/rxcpp/rx-observable.hpp index f82a8e0..5e11b67 100644 --- a/Rx/v2/src/rxcpp/rx-observable.hpp +++ b/Rx/v2/src/rxcpp/rx-observable.hpp @@ -2087,29 +2087,6 @@ public: return observable_member(take_tag{}, *this, std::forward<AN>(an)...); } - /*! Emit only the final t items emitted by the source Observable. - - \tparam Count the type of the items counter - - \param t the number of last items to take - - \return An observable that emits only the last t items emitted by the source Observable, or all of the items from the source observable if that observable emits fewer than t items. - - \sample - \snippet take_last.cpp take_last sample - \snippet output.txt take_last sample - */ - template<class Count> - auto take_last(Count t) const - /// \cond SHOW_SERVICE_MEMBERS - -> observable<T, rxo::detail::take_last<T, this_type, Count>> - /// \endcond - { - return observable<T, rxo::detail::take_last<T, this_type, Count>>( - rxo::detail::take_last<T, this_type, Count>(*this, t)); - } - - /*! For each item from this observable until on_next occurs on the trigger observable, emit them from the new observable that is returned. \tparam TriggerSource the type of the trigger observable @@ -2209,15 +2186,26 @@ public: return take_until(rxs::timer(when, cn), cn); } + /*! @copydoc rx-take_last.hpp + */ + template<class... AN> + auto take_last(AN&&... an) const + /// \cond SHOW_SERVICE_MEMBERS + -> decltype(observable_member(take_last_tag{}, *(this_type*)nullptr, std::forward<AN>(an)...)) + /// \endcond + { + return observable_member(take_last_tag{}, *this, std::forward<AN>(an)...); + } + /*! @copydoc rx-take_while.hpp */ template<class... AN> auto take_while(AN&&... an) const - /// \cond SHOW_SERVICE_MEMBERS - -> decltype(observable_member(take_while_tag{}, *(this_type*)nullptr, std::forward<AN>(an)...)) - /// \endcond + /// \cond SHOW_SERVICE_MEMBERS + -> decltype(observable_member(take_while_tag{}, *(this_type*)nullptr, std::forward<AN>(an)...)) + /// \endcond { - return observable_member(take_while_tag{}, *this, std::forward<AN>(an)...); + return observable_member(take_while_tag{}, *this, std::forward<AN>(an)...); } /*! @copydoc rx-repeat.hpp diff --git a/Rx/v2/src/rxcpp/rx-operators.hpp b/Rx/v2/src/rxcpp/rx-operators.hpp index 35897a1..291e11f 100644 --- a/Rx/v2/src/rxcpp/rx-operators.hpp +++ b/Rx/v2/src/rxcpp/rx-operators.hpp @@ -113,7 +113,6 @@ public: #include "operators/rx-subscribe_on.hpp" #include "operators/rx-switch_if_empty.hpp" #include "operators/rx-switch_on_next.hpp" -#include "operators/rx-take_last.hpp" #include "operators/rx-take_until.hpp" #include "operators/rx-tap.hpp" #include "operators/rx-window_toggle.hpp" @@ -327,6 +326,13 @@ struct take_tag { }; }; +struct take_last_tag { + template<class Included> + struct include_header{ + static_assert(Included::value, "missing include: please #include <rxcpp/operators/rx-take_last.hpp>"); + }; +}; + struct take_while_tag { template<class Included> struct include_header{ diff --git a/Rx/v2/test/operators/take_last.cpp b/Rx/v2/test/operators/take_last.cpp index 82d8696..76228f0 100644 --- a/Rx/v2/test/operators/take_last.cpp +++ b/Rx/v2/test/operators/take_last.cpp @@ -1,4 +1,5 @@ #include "../test.h" +#include <rxcpp/operators/rx-take_last.hpp> SCENARIO("take last 0", "[take_last][operators]"){ GIVEN("a source"){ @@ -20,9 +21,9 @@ SCENARIO("take last 0", "[take_last][operators]"){ auto res = w.start( [xs]() { return xs - .take_last(0) + | rxo::take_last(0) // forget type to workaround lambda deduction bug on msvc 2013 - .as_dynamic(); + | rxo::as_dynamic(); } ); |