From 7a4dd376f774545ccccd7222455cdb60a76ce923 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Wed, 14 Feb 2024 18:24:47 +0300 Subject: [PATCH 01/19] simplify a bit --- .../observables/details/chain_strategy.hpp | 2 +- src/rpp/rpp/observables/fwd.hpp | 16 ++++-- src/rpp/rpp/observables/observable.hpp | 12 +++-- src/rpp/rpp/operators/details/strategy.hpp | 54 +++++-------------- src/rpp/rpp/operators/distinct.hpp | 17 ++++-- src/tests/utils/copy_count_tracker.hpp | 26 ++++----- 6 files changed, 58 insertions(+), 69 deletions(-) diff --git a/src/rpp/rpp/observables/details/chain_strategy.hpp b/src/rpp/rpp/observables/details/chain_strategy.hpp index e50a2c5e3..d0087b53b 100644 --- a/src/rpp/rpp/observables/details/chain_strategy.hpp +++ b/src/rpp/rpp/observables/details/chain_strategy.hpp @@ -23,7 +23,7 @@ class observable_chain_strategy public: using expected_disposable_strategy = details::observables::deduce_updated_disposable_strategy; - using value_type = typename TStrategy::template result_value; + using value_type = typename TStrategy::template traits::result_type; observable_chain_strategy(const TStrategy& strategy, const TStrategies&... strategies) : m_strategy(strategy) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 085fd0196..299b83abe 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -92,30 +92,36 @@ concept operator_observable_transform = requires(const Op& op, TObs obs) template concept operator_base = requires(const Op& op) { - typename std::decay_t::template result_value; + typename std::decay_t::template traits; + typename std::decay_t::template traits::result_type; requires details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; }; template -concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template result_value>&& observer, const observable_chain_strategy>& chain) +concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer, const observable_chain_strategy>& chain) { {op.subscribe(std::move(observer), chain)}; }; template -concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template result_value>&& observer) +concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer) { {op.template lift(std::move(observer))} -> rpp::constraint::observer_of_type; }; template -concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template result_value>&& observer) +concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer) { {op.template lift_with_disposable_strategy(std::move(observer))} -> rpp::constraint::observer_of_type; }; +template +concept operator_requirements_satisfied = (!(requires {typename std::decay_t::template traits::requirements; }) || std::is_destructible_v::template traits::requirements>); + template -concept operator_chain = operator_subscribe || operator_lift || operator_lift_with_disposable_strategy; +concept operator_chain = operator_base + && operator_requirements_satisfied + && (operator_subscribe || operator_lift || operator_lift_with_disposable_strategy); template concept observables_of_same_type = rpp::constraint::observable && diff --git a/src/rpp/rpp/observables/observable.hpp b/src/rpp/rpp/observables/observable.hpp index 30828eae8..7cb70412a 100644 --- a/src/rpp/rpp/observables/observable.hpp +++ b/src/rpp/rpp/observables/observable.hpp @@ -36,7 +36,7 @@ class observable { public: using value_type = Type; - + using expected_disposable_strategy = rpp::details::observables::deduce_disposable_strategy_t; template @@ -310,16 +310,18 @@ class observable */ auto as_dynamic() && { return rpp::dynamic_observable{std::move(*this)}; } - template Op> + template Op> auto operator|(Op&& op) const & { - return observable::template result_value, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; + static_assert(constraint::operator_chain); + return observable::template traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; } - template Op> + template Op> auto operator|(Op&& op) && { - return observable::template result_value, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; + static_assert(constraint::operator_chain); + return observable::template traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; } template Op> diff --git a/src/rpp/rpp/operators/details/strategy.hpp b/src/rpp/rpp/operators/details/strategy.hpp index ee5737d1a..684a35013 100644 --- a/src/rpp/rpp/operators/details/strategy.hpp +++ b/src/rpp/rpp/operators/details/strategy.hpp @@ -23,61 +23,33 @@ namespace rpp::operators::details { -template -class operator_observable_strategy_base +template +class lift_operator { public: - template... TArgs> - operator_observable_strategy_base(TArgs&&... args) - : m_vals{std::forward(args)...} + template... TTArgs> + lift_operator(TTArgs&&... args) + : m_vals{std::forward(args)...} { } template auto lift(Observer&& observer) const { - return m_vals.apply(&SubscribeStrategy::template apply, std::forward(observer)); + return m_vals.apply(&apply, std::forward(observer)); } private: - RPP_NO_UNIQUE_ADDRESS rpp::utils::tuple m_vals{}; -}; - -template typename Strategy, typename Types> -struct identity_subscribe_strategy; - -template typename Strategy, typename... Types> -struct identity_subscribe_strategy> -{ - template + template static auto apply(Observer&& observer, const Args&... vals) { - return rpp::observer, Types...>>{std::forward(observer), vals...}; + static_assert(rpp::constraint::observer_of_type, typename Operator::template traits::result_type>); + return rpp::observer::template observer_strategy>>{std::forward(observer), vals...}; } -}; - -template typename Strategy, rpp::constraint::decayed_type... Args> -using operator_observable_strategy = operator_observable_strategy_base>, Args...>; - -template typename Strategy, typename Types = rpp::utils::types<>, rpp::constraint::decayed_type... Args> -using operator_observable_strategy_different_types = operator_observable_strategy_base, Args...>; - -template typename Strategy, typename Types> -struct template_subscribe_strategy; -template typename Strategy, typename... Types> -struct template_subscribe_strategy> -{ - template - static auto apply(Observer&& observer, const Args&... vals) - { - return rpp::observer, Types...>>{std::forward(observer), vals...}; - } +private: + RPP_NO_UNIQUE_ADDRESS rpp::utils::tuple m_vals{}; }; - -template typename Strategy, rpp::constraint::decayed_type... Args> -using template_operator_observable_strategy = operator_observable_strategy_base>, Args...>; - -template typename Strategy, typename Types = rpp::utils::types<>, rpp::constraint::decayed_type... Args> -using template_operator_observable_strategy_different_types = operator_observable_strategy_base, Args...>; } diff --git a/src/rpp/rpp/operators/distinct.hpp b/src/rpp/rpp/operators/distinct.hpp index dcc71d5f3..e762a6490 100644 --- a/src/rpp/rpp/operators/distinct.hpp +++ b/src/rpp/rpp/operators/distinct.hpp @@ -23,8 +23,6 @@ namespace rpp::operators::details template struct distinct_observer_strategy { - static_assert(rpp::constraint::hashable, "Distinct operator requires hashable type"); - using preferred_disposable_strategy = rpp::details::observers::none_disposable_strategy; RPP_NO_UNIQUE_ADDRESS TObserver observer; @@ -49,10 +47,21 @@ struct distinct_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct distinct_t : public operators::details::template_operator_observable_strategy +struct distinct_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + struct requirements + { + static_assert(rpp::constraint::hashable, "T is not hashable"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = distinct_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/tests/utils/copy_count_tracker.hpp b/src/tests/utils/copy_count_tracker.hpp index eedf8f1e1..f02108bef 100644 --- a/src/tests/utils/copy_count_tracker.hpp +++ b/src/tests/utils/copy_count_tracker.hpp @@ -117,16 +117,16 @@ class copy_count_tracker std::shared_ptr _state; }; -namespace std -{ -// Make copy_count_tracker hashable for distinct operator -template<> -struct hash -{ - size_t operator()(const copy_count_tracker& tracker) const noexcept - { - return std::hash{}(tracker.get_copy_count()) - ^ (std::hash{}(tracker.get_move_count()) << 1); - } -}; -} +// namespace std +// { +// // Make copy_count_tracker hashable for distinct operator +// template<> +// struct hash +// { +// size_t operator()(const copy_count_tracker& tracker) const noexcept +// { +// return std::hash{}(tracker.get_copy_count()) +// ^ (std::hash{}(tracker.get_move_count()) << 1); +// } +// }; +// } From 91e286a81ce22ba5a37ab191c2e9e4c63a632e46 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 00:21:20 +0300 Subject: [PATCH 02/19] fix args --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f74ccbc62..9116f6d65 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,8 @@ "--header-insertion=never", "--background-index", "--clang-tidy", - "-j=32" + "-j=32", + "--function-arg-placeholders=0" ], "sonarlint.pathToCompileCommands": "${workspaceFolder}/build/compile_commands.json", } \ No newline at end of file From 5facd56597a1f16a2a889108f615fbfb48dec68d Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 00:21:25 +0300 Subject: [PATCH 03/19] improve error message --- docs/readme.md | 16 ++++++-- src/rpp/rpp/operators/buffer.hpp | 10 ++++- src/rpp/rpp/operators/combine_latest.hpp | 11 ++++- src/rpp/rpp/operators/concat.hpp | 16 ++++++-- src/rpp/rpp/operators/debounce.hpp | 5 ++- src/rpp/rpp/operators/delay.hpp | 5 ++- .../rpp/operators/distinct_until_changed.hpp | 16 ++++++-- src/rpp/rpp/operators/filter.hpp | 16 ++++++-- src/rpp/rpp/operators/first.hpp | 10 ++++- src/rpp/rpp/operators/group_by.hpp | 22 +++++++--- src/rpp/rpp/operators/last.hpp | 10 ++++- src/rpp/rpp/operators/map.hpp | 16 ++++++-- src/rpp/rpp/operators/merge.hpp | 22 ++++++++-- src/rpp/rpp/operators/reduce.hpp | 34 ++++++++++++---- src/rpp/rpp/operators/scan.hpp | 40 ++++++++++++++----- src/rpp/rpp/operators/skip.hpp | 10 ++++- src/rpp/rpp/operators/subscribe_on.hpp | 5 ++- src/rpp/rpp/operators/switch_on_next.hpp | 17 ++++++-- src/rpp/rpp/operators/take.hpp | 10 ++++- src/rpp/rpp/operators/take_last.hpp | 10 ++++- src/rpp/rpp/operators/take_until.hpp | 5 ++- src/rpp/rpp/operators/take_while.hpp | 16 ++++++-- src/rpp/rpp/operators/throttle.hpp | 10 ++++- src/rpp/rpp/operators/window.hpp | 10 ++++- src/rpp/rpp/operators/window_toggle.hpp | 7 +++- src/rpp/rpp/operators/with_latest_from.hpp | 11 ++++- 26 files changed, 288 insertions(+), 72 deletions(-) diff --git a/docs/readme.md b/docs/readme.md index bf43eaeeb..5fe7f8e7b 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -269,15 +269,25 @@ There we convert observable to concatenation of original observable and `just(2) One more posible but a bit more advanced way to implement operators - is to lift observer. To do this, your functor-adapter must to satisfy `rpp::constraint::operator_lift` concept. Actually, your class must to have: - member function `lift` accepting downstream observer and returning new upstream observer -- using `result_value` accepting typename of upstream and providing new value for downstream (== typename of original observable and return new resulting type for new observable) +- inner `template struct traits` struct accepting typename of upstream and providing: + - `using result_type =` with typename of new resulting type for new observable + - (optionally) `struct requirements` with static_asserts over passed type Example: ```cpp template struct map { - template - using result_value = std::invoke_result_t; + template + struct traits + { + struct requirements + { + static_assert(std::invocable, "Fn is not invocable with T"); + }; + + using result_type = std::invoke_result_t; + }; Fn fn{}; diff --git a/src/rpp/rpp/operators/buffer.hpp b/src/rpp/rpp/operators/buffer.hpp index 3e9be1406..05ed88e3e 100644 --- a/src/rpp/rpp/operators/buffer.hpp +++ b/src/rpp/rpp/operators/buffer.hpp @@ -64,10 +64,16 @@ class buffer_observer_strategy mutable std::vector m_bucket; }; -struct buffer_t : public operators::details::operator_observable_strategy_different_types, size_t> +struct buffer_t final : public operators::details::lift_operator { template - using result_value = std::vector; + struct traits + { + using result_type = std::vector; + + template TObserver> + using observer_strategy = buffer_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/combine_latest.hpp b/src/rpp/rpp/operators/combine_latest.hpp index 17d62352d..d82b0112d 100644 --- a/src/rpp/rpp/operators/combine_latest.hpp +++ b/src/rpp/rpp/operators/combine_latest.hpp @@ -103,8 +103,15 @@ struct combine_latest_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - requires std::invocable...> - using result_value = std::invoke_result_t...>; + struct traits + { + struct requirements + { + static_assert(std::invocable...>, "Selector is not callable with passed T type"); + }; + + using result_type = std::invoke_result_t...>; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/concat.hpp b/src/rpp/rpp/operators/concat.hpp index d8de38db9..1de6f6f42 100644 --- a/src/rpp/rpp/operators/concat.hpp +++ b/src/rpp/rpp/operators/concat.hpp @@ -195,11 +195,21 @@ struct concat_observer_strategy : public concat_observer_strategy_base +struct concat_t final : public operators::details::lift_operator { template - requires rpp::constraint::observable - using result_value = rpp::utils::extract_observable_type_t; + struct traits + { + struct requirements + { + static_assert(rpp::constraint::observable, "T is not observable"); + }; + + using result_type = rpp::utils::extract_observable_type_t; + + template TObserver> + using observer_strategy = concat_observer_strategy; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/debounce.hpp b/src/rpp/rpp/operators/debounce.hpp index 9541efbc7..7c256d94c 100644 --- a/src/rpp/rpp/operators/debounce.hpp +++ b/src/rpp/rpp/operators/debounce.hpp @@ -156,7 +156,10 @@ template struct debounce_t { template - using result_value = T; + struct traits + { + using result_type = T; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/delay.hpp b/src/rpp/rpp/operators/delay.hpp index 5959f23a8..397ead20d 100644 --- a/src/rpp/rpp/operators/delay.hpp +++ b/src/rpp/rpp/operators/delay.hpp @@ -170,7 +170,10 @@ template struct delay_t { template - using result_value = T; + struct traits + { + using result_type = T; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/distinct_until_changed.hpp b/src/rpp/rpp/operators/distinct_until_changed.hpp index 876bbe016..5e36c66b9 100644 --- a/src/rpp/rpp/operators/distinct_until_changed.hpp +++ b/src/rpp/rpp/operators/distinct_until_changed.hpp @@ -48,11 +48,21 @@ struct distinct_until_changed_observer_strategy }; template -struct distinct_until_changed_t : public operators::details::template_operator_observable_strategy +struct distinct_until_changed_t : public operators::details::lift_operator, EqualityFn> { template - requires rpp::constraint::invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(rpp::constraint::invocable_r_v, "EqualityFn is not invocable with T and T returning bool"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = distinct_until_changed_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/filter.hpp b/src/rpp/rpp/operators/filter.hpp index d3a16e615..b902e9945 100644 --- a/src/rpp/rpp/operators/filter.hpp +++ b/src/rpp/rpp/operators/filter.hpp @@ -44,11 +44,21 @@ struct filter_observer_strategy }; template -struct filter_t : public operators::details::operator_observable_strategy +struct filter_t final : public operators::details::lift_operator, Fn> { template - requires std::is_invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = filter_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/first.hpp b/src/rpp/rpp/operators/first.hpp index 838960ea7..f9743b9ad 100644 --- a/src/rpp/rpp/operators/first.hpp +++ b/src/rpp/rpp/operators/first.hpp @@ -43,10 +43,16 @@ struct first_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct first_t : public operators::details::operator_observable_strategy +struct first_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = first_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/group_by.hpp b/src/rpp/rpp/operators/group_by.hpp index 75de84d6f..10b827059 100644 --- a/src/rpp/rpp/operators/group_by.hpp +++ b/src/rpp/rpp/operators/group_by.hpp @@ -162,13 +162,25 @@ struct group_by_observable_strategy }; template -struct group_by_t : public operators::details::template_operator_observable_strategy +struct group_by_t final : public operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator> { - using operators::details::template_operator_observable_strategy::template_operator_observable_strategy; - + using operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator>::lift_operator; + template - requires std::invocable && std::invocable && std::strict_weak_order, rpp::utils::decayed_invoke_result_t> - using result_value = grouped_observable, rpp::utils::decayed_invoke_result_t, group_by_observable_strategy>>; + struct traits + { + struct requirements + { + static_assert(std::invocable, "KeySelector is not invocacble with T"); + static_assert(std::invocable, "ValueSelector is not invocable with T"); + static_assert(std::strict_weak_order, rpp::utils::decayed_invoke_result_t>, "KeyComparator is not invocable with result of KeySelector"); + }; + + using result_type = grouped_observable, rpp::utils::decayed_invoke_result_t, group_by_observable_strategy>>; + + template TObserver> + using observer_strategy = group_by_observer_strategy; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/last.hpp b/src/rpp/rpp/operators/last.hpp index de187f3ff..503237cf8 100644 --- a/src/rpp/rpp/operators/last.hpp +++ b/src/rpp/rpp/operators/last.hpp @@ -51,10 +51,16 @@ struct last_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct last_t : public operators::details::template_operator_observable_strategy +struct last_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = last_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/map.hpp b/src/rpp/rpp/operators/map.hpp index 7ae7aa03d..a7edaedd4 100644 --- a/src/rpp/rpp/operators/map.hpp +++ b/src/rpp/rpp/operators/map.hpp @@ -43,11 +43,21 @@ struct map_observer_strategy }; template -struct map_t : public operators::details::operator_observable_strategy +struct map_t final : public operators::details::lift_operator, Fn> { template - requires std::invocable - using result_value = std::invoke_result_t; + struct traits + { + struct requirements + { + static_assert(std::invocable, "Fn is not invocable with T"); + }; + + using result_type = std::invoke_result_t; + + template TObserver> + using observer_strategy = map_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/merge.hpp b/src/rpp/rpp/operators/merge.hpp index 0571ebe97..a6091b278 100644 --- a/src/rpp/rpp/operators/merge.hpp +++ b/src/rpp/rpp/operators/merge.hpp @@ -133,8 +133,15 @@ class merge_observer_strategy final : public merge_observer_base_strategy - requires rpp::constraint::observable - using result_value = rpp::utils::extract_observable_type_t; + struct traits + { + struct requirements + { + static_assert(rpp::constraint::observable, "T is not observable"); + }; + + using result_type = rpp::utils::extract_observable_type_t; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; @@ -157,8 +164,15 @@ struct merge_with_t RPP_NO_UNIQUE_ADDRESS rpp::utils::tuple observables{}; template - requires (std::same_as> && ...) - using result_value = T; + struct traits + { + struct requirements + { + static_assert((std::same_as> && ...), "T is not same as values of other observables"); + }; + + using result_type = T; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/reduce.hpp b/src/rpp/rpp/operators/reduce.hpp index ad69db487..53c5a0c5e 100644 --- a/src/rpp/rpp/operators/reduce.hpp +++ b/src/rpp/rpp/operators/reduce.hpp @@ -47,13 +47,23 @@ struct reduce_observer_strategy }; template -struct reduce_t : public operators::details::operator_observable_strategy_different_types, Seed, Accumulator> +struct reduce_t final : public operators::details::lift_operator, Seed, Accumulator> { - using operators::details::operator_observable_strategy_different_types, Seed, Accumulator>::operator_observable_strategy_different_types; + using operators::details::lift_operator, Seed, Accumulator>::lift_operator; template - requires std::is_invocable_r_v - using result_value = Seed; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); + }; + + using result_type = Seed; + + template TObserver> + using observer_strategy = reduce_observer_strategy; + }; template using updated_disposable_strategy = Prev; @@ -92,11 +102,21 @@ struct reduce_no_seed_observer_strategy }; template -struct reduce_no_seed_t : public operators::details::operator_observable_strategy +struct reduce_no_seed_t final : public operators::details::lift_operator, Accumulator> { template - requires std::is_invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = reduce_no_seed_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/scan.hpp b/src/rpp/rpp/operators/scan.hpp index 512619715..a85dd845f 100644 --- a/src/rpp/rpp/operators/scan.hpp +++ b/src/rpp/rpp/operators/scan.hpp @@ -52,23 +52,35 @@ struct scan_observer_strategy }; template -struct scan_t : public operators::details::operator_observable_strategy +struct scan_t final : public operators::details::lift_operator, InitialValue, Fn> { - using operators::details::operator_observable_strategy::operator_observable_strategy; - + using operators::details::lift_operator, InitialValue, Fn>::lift_operator; + template - requires std::is_invocable_r_v - using result_value = InitialValue; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); + }; + + using result_type = InitialValue; + + template TObserver> + using observer_strategy = scan_observer_strategy; + }; template using updated_disposable_strategy = Prev; }; -template +template struct scan_no_seed_observer_strategy { using preferred_disposable_strategy = rpp::details::observers::none_disposable_strategy; + using Seed = rpp::utils::extract_observer_type_t; + RPP_NO_UNIQUE_ADDRESS TObserver observer; RPP_NO_UNIQUE_ADDRESS Fn fn; mutable std::optional seed{}; @@ -94,11 +106,21 @@ struct scan_no_seed_observer_strategy }; template -struct scan_no_seed_t : public operators::details::template_operator_observable_strategy +struct scan_no_seed_t final : public operators::details::lift_operator, Fn> { template - requires std::is_invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = scan_no_seed_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/skip.hpp b/src/rpp/rpp/operators/skip.hpp index 6158b887a..c5f0a78e3 100644 --- a/src/rpp/rpp/operators/skip.hpp +++ b/src/rpp/rpp/operators/skip.hpp @@ -45,10 +45,16 @@ struct skip_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct skip_t : public operators::details::operator_observable_strategy_different_types, size_t> +struct skip_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = skip_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/subscribe_on.hpp b/src/rpp/rpp/operators/subscribe_on.hpp index 4264a2386..e68b3af27 100644 --- a/src/rpp/rpp/operators/subscribe_on.hpp +++ b/src/rpp/rpp/operators/subscribe_on.hpp @@ -36,7 +36,10 @@ template struct subscribe_on_t { template - using result_value = T; + struct traits + { + using result_type = T; + }; template using updated_disposable_strategy = typename Prev::template add::is_none_disposable ? 0 : 1>; diff --git a/src/rpp/rpp/operators/switch_on_next.hpp b/src/rpp/rpp/operators/switch_on_next.hpp index c2ee5cb35..3112b977e 100644 --- a/src/rpp/rpp/operators/switch_on_next.hpp +++ b/src/rpp/rpp/operators/switch_on_next.hpp @@ -134,10 +134,21 @@ class switch_on_next_observer_strategy mutable rpp::composite_disposable_wrapper m_last_refcount = composite_disposable_wrapper::empty(); }; -struct switch_on_next_t : public operators::details::operator_observable_strategy +struct switch_on_next_t final : public operators::details::lift_operator { - template - using result_value = rpp::utils::extract_observable_type_t; + template + struct traits + { + struct requirements + { + static_assert(rpp::constraint::observable, "T is not observable"); + }; + + using result_type = rpp::utils::extract_observable_type_t; + + template TObserver> + using observer_strategy = switch_on_next_observer_strategy; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/take.hpp b/src/rpp/rpp/operators/take.hpp index 6ac92125c..c2b54f797 100644 --- a/src/rpp/rpp/operators/take.hpp +++ b/src/rpp/rpp/operators/take.hpp @@ -49,10 +49,16 @@ struct take_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct take_t : public operator_observable_strategy_different_types, size_t> +struct take_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = take_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/take_last.hpp b/src/rpp/rpp/operators/take_last.hpp index bd37d5e9f..781edcb43 100644 --- a/src/rpp/rpp/operators/take_last.hpp +++ b/src/rpp/rpp/operators/take_last.hpp @@ -80,10 +80,16 @@ class take_last_observer_strategy mutable size_t m_current_end{}; }; -struct take_last_t : public operator_observable_strategy_different_types, size_t> +struct take_last_t final : public operators::details::lift_operator { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = take_last_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/take_until.hpp b/src/rpp/rpp/operators/take_until.hpp index 05a92feaf..f60028986 100644 --- a/src/rpp/rpp/operators/take_until.hpp +++ b/src/rpp/rpp/operators/take_until.hpp @@ -90,7 +90,10 @@ struct take_until_t RPP_NO_UNIQUE_ADDRESS TObservable observable{}; template - using result_value = T; + struct traits + { + using result_type = T; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index 834e8916e..a0e68ea75 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -44,11 +44,21 @@ struct take_while_observer_strategy }; template -struct take_while_t : public operators::details::operator_observable_strategy +struct take_while_t final : public operators::details::lift_operator, Fn> { template - requires std::is_invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); + }; + + using result_type = std::invoke_result_t; + + template TObserver> + using observer_strategy = take_while_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/throttle.hpp b/src/rpp/rpp/operators/throttle.hpp index 2decc7234..ae284c096 100644 --- a/src/rpp/rpp/operators/throttle.hpp +++ b/src/rpp/rpp/operators/throttle.hpp @@ -51,10 +51,16 @@ struct throttle_observer_strategy }; template -struct throttle_t : public operators::details::operator_observable_strategy_different_types, rpp::schedulers::duration> +struct throttle_t final : public operators::details::lift_operator, rpp::schedulers::duration> { template - using result_value = T; + struct traits + { + using result_type = T; + + template TObserver> + using observer_strategy = throttle_observer_strategy; + }; template using updated_disposable_strategy = Prev; diff --git a/src/rpp/rpp/operators/window.hpp b/src/rpp/rpp/operators/window.hpp index 30d6d0ef2..75db6c980 100644 --- a/src/rpp/rpp/operators/window.hpp +++ b/src/rpp/rpp/operators/window.hpp @@ -102,10 +102,16 @@ class window_observer_strategy mutable size_t m_items_in_current_window = m_window_size; }; -struct window_t : public operators::details::operator_observable_strategy_different_types, size_t> +struct window_t final : public operators::details::lift_operator { template - using result_value = window_observable; + struct traits + { + using result_type = window_observable; + + template TObserver> + using observer_strategy = window_observer_strategy; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/window_toggle.hpp b/src/rpp/rpp/operators/window_toggle.hpp index 72e64491b..d9e93d319 100644 --- a/src/rpp/rpp/operators/window_toggle.hpp +++ b/src/rpp/rpp/operators/window_toggle.hpp @@ -185,13 +185,16 @@ class window_toggle_observer_strategy template requires rpp::constraint::observable>> -struct window_toggle_t //: public operators::details::operator_observable_strategy +struct window_toggle_t { RPP_NO_UNIQUE_ADDRESS TOpeningsObservable openings; RPP_NO_UNIQUE_ADDRESS TClosingsSelectorFn closings_selector; template - using result_value = rpp::window_toggle_observable; + struct traits + { + using result_type = rpp::window_toggle_observable; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; diff --git a/src/rpp/rpp/operators/with_latest_from.hpp b/src/rpp/rpp/operators/with_latest_from.hpp index 94900b5fa..cad74c015 100644 --- a/src/rpp/rpp/operators/with_latest_from.hpp +++ b/src/rpp/rpp/operators/with_latest_from.hpp @@ -131,8 +131,15 @@ struct with_latest_from_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - requires std::invocable...> - using result_value = std::invoke_result_t...>; + struct traits + { + struct requirements + { + static_assert(std::invocable...>, "TSelector is not invocable with T and types of rest observables"); + }; + + using result_type = std::invoke_result_t...>; + }; template using updated_disposable_strategy = rpp::details::observables::fixed_disposable_strategy_selector<1>; From 08dc49ec45bcd57b55d2b14ef3a97ef8847d6da1 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 00:25:44 +0300 Subject: [PATCH 04/19] compile fixes --- src/rpp/rpp/operators/take_while.hpp | 2 +- src/tests/utils/copy_count_tracker.hpp | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index a0e68ea75..43ce10a59 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -54,7 +54,7 @@ struct take_while_t final : public operators::details::lift_operator, "Fn is not invocable with T returning bool"); }; - using result_type = std::invoke_result_t; + using result_type = T; template TObserver> using observer_strategy = take_while_observer_strategy; diff --git a/src/tests/utils/copy_count_tracker.hpp b/src/tests/utils/copy_count_tracker.hpp index f02108bef..eedf8f1e1 100644 --- a/src/tests/utils/copy_count_tracker.hpp +++ b/src/tests/utils/copy_count_tracker.hpp @@ -117,16 +117,16 @@ class copy_count_tracker std::shared_ptr _state; }; -// namespace std -// { -// // Make copy_count_tracker hashable for distinct operator -// template<> -// struct hash -// { -// size_t operator()(const copy_count_tracker& tracker) const noexcept -// { -// return std::hash{}(tracker.get_copy_count()) -// ^ (std::hash{}(tracker.get_move_count()) << 1); -// } -// }; -// } +namespace std +{ +// Make copy_count_tracker hashable for distinct operator +template<> +struct hash +{ + size_t operator()(const copy_count_tracker& tracker) const noexcept + { + return std::hash{}(tracker.get_copy_count()) + ^ (std::hash{}(tracker.get_move_count()) << 1); + } +}; +} From 377444deda123c1965608fe55af4e66a81a5373a Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 10:13:38 +0300 Subject: [PATCH 05/19] adapt tap --- src/rpp/rpp/operators/tap.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/rpp/rpp/operators/tap.hpp b/src/rpp/rpp/operators/tap.hpp index 17b44619f..68b82dd25 100644 --- a/src/rpp/rpp/operators/tap.hpp +++ b/src/rpp/rpp/operators/tap.hpp @@ -59,13 +59,23 @@ template< rpp::constraint::decayed_type OnNext, rpp::constraint::decayed_type OnError, rpp::constraint::decayed_type OnCompleted> -struct tap_t : public operators::details::operator_observable_strategy +struct tap_t : public operators::details::lift_operator, OnNext, OnError, OnCompleted> { - using operators::details::operator_observable_strategy::operator_observable_strategy; + using operators::details::lift_operator, OnNext, OnError, OnCompleted>::lift_operator; template - requires rpp::constraint::invocable_r_v - using result_value = T; + struct traits + { + struct requirements + { + static_assert(rpp::constraint::invocable_r_v, "OnNext is not invocable with T"); + }; + + using result_type = T; + + template TObserver> + using observer_strategy = tap_observer_strategy; + }; template using updated_disposable_strategy = Prev; From 92654dc6418e9022c5f37f995374d601807d62c4 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:08:01 +0300 Subject: [PATCH 06/19] simplify --- src/rpp/rpp/observables/fwd.hpp | 14 +++++--------- src/rpp/rpp/operators/combine_latest.hpp | 5 +---- src/rpp/rpp/operators/concat.hpp | 13 +++++-------- src/rpp/rpp/operators/distinct.hpp | 5 +---- src/rpp/rpp/operators/distinct_until_changed.hpp | 5 +---- src/rpp/rpp/operators/filter.hpp | 5 +---- src/rpp/rpp/operators/group_by.hpp | 13 +++++-------- src/rpp/rpp/operators/map.hpp | 5 +---- src/rpp/rpp/operators/merge.hpp | 10 ++-------- src/rpp/rpp/operators/reduce.hpp | 10 ++-------- src/rpp/rpp/operators/scan.hpp | 12 +++--------- src/rpp/rpp/operators/switch_on_next.hpp | 9 +++------ src/rpp/rpp/operators/take_while.hpp | 5 +---- src/rpp/rpp/operators/tap.hpp | 5 +---- src/rpp/rpp/operators/with_latest_from.hpp | 5 +---- 15 files changed, 33 insertions(+), 88 deletions(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 299b83abe..947c10531 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -91,11 +91,7 @@ concept operator_observable_transform = requires(const Op& op, TObs obs) }; template -concept operator_base = requires(const Op& op) { - typename std::decay_t::template traits; - typename std::decay_t::template traits::result_type; - requires details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; -}; +concept operator_base = requires(const Op& op) { typename std::decay_t::template traits; } && details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; template concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer, const observable_chain_strategy>& chain) @@ -116,12 +112,12 @@ concept operator_lift_with_disposable_strategy = operator_base && requ }; template -concept operator_requirements_satisfied = (!(requires {typename std::decay_t::template traits::requirements; }) || std::is_destructible_v::template traits::requirements>); +concept operator_requirements_satisfied = requires { typename std::decay_t::template traits::result_type; }; template -concept operator_chain = operator_base - && operator_requirements_satisfied - && (operator_subscribe || operator_lift || operator_lift_with_disposable_strategy); +concept operator_chain = operator_base, Type> + && operator_requirements_satisfied, Type> + && (operator_subscribe, Type> || operator_lift, Type> || operator_lift_with_disposable_strategy, Type, DisposableStrategy>); template concept observables_of_same_type = rpp::constraint::observable && diff --git a/src/rpp/rpp/operators/combine_latest.hpp b/src/rpp/rpp/operators/combine_latest.hpp index d82b0112d..ce090dd37 100644 --- a/src/rpp/rpp/operators/combine_latest.hpp +++ b/src/rpp/rpp/operators/combine_latest.hpp @@ -105,10 +105,7 @@ struct combine_latest_t template struct traits { - struct requirements - { - static_assert(std::invocable...>, "Selector is not callable with passed T type"); - }; + static_assert(std::invocable...>, "Selector is not callable with passed T type"); using result_type = std::invoke_result_t...>; }; diff --git a/src/rpp/rpp/operators/concat.hpp b/src/rpp/rpp/operators/concat.hpp index 1de6f6f42..afffb4780 100644 --- a/src/rpp/rpp/operators/concat.hpp +++ b/src/rpp/rpp/operators/concat.hpp @@ -71,7 +71,7 @@ class concat_state_t final : public rpp::refcount_disposable { if (handle_observable_impl(observable, refcounted)) return; - + drain(refcounted); } @@ -168,12 +168,12 @@ struct concat_observer_strategy : public concat_observer_strategy_base - void on_next(T&& v) const - { + void on_next(T&& v) const + { ConcatStage current = ConcatStage::None; if (base::state->stage().compare_exchange_strong(current, ConcatStage::Draining, std::memory_order::seq_cst)) base::state->handle_observable(std::forward(v), base::state->add_ref()); - else + else base::state->get_queue()->push(std::forward(v)); } @@ -200,10 +200,7 @@ struct concat_t final : public operators::details::lift_operator template struct traits { - struct requirements - { - static_assert(rpp::constraint::observable, "T is not observable"); - }; + static_assert(rpp::constraint::observable, "T is not observable"); using result_type = rpp::utils::extract_observable_type_t; diff --git a/src/rpp/rpp/operators/distinct.hpp b/src/rpp/rpp/operators/distinct.hpp index e762a6490..7e8ad94f8 100644 --- a/src/rpp/rpp/operators/distinct.hpp +++ b/src/rpp/rpp/operators/distinct.hpp @@ -52,10 +52,7 @@ struct distinct_t final : public operators::details::lift_operator template struct traits { - struct requirements - { - static_assert(rpp::constraint::hashable, "T is not hashable"); - }; + static_assert(rpp::constraint::hashable, "T is not hashable"); using result_type = T; diff --git a/src/rpp/rpp/operators/distinct_until_changed.hpp b/src/rpp/rpp/operators/distinct_until_changed.hpp index 5e36c66b9..b039ffd14 100644 --- a/src/rpp/rpp/operators/distinct_until_changed.hpp +++ b/src/rpp/rpp/operators/distinct_until_changed.hpp @@ -53,10 +53,7 @@ struct distinct_until_changed_t : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(rpp::constraint::invocable_r_v, "EqualityFn is not invocable with T and T returning bool"); - }; + static_assert(rpp::constraint::invocable_r_v, "EqualityFn is not invocable with T and T returning bool"); using result_type = T; diff --git a/src/rpp/rpp/operators/filter.hpp b/src/rpp/rpp/operators/filter.hpp index b902e9945..bc7d8f345 100644 --- a/src/rpp/rpp/operators/filter.hpp +++ b/src/rpp/rpp/operators/filter.hpp @@ -49,10 +49,7 @@ struct filter_t final : public operators::details::lift_operator, F template struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); - }; + static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); using result_type = T; diff --git a/src/rpp/rpp/operators/group_by.hpp b/src/rpp/rpp/operators/group_by.hpp index 10b827059..dd627a4a1 100644 --- a/src/rpp/rpp/operators/group_by.hpp +++ b/src/rpp/rpp/operators/group_by.hpp @@ -121,7 +121,7 @@ struct group_by_observer_strategy const subject_observer* deduce_observer(const rpp::constraint::observer auto& obs, const TT& val) const { const auto key = key_selector(utils::as_const(val)); - + if (const auto itr = key_to_observer.find(key); itr != key_to_observer.cend()) return &itr->second; @@ -165,16 +165,13 @@ template, KeySelector, ValueSelector, KeyComparator> { using operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator>::lift_operator; - + template struct traits { - struct requirements - { - static_assert(std::invocable, "KeySelector is not invocacble with T"); - static_assert(std::invocable, "ValueSelector is not invocable with T"); - static_assert(std::strict_weak_order, rpp::utils::decayed_invoke_result_t>, "KeyComparator is not invocable with result of KeySelector"); - }; + static_assert(std::invocable, "KeySelector is not invocacble with T"); + static_assert(std::invocable, "ValueSelector is not invocable with T"); + static_assert(std::strict_weak_order, rpp::utils::decayed_invoke_result_t>, "KeyComparator is not invocable with result of KeySelector"); using result_type = grouped_observable, rpp::utils::decayed_invoke_result_t, group_by_observable_strategy>>; diff --git a/src/rpp/rpp/operators/map.hpp b/src/rpp/rpp/operators/map.hpp index a7edaedd4..505f04303 100644 --- a/src/rpp/rpp/operators/map.hpp +++ b/src/rpp/rpp/operators/map.hpp @@ -48,10 +48,7 @@ struct map_t final : public operators::details::lift_operator, Fn> template struct traits { - struct requirements - { - static_assert(std::invocable, "Fn is not invocable with T"); - }; + static_assert(std::invocable, "Fn is not invocable with T"); using result_type = std::invoke_result_t; diff --git a/src/rpp/rpp/operators/merge.hpp b/src/rpp/rpp/operators/merge.hpp index a6091b278..b29f9e785 100644 --- a/src/rpp/rpp/operators/merge.hpp +++ b/src/rpp/rpp/operators/merge.hpp @@ -135,10 +135,7 @@ struct merge_t template struct traits { - struct requirements - { - static_assert(rpp::constraint::observable, "T is not observable"); - }; + static_assert(rpp::constraint::observable, "T is not observable"); using result_type = rpp::utils::extract_observable_type_t; }; @@ -166,10 +163,7 @@ struct merge_with_t template struct traits { - struct requirements - { - static_assert((std::same_as> && ...), "T is not same as values of other observables"); - }; + static_assert((std::same_as> && ...), "T is not same as values of other observables"); using result_type = T; }; diff --git a/src/rpp/rpp/operators/reduce.hpp b/src/rpp/rpp/operators/reduce.hpp index 53c5a0c5e..c16c632b0 100644 --- a/src/rpp/rpp/operators/reduce.hpp +++ b/src/rpp/rpp/operators/reduce.hpp @@ -54,10 +54,7 @@ struct reduce_t final : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); - }; + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); using result_type = Seed; @@ -107,10 +104,7 @@ struct reduce_no_seed_t final : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); - }; + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); using result_type = T; diff --git a/src/rpp/rpp/operators/scan.hpp b/src/rpp/rpp/operators/scan.hpp index a85dd845f..e6e8657e0 100644 --- a/src/rpp/rpp/operators/scan.hpp +++ b/src/rpp/rpp/operators/scan.hpp @@ -55,14 +55,11 @@ template, InitialValue, Fn> { using operators::details::lift_operator, InitialValue, Fn>::lift_operator; - + template struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); - }; + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); using result_type = InitialValue; @@ -111,10 +108,7 @@ struct scan_no_seed_t final : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); - }; + static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); using result_type = T; diff --git a/src/rpp/rpp/operators/switch_on_next.hpp b/src/rpp/rpp/operators/switch_on_next.hpp index 3112b977e..974058bc0 100644 --- a/src/rpp/rpp/operators/switch_on_next.hpp +++ b/src/rpp/rpp/operators/switch_on_next.hpp @@ -89,7 +89,7 @@ class switch_on_next_observer_strategy using preferred_disposable_strategy = rpp::details::observers::none_disposable_strategy; switch_on_next_observer_strategy(TObserver&& obs) - : m_state{init_state(std::move(obs))} + : m_state{init_state(std::move(obs))} { } @@ -127,7 +127,7 @@ class switch_on_next_observer_strategy ptr->get_observer()->set_upstream(d.as_weak()); return ptr; } - + private: std::shared_ptr> m_state; rpp::composite_disposable_wrapper m_this_refcount = m_state->add_ref(); @@ -139,10 +139,7 @@ struct switch_on_next_t final : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(rpp::constraint::observable, "T is not observable"); - }; + static_assert(rpp::constraint::observable, "T is not observable"); using result_type = rpp::utils::extract_observable_type_t; diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index 43ce10a59..ed010423f 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -49,10 +49,7 @@ struct take_while_t final : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); - }; + static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); using result_type = T; diff --git a/src/rpp/rpp/operators/tap.hpp b/src/rpp/rpp/operators/tap.hpp index 68b82dd25..c6ccdb5bd 100644 --- a/src/rpp/rpp/operators/tap.hpp +++ b/src/rpp/rpp/operators/tap.hpp @@ -66,10 +66,7 @@ struct tap_t : public operators::details::lift_operator struct traits { - struct requirements - { - static_assert(rpp::constraint::invocable_r_v, "OnNext is not invocable with T"); - }; + static_assert(rpp::constraint::invocable_r_v, "OnNext is not invocable with T"); using result_type = T; diff --git a/src/rpp/rpp/operators/with_latest_from.hpp b/src/rpp/rpp/operators/with_latest_from.hpp index cad74c015..5b9d59d36 100644 --- a/src/rpp/rpp/operators/with_latest_from.hpp +++ b/src/rpp/rpp/operators/with_latest_from.hpp @@ -133,10 +133,7 @@ struct with_latest_from_t template struct traits { - struct requirements - { - static_assert(std::invocable...>, "TSelector is not invocable with T and types of rest observables"); - }; + static_assert(std::invocable...>, "TSelector is not invocable with T and types of rest observables"); using result_type = std::invoke_result_t...>; }; From ce8d8bf10866ad3732e858da5750162b6c9732bb Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:09:04 +0300 Subject: [PATCH 07/19] fake error --- src/examples/rpp/doxygen/map.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/examples/rpp/doxygen/map.cpp b/src/examples/rpp/doxygen/map.cpp index d6bae5bcc..cf7b082cf 100644 --- a/src/examples/rpp/doxygen/map.cpp +++ b/src/examples/rpp/doxygen/map.cpp @@ -10,15 +10,15 @@ int main() // NOLINT(bugprone-exception-escape) { //! [Same type] rpp::source::just(42) - | rpp::operators::map([](int value) { return value + 10; }) - | rpp::operators::subscribe([](int v) { std::cout << v << std::endl; }); + | rpp::operators::map([](std::string value) { return value; }); + // | rpp::operators::subscribe([](int v) { std::cout << v << std::endl; }); // Output: 52 //! [Same type] //! [Changed type] - rpp::source::just(42) - | rpp::operators::map([](int value) { return std::to_string(value) + " VAL"; }) - | rpp::operators::subscribe([](const std::string& v) { std::cout << v << std::endl; }); + rpp::source::just(std::vector{}) + | rpp::operators::distinct(); + // | rpp::operators::subscribe([](const std::string& v) { std::cout << v << std::endl; }); // Output: 42 VAL //! [Changed type] return 0; From f1678125bf861ed9f33ff028939e7c264873a7d9 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:16:45 +0300 Subject: [PATCH 08/19] improve --- src/rpp/rpp/observables/fwd.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 947c10531..8647d1e49 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -112,7 +112,10 @@ concept operator_lift_with_disposable_strategy = operator_base && requ }; template -concept operator_requirements_satisfied = requires { typename std::decay_t::template traits::result_type; }; +concept operator_requirements_satisfied = requires { + typename std::decay_t::template traits{}; // traits can be instantiated if all inner static_asserts are fine + typename std::decay_t::template traits::result_type; +}; template concept operator_chain = operator_base, Type> From 35620f5ea5b8a4754c7ccf8aebbcb197937481ab Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:22:59 +0300 Subject: [PATCH 09/19] fix --- src/rpp/rpp/observables/fwd.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 8647d1e49..3fc581d52 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -113,7 +113,7 @@ concept operator_lift_with_disposable_strategy = operator_base && requ template concept operator_requirements_satisfied = requires { - typename std::decay_t::template traits{}; // traits can be instantiated if all inner static_asserts are fine + std::declval::template traits>(); typename std::decay_t::template traits::result_type; }; From 632ddefd264fb333ce1b6134b0185e63edff442e Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:24:41 +0300 Subject: [PATCH 10/19] fix --- src/rpp/rpp/observables/fwd.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 3fc581d52..98204a7c6 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -113,7 +113,7 @@ concept operator_lift_with_disposable_strategy = operator_base && requ template concept operator_requirements_satisfied = requires { - std::declval::template traits>(); + { typename std::decay_t::template traits{} }; // traits can be instantiated if all inner static_asserts are fine typename std::decay_t::template traits::result_type; }; From 5a3b2083099870ee94ac7e33e6c9ac59f2499fed Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:37:37 +0300 Subject: [PATCH 11/19] rename --- .../rpp/observables/details/chain_strategy.hpp | 2 +- src/rpp/rpp/observables/fwd.hpp | 18 +++++++----------- src/rpp/rpp/observables/observable.hpp | 8 ++++++-- src/rpp/rpp/operators/buffer.hpp | 2 +- src/rpp/rpp/operators/combine_latest.hpp | 2 +- src/rpp/rpp/operators/concat.hpp | 2 +- src/rpp/rpp/operators/debounce.hpp | 2 +- src/rpp/rpp/operators/delay.hpp | 2 +- src/rpp/rpp/operators/details/strategy.hpp | 8 ++++---- src/rpp/rpp/operators/distinct.hpp | 2 +- .../rpp/operators/distinct_until_changed.hpp | 2 +- src/rpp/rpp/operators/filter.hpp | 2 +- src/rpp/rpp/operators/first.hpp | 2 +- src/rpp/rpp/operators/group_by.hpp | 2 +- src/rpp/rpp/operators/last.hpp | 2 +- src/rpp/rpp/operators/map.hpp | 2 +- src/rpp/rpp/operators/merge.hpp | 4 ++-- src/rpp/rpp/operators/reduce.hpp | 4 ++-- src/rpp/rpp/operators/scan.hpp | 4 ++-- src/rpp/rpp/operators/skip.hpp | 2 +- src/rpp/rpp/operators/subscribe_on.hpp | 2 +- src/rpp/rpp/operators/switch_on_next.hpp | 2 +- src/rpp/rpp/operators/take.hpp | 2 +- src/rpp/rpp/operators/take_last.hpp | 12 ++++++------ src/rpp/rpp/operators/take_until.hpp | 6 +++--- src/rpp/rpp/operators/take_while.hpp | 2 +- src/rpp/rpp/operators/tap.hpp | 2 +- src/rpp/rpp/operators/throttle.hpp | 2 +- src/rpp/rpp/operators/window.hpp | 2 +- src/rpp/rpp/operators/window_toggle.hpp | 2 +- src/rpp/rpp/operators/with_latest_from.hpp | 2 +- 31 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/rpp/rpp/observables/details/chain_strategy.hpp b/src/rpp/rpp/observables/details/chain_strategy.hpp index d0087b53b..fb2904a48 100644 --- a/src/rpp/rpp/observables/details/chain_strategy.hpp +++ b/src/rpp/rpp/observables/details/chain_strategy.hpp @@ -23,7 +23,7 @@ class observable_chain_strategy public: using expected_disposable_strategy = details::observables::deduce_updated_disposable_strategy; - using value_type = typename TStrategy::template traits::result_type; + using value_type = typename TStrategy::template operator_traits_for_upstream_type::result_type; observable_chain_strategy(const TStrategy& strategy, const TStrategies&... strategies) : m_strategy(strategy) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 98204a7c6..ac5a6e5b0 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -91,35 +91,29 @@ concept operator_observable_transform = requires(const Op& op, TObs obs) }; template -concept operator_base = requires(const Op& op) { typename std::decay_t::template traits; } && details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; +concept operator_base = requires(const Op& op) { typename std::decay_t::template operator_traits_for_upstream_type; } && details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; template -concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer, const observable_chain_strategy>& chain) +concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer, const observable_chain_strategy>& chain) { {op.subscribe(std::move(observer), chain)}; }; template -concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer) +concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer) { {op.template lift(std::move(observer))} -> rpp::constraint::observer_of_type; }; template -concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template traits::result_type>&& observer) +concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer) { {op.template lift_with_disposable_strategy(std::move(observer))} -> rpp::constraint::observer_of_type; }; -template -concept operator_requirements_satisfied = requires { - { typename std::decay_t::template traits{} }; // traits can be instantiated if all inner static_asserts are fine - typename std::decay_t::template traits::result_type; -}; - template concept operator_chain = operator_base, Type> - && operator_requirements_satisfied, Type> + && requires { typename std::decay_t::template operator_traits_for_upstream_type::result_type; } && (operator_subscribe, Type> || operator_lift, Type> || operator_lift_with_disposable_strategy, Type, DisposableStrategy>); template @@ -127,3 +121,5 @@ concept observables_of_same_type = rpp::constraint::observable && (rpp::constraint::observable && ...) && (std::same_as, rpp::utils::extract_observable_type_t> && ...); } + +#define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) [[maybe_unused]] constexpr auto _ = typename std::decay_t::template operator_traits_for_upstream_type{}; // operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine \ No newline at end of file diff --git a/src/rpp/rpp/observables/observable.hpp b/src/rpp/rpp/observables/observable.hpp index 7cb70412a..c85a8ecbd 100644 --- a/src/rpp/rpp/observables/observable.hpp +++ b/src/rpp/rpp/observables/observable.hpp @@ -313,15 +313,19 @@ class observable template Op> auto operator|(Op&& op) const & { + RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); + static_assert(constraint::operator_chain); - return observable::template traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; + return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; } template Op> auto operator|(Op&& op) && { + RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); + static_assert(constraint::operator_chain); - return observable::template traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; + return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; } template Op> diff --git a/src/rpp/rpp/operators/buffer.hpp b/src/rpp/rpp/operators/buffer.hpp index 05ed88e3e..b44e2acc5 100644 --- a/src/rpp/rpp/operators/buffer.hpp +++ b/src/rpp/rpp/operators/buffer.hpp @@ -67,7 +67,7 @@ class buffer_observer_strategy struct buffer_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = std::vector; diff --git a/src/rpp/rpp/operators/combine_latest.hpp b/src/rpp/rpp/operators/combine_latest.hpp index ce090dd37..6fbf0428a 100644 --- a/src/rpp/rpp/operators/combine_latest.hpp +++ b/src/rpp/rpp/operators/combine_latest.hpp @@ -103,7 +103,7 @@ struct combine_latest_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::invocable...>, "Selector is not callable with passed T type"); diff --git a/src/rpp/rpp/operators/concat.hpp b/src/rpp/rpp/operators/concat.hpp index afffb4780..cf86d57ee 100644 --- a/src/rpp/rpp/operators/concat.hpp +++ b/src/rpp/rpp/operators/concat.hpp @@ -198,7 +198,7 @@ struct concat_observer_strategy : public concat_observer_strategy_base { template - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::observable, "T is not observable"); diff --git a/src/rpp/rpp/operators/debounce.hpp b/src/rpp/rpp/operators/debounce.hpp index 7c256d94c..16bff2fcf 100644 --- a/src/rpp/rpp/operators/debounce.hpp +++ b/src/rpp/rpp/operators/debounce.hpp @@ -156,7 +156,7 @@ template struct debounce_t { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; }; diff --git a/src/rpp/rpp/operators/delay.hpp b/src/rpp/rpp/operators/delay.hpp index 397ead20d..0df077b3e 100644 --- a/src/rpp/rpp/operators/delay.hpp +++ b/src/rpp/rpp/operators/delay.hpp @@ -170,7 +170,7 @@ template struct delay_t { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; }; diff --git a/src/rpp/rpp/operators/details/strategy.hpp b/src/rpp/rpp/operators/details/strategy.hpp index 684a35013..1afe3912c 100644 --- a/src/rpp/rpp/operators/details/strategy.hpp +++ b/src/rpp/rpp/operators/details/strategy.hpp @@ -40,13 +40,13 @@ class lift_operator } private: - template static auto apply(Observer&& observer, const Args&... vals) { - static_assert(rpp::constraint::observer_of_type, typename Operator::template traits::result_type>); - return rpp::observer::template observer_strategy>>{std::forward(observer), vals...}; + static_assert(rpp::constraint::observer_of_type, typename Operator::template operator_traits_for_upstream_type::result_type>); + return rpp::observer::template observer_strategy>>{std::forward(observer), vals...}; } private: diff --git a/src/rpp/rpp/operators/distinct.hpp b/src/rpp/rpp/operators/distinct.hpp index 7e8ad94f8..4169c48f4 100644 --- a/src/rpp/rpp/operators/distinct.hpp +++ b/src/rpp/rpp/operators/distinct.hpp @@ -50,7 +50,7 @@ struct distinct_observer_strategy struct distinct_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::hashable, "T is not hashable"); diff --git a/src/rpp/rpp/operators/distinct_until_changed.hpp b/src/rpp/rpp/operators/distinct_until_changed.hpp index b039ffd14..8a4d9e106 100644 --- a/src/rpp/rpp/operators/distinct_until_changed.hpp +++ b/src/rpp/rpp/operators/distinct_until_changed.hpp @@ -51,7 +51,7 @@ template struct distinct_until_changed_t : public operators::details::lift_operator, EqualityFn> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::invocable_r_v, "EqualityFn is not invocable with T and T returning bool"); diff --git a/src/rpp/rpp/operators/filter.hpp b/src/rpp/rpp/operators/filter.hpp index bc7d8f345..fa22b088e 100644 --- a/src/rpp/rpp/operators/filter.hpp +++ b/src/rpp/rpp/operators/filter.hpp @@ -47,7 +47,7 @@ template struct filter_t final : public operators::details::lift_operator, Fn> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); diff --git a/src/rpp/rpp/operators/first.hpp b/src/rpp/rpp/operators/first.hpp index f9743b9ad..5a4c18e1d 100644 --- a/src/rpp/rpp/operators/first.hpp +++ b/src/rpp/rpp/operators/first.hpp @@ -46,7 +46,7 @@ struct first_observer_strategy struct first_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; diff --git a/src/rpp/rpp/operators/group_by.hpp b/src/rpp/rpp/operators/group_by.hpp index dd627a4a1..52bf1f7dd 100644 --- a/src/rpp/rpp/operators/group_by.hpp +++ b/src/rpp/rpp/operators/group_by.hpp @@ -167,7 +167,7 @@ struct group_by_t final : public operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator>::lift_operator; template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::invocable, "KeySelector is not invocacble with T"); static_assert(std::invocable, "ValueSelector is not invocable with T"); diff --git a/src/rpp/rpp/operators/last.hpp b/src/rpp/rpp/operators/last.hpp index 503237cf8..8a520e7a0 100644 --- a/src/rpp/rpp/operators/last.hpp +++ b/src/rpp/rpp/operators/last.hpp @@ -54,7 +54,7 @@ struct last_observer_strategy struct last_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; diff --git a/src/rpp/rpp/operators/map.hpp b/src/rpp/rpp/operators/map.hpp index 505f04303..cfb9fb0a7 100644 --- a/src/rpp/rpp/operators/map.hpp +++ b/src/rpp/rpp/operators/map.hpp @@ -46,7 +46,7 @@ template struct map_t final : public operators::details::lift_operator, Fn> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::invocable, "Fn is not invocable with T"); diff --git a/src/rpp/rpp/operators/merge.hpp b/src/rpp/rpp/operators/merge.hpp index b29f9e785..31d04e7d5 100644 --- a/src/rpp/rpp/operators/merge.hpp +++ b/src/rpp/rpp/operators/merge.hpp @@ -133,7 +133,7 @@ class merge_observer_strategy final : public merge_observer_base_strategy - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::observable, "T is not observable"); @@ -161,7 +161,7 @@ struct merge_with_t RPP_NO_UNIQUE_ADDRESS rpp::utils::tuple observables{}; template - struct traits + struct operator_traits_for_upstream_type { static_assert((std::same_as> && ...), "T is not same as values of other observables"); diff --git a/src/rpp/rpp/operators/reduce.hpp b/src/rpp/rpp/operators/reduce.hpp index c16c632b0..5b7cbb4c8 100644 --- a/src/rpp/rpp/operators/reduce.hpp +++ b/src/rpp/rpp/operators/reduce.hpp @@ -52,7 +52,7 @@ struct reduce_t final : public operators::details::lift_operator, Seed, Accumulator>::lift_operator; template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); @@ -102,7 +102,7 @@ template struct reduce_no_seed_t final : public operators::details::lift_operator, Accumulator> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); diff --git a/src/rpp/rpp/operators/scan.hpp b/src/rpp/rpp/operators/scan.hpp index e6e8657e0..873d6b323 100644 --- a/src/rpp/rpp/operators/scan.hpp +++ b/src/rpp/rpp/operators/scan.hpp @@ -57,7 +57,7 @@ struct scan_t final : public operators::details::lift_operator, InitialValue, Fn>::lift_operator; template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); @@ -106,7 +106,7 @@ template struct scan_no_seed_t final : public operators::details::lift_operator, Fn> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); diff --git a/src/rpp/rpp/operators/skip.hpp b/src/rpp/rpp/operators/skip.hpp index c5f0a78e3..6f5bdb81d 100644 --- a/src/rpp/rpp/operators/skip.hpp +++ b/src/rpp/rpp/operators/skip.hpp @@ -48,7 +48,7 @@ struct skip_observer_strategy struct skip_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; diff --git a/src/rpp/rpp/operators/subscribe_on.hpp b/src/rpp/rpp/operators/subscribe_on.hpp index e68b3af27..9bb01fab0 100644 --- a/src/rpp/rpp/operators/subscribe_on.hpp +++ b/src/rpp/rpp/operators/subscribe_on.hpp @@ -36,7 +36,7 @@ template struct subscribe_on_t { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; }; diff --git a/src/rpp/rpp/operators/switch_on_next.hpp b/src/rpp/rpp/operators/switch_on_next.hpp index 974058bc0..e6fcd9188 100644 --- a/src/rpp/rpp/operators/switch_on_next.hpp +++ b/src/rpp/rpp/operators/switch_on_next.hpp @@ -137,7 +137,7 @@ class switch_on_next_observer_strategy struct switch_on_next_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::observable, "T is not observable"); diff --git a/src/rpp/rpp/operators/take.hpp b/src/rpp/rpp/operators/take.hpp index c2b54f797..8b5548de0 100644 --- a/src/rpp/rpp/operators/take.hpp +++ b/src/rpp/rpp/operators/take.hpp @@ -52,7 +52,7 @@ struct take_observer_strategy struct take_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; diff --git a/src/rpp/rpp/operators/take_last.hpp b/src/rpp/rpp/operators/take_last.hpp index 781edcb43..dfffe89c8 100644 --- a/src/rpp/rpp/operators/take_last.hpp +++ b/src/rpp/rpp/operators/take_last.hpp @@ -52,15 +52,15 @@ class take_last_observer_strategy void on_error(const std::exception_ptr& err) const { m_observer.on_error(err); } - void on_completed() const - { + void on_completed() const + { for (size_t i =0; i < m_data.size(); ++i) { m_observer.on_next(std::move(m_data[m_current_end])); m_current_end = get_next(m_current_end); } - m_observer.on_completed(); + m_observer.on_completed(); } void set_upstream(const disposable_wrapper& d) { m_observer.set_upstream(d); } @@ -83,7 +83,7 @@ class take_last_observer_strategy struct take_last_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; @@ -100,7 +100,7 @@ namespace rpp::operators { /** * @brief Emit only last `count` items provided by observable, then send `on_completed` - * + * * @marble take_last { source observable : +--1-2-3-4-5-6-| @@ -111,7 +111,7 @@ namespace rpp::operators * * @param count amount of last items to be emitted * @warning #include - * + * * @par Example * @snippet take_last.cpp take_last * diff --git a/src/rpp/rpp/operators/take_until.hpp b/src/rpp/rpp/operators/take_until.hpp index f60028986..3534fc490 100644 --- a/src/rpp/rpp/operators/take_until.hpp +++ b/src/rpp/rpp/operators/take_until.hpp @@ -46,13 +46,13 @@ struct take_until_observer_strategy_base std::shared_ptr> state; - void on_error(const std::exception_ptr& err) const + void on_error(const std::exception_ptr& err) const { state->dispose(); state->get_observer()->on_error(err); } - void on_completed() const + void on_completed() const { state->dispose(); state->get_observer()->on_completed(); @@ -90,7 +90,7 @@ struct take_until_t RPP_NO_UNIQUE_ADDRESS TObservable observable{}; template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; }; diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index ed010423f..5903ed9d5 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -47,7 +47,7 @@ template struct take_while_t final : public operators::details::lift_operator, Fn> { template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); diff --git a/src/rpp/rpp/operators/tap.hpp b/src/rpp/rpp/operators/tap.hpp index c6ccdb5bd..62610e596 100644 --- a/src/rpp/rpp/operators/tap.hpp +++ b/src/rpp/rpp/operators/tap.hpp @@ -64,7 +64,7 @@ struct tap_t : public operators::details::lift_operator, OnNext, OnError, OnCompleted>::lift_operator; template - struct traits + struct operator_traits_for_upstream_type { static_assert(rpp::constraint::invocable_r_v, "OnNext is not invocable with T"); diff --git a/src/rpp/rpp/operators/throttle.hpp b/src/rpp/rpp/operators/throttle.hpp index ae284c096..808b83f21 100644 --- a/src/rpp/rpp/operators/throttle.hpp +++ b/src/rpp/rpp/operators/throttle.hpp @@ -54,7 +54,7 @@ template struct throttle_t final : public operators::details::lift_operator, rpp::schedulers::duration> { template - struct traits + struct operator_traits_for_upstream_type { using result_type = T; diff --git a/src/rpp/rpp/operators/window.hpp b/src/rpp/rpp/operators/window.hpp index 75db6c980..a43398e7d 100644 --- a/src/rpp/rpp/operators/window.hpp +++ b/src/rpp/rpp/operators/window.hpp @@ -105,7 +105,7 @@ class window_observer_strategy struct window_t final : public operators::details::lift_operator { template - struct traits + struct operator_traits_for_upstream_type { using result_type = window_observable; diff --git a/src/rpp/rpp/operators/window_toggle.hpp b/src/rpp/rpp/operators/window_toggle.hpp index d9e93d319..ba1bb2b87 100644 --- a/src/rpp/rpp/operators/window_toggle.hpp +++ b/src/rpp/rpp/operators/window_toggle.hpp @@ -191,7 +191,7 @@ struct window_toggle_t RPP_NO_UNIQUE_ADDRESS TClosingsSelectorFn closings_selector; template - struct traits + struct operator_traits_for_upstream_type { using result_type = rpp::window_toggle_observable; }; diff --git a/src/rpp/rpp/operators/with_latest_from.hpp b/src/rpp/rpp/operators/with_latest_from.hpp index 5b9d59d36..e5c93ebf6 100644 --- a/src/rpp/rpp/operators/with_latest_from.hpp +++ b/src/rpp/rpp/operators/with_latest_from.hpp @@ -131,7 +131,7 @@ struct with_latest_from_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - struct traits + struct operator_traits_for_upstream_type { static_assert(std::invocable...>, "TSelector is not invocable with T and types of rest observables"); From 45740e67da5f710b733bbf581e82d1a352193070 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 11:44:56 +0300 Subject: [PATCH 12/19] fix --- src/rpp/rpp/observables/observable.hpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/rpp/rpp/observables/observable.hpp b/src/rpp/rpp/observables/observable.hpp index c85a8ecbd..3b49249bf 100644 --- a/src/rpp/rpp/observables/observable.hpp +++ b/src/rpp/rpp/observables/observable.hpp @@ -314,18 +314,14 @@ class observable auto operator|(Op&& op) const & { RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); - - static_assert(constraint::operator_chain); - return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; + return inner_make_chain_operator(std::forward(op)); } template Op> auto operator|(Op&& op) && { RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); - - static_assert(constraint::operator_chain); - return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; + return std::move(*this).inner_make_chain_operator(std::forward(op)); } template Op> @@ -364,6 +360,19 @@ class observable return std::move(*this) | std::forward(op); } +private: + template Op> + auto inner_make_chain_operator(Op&& op) const & + { + return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; + } + + template Op> + auto inner_make_chain_operator(Op&& op) && + { + return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; + } + private: RPP_NO_UNIQUE_ADDRESS Strategy m_strategy; }; From a7c20afa0cc0bce9d027e7ff07e61e9a010758cd Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 12:30:27 +0300 Subject: [PATCH 13/19] one more approach --- src/rpp/rpp/observables/fwd.hpp | 6 +++++- src/rpp/rpp/observables/observable.hpp | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index ac5a6e5b0..7bfeaf119 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -122,4 +122,8 @@ concept observables_of_same_type = rpp::constraint::observable && (std::same_as, rpp::utils::extract_observable_type_t> && ...); } -#define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) [[maybe_unused]] constexpr auto _ = typename std::decay_t::template operator_traits_for_upstream_type{}; // operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine \ No newline at end of file +#define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ + /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ + if constexpr (!(requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; })) \ + static_assert(requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }); \ + else \ No newline at end of file diff --git a/src/rpp/rpp/observables/observable.hpp b/src/rpp/rpp/observables/observable.hpp index 3b49249bf..5e2fbe2ca 100644 --- a/src/rpp/rpp/observables/observable.hpp +++ b/src/rpp/rpp/observables/observable.hpp @@ -313,14 +313,14 @@ class observable template Op> auto operator|(Op&& op) const & { - RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); + RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) return inner_make_chain_operator(std::forward(op)); } template Op> auto operator|(Op&& op) && { - RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type); + RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) return std::move(*this).inner_make_chain_operator(std::forward(op)); } From 51ca2058c5bbbc10d2d2335f77b69e9a12d8bc76 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 12:32:24 +0300 Subject: [PATCH 14/19] simplify --- src/rpp/rpp/observables/fwd.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 7bfeaf119..7160b7cde 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -122,8 +122,8 @@ concept observables_of_same_type = rpp::constraint::observable && (std::same_as, rpp::utils::extract_observable_type_t> && ...); } -#define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ - /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ - if constexpr (!(requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; })) \ - static_assert(requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }); \ - else \ No newline at end of file +#define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ + /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ + constexpr auto operator_asserts_satisfied = requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }; \ + static_assert(operator_asserts_satisfied); \ + if constexpr (operator_asserts_satisfied) \ No newline at end of file From 163ee8314b53d6f868c3433db68dbbc81438522f Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 14:59:05 +0300 Subject: [PATCH 15/19] fix --- src/rpp/rpp/observables/fwd.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 7160b7cde..502ecad2b 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -124,6 +124,5 @@ concept observables_of_same_type = rpp::constraint::observable && #define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ - constexpr auto operator_asserts_satisfied = requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }; \ - static_assert(operator_asserts_satisfied); \ - if constexpr (operator_asserts_satisfied) \ No newline at end of file + constexpr auto operator_asserts_satisfied = requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }; \ + if constexpr (operator_asserts_satisfied) From 564fab21221063a4462425eb8a3aab47934115ef Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 14:59:46 +0300 Subject: [PATCH 16/19] fix --- src/rpp/rpp/observables/fwd.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 502ecad2b..7923db633 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -124,5 +124,4 @@ concept observables_of_same_type = rpp::constraint::observable && #define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ - constexpr auto operator_asserts_satisfied = requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }; \ - if constexpr (operator_asserts_satisfied) + if constexpr (requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }) From 46a93feb9f356d155b60331ce6fdb1e3d74a21ea Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 16:15:12 +0300 Subject: [PATCH 17/19] rename --- src/rpp/rpp/observables/details/chain_strategy.hpp | 2 +- src/rpp/rpp/observables/fwd.hpp | 14 +++++++------- src/rpp/rpp/observables/observable.hpp | 4 ++-- src/rpp/rpp/operators/buffer.hpp | 2 +- src/rpp/rpp/operators/combine_latest.hpp | 2 +- src/rpp/rpp/operators/concat.hpp | 2 +- src/rpp/rpp/operators/debounce.hpp | 2 +- src/rpp/rpp/operators/delay.hpp | 2 +- src/rpp/rpp/operators/details/strategy.hpp | 4 ++-- src/rpp/rpp/operators/distinct.hpp | 2 +- src/rpp/rpp/operators/distinct_until_changed.hpp | 2 +- src/rpp/rpp/operators/filter.hpp | 2 +- src/rpp/rpp/operators/first.hpp | 2 +- src/rpp/rpp/operators/group_by.hpp | 2 +- src/rpp/rpp/operators/last.hpp | 2 +- src/rpp/rpp/operators/map.hpp | 2 +- src/rpp/rpp/operators/merge.hpp | 4 ++-- src/rpp/rpp/operators/reduce.hpp | 4 ++-- src/rpp/rpp/operators/scan.hpp | 4 ++-- src/rpp/rpp/operators/skip.hpp | 2 +- src/rpp/rpp/operators/subscribe_on.hpp | 2 +- src/rpp/rpp/operators/switch_on_next.hpp | 2 +- src/rpp/rpp/operators/take.hpp | 2 +- src/rpp/rpp/operators/take_last.hpp | 2 +- src/rpp/rpp/operators/take_until.hpp | 2 +- src/rpp/rpp/operators/take_while.hpp | 2 +- src/rpp/rpp/operators/tap.hpp | 2 +- src/rpp/rpp/operators/throttle.hpp | 2 +- src/rpp/rpp/operators/window.hpp | 2 +- src/rpp/rpp/operators/window_toggle.hpp | 2 +- src/rpp/rpp/operators/with_latest_from.hpp | 2 +- 31 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/rpp/rpp/observables/details/chain_strategy.hpp b/src/rpp/rpp/observables/details/chain_strategy.hpp index fb2904a48..c03fbf2b6 100644 --- a/src/rpp/rpp/observables/details/chain_strategy.hpp +++ b/src/rpp/rpp/observables/details/chain_strategy.hpp @@ -23,7 +23,7 @@ class observable_chain_strategy public: using expected_disposable_strategy = details::observables::deduce_updated_disposable_strategy; - using value_type = typename TStrategy::template operator_traits_for_upstream_type::result_type; + using value_type = typename TStrategy::template operator_traits::result_type; observable_chain_strategy(const TStrategy& strategy, const TStrategies&... strategies) : m_strategy(strategy) diff --git a/src/rpp/rpp/observables/fwd.hpp b/src/rpp/rpp/observables/fwd.hpp index 7923db633..b6e33876e 100644 --- a/src/rpp/rpp/observables/fwd.hpp +++ b/src/rpp/rpp/observables/fwd.hpp @@ -91,29 +91,29 @@ concept operator_observable_transform = requires(const Op& op, TObs obs) }; template -concept operator_base = requires(const Op& op) { typename std::decay_t::template operator_traits_for_upstream_type; } && details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; +concept operator_base = requires(const Op& op) { typename std::decay_t::template operator_traits; } && details::observables::constraint::disposable_strategy, typename observable_chain_strategy>::expected_disposable_strategy>>; template -concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer, const observable_chain_strategy>& chain) +concept operator_subscribe = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits::result_type>&& observer, const observable_chain_strategy>& chain) { {op.subscribe(std::move(observer), chain)}; }; template -concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer) +concept operator_lift = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits::result_type>&& observer) { {op.template lift(std::move(observer))} -> rpp::constraint::observer_of_type; }; template -concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits_for_upstream_type::result_type>&& observer) +concept operator_lift_with_disposable_strategy = operator_base && requires(const Op& op, rpp::details::observers::fake_observer::template operator_traits::result_type>&& observer) { {op.template lift_with_disposable_strategy(std::move(observer))} -> rpp::constraint::observer_of_type; }; template concept operator_chain = operator_base, Type> - && requires { typename std::decay_t::template operator_traits_for_upstream_type::result_type; } + && requires { typename std::decay_t::template operator_traits::result_type; } && (operator_subscribe, Type> || operator_lift, Type> || operator_lift_with_disposable_strategy, Type, DisposableStrategy>); template @@ -123,5 +123,5 @@ concept observables_of_same_type = rpp::constraint::observable && } #define RPP_CHECK_IF_TRAIT_ASSERTS_SATISFIED(Op, Type) \ - /* operator_traits_for_upstream_type can be instantiated if all inner static_asserts are fine*/ \ - if constexpr (requires { { typename std::decay_t::template operator_traits_for_upstream_type{}}; }) + /* operator_traits can be instantiated if all inner static_asserts are fine*/ \ + if constexpr (requires { { typename std::decay_t::template operator_traits{}}; }) diff --git a/src/rpp/rpp/observables/observable.hpp b/src/rpp/rpp/observables/observable.hpp index 5e2fbe2ca..309f9c785 100644 --- a/src/rpp/rpp/observables/observable.hpp +++ b/src/rpp/rpp/observables/observable.hpp @@ -364,13 +364,13 @@ class observable template Op> auto inner_make_chain_operator(Op&& op) const & { - return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; + return observable::template operator_traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), m_strategy}; } template Op> auto inner_make_chain_operator(Op&& op) && { - return observable::template operator_traits_for_upstream_type::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; + return observable::template operator_traits::result_type, make_chain_observable_t, Strategy>>{std::forward(op), std::move(m_strategy)}; } private: diff --git a/src/rpp/rpp/operators/buffer.hpp b/src/rpp/rpp/operators/buffer.hpp index b44e2acc5..c100f17b4 100644 --- a/src/rpp/rpp/operators/buffer.hpp +++ b/src/rpp/rpp/operators/buffer.hpp @@ -67,7 +67,7 @@ class buffer_observer_strategy struct buffer_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = std::vector; diff --git a/src/rpp/rpp/operators/combine_latest.hpp b/src/rpp/rpp/operators/combine_latest.hpp index 6fbf0428a..49b74ae0c 100644 --- a/src/rpp/rpp/operators/combine_latest.hpp +++ b/src/rpp/rpp/operators/combine_latest.hpp @@ -103,7 +103,7 @@ struct combine_latest_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::invocable...>, "Selector is not callable with passed T type"); diff --git a/src/rpp/rpp/operators/concat.hpp b/src/rpp/rpp/operators/concat.hpp index cf86d57ee..5113f886f 100644 --- a/src/rpp/rpp/operators/concat.hpp +++ b/src/rpp/rpp/operators/concat.hpp @@ -198,7 +198,7 @@ struct concat_observer_strategy : public concat_observer_strategy_base { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::observable, "T is not observable"); diff --git a/src/rpp/rpp/operators/debounce.hpp b/src/rpp/rpp/operators/debounce.hpp index 16bff2fcf..6030b1490 100644 --- a/src/rpp/rpp/operators/debounce.hpp +++ b/src/rpp/rpp/operators/debounce.hpp @@ -156,7 +156,7 @@ template struct debounce_t { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; }; diff --git a/src/rpp/rpp/operators/delay.hpp b/src/rpp/rpp/operators/delay.hpp index 0df077b3e..61b22ee7b 100644 --- a/src/rpp/rpp/operators/delay.hpp +++ b/src/rpp/rpp/operators/delay.hpp @@ -170,7 +170,7 @@ template struct delay_t { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; }; diff --git a/src/rpp/rpp/operators/details/strategy.hpp b/src/rpp/rpp/operators/details/strategy.hpp index 1afe3912c..13778739d 100644 --- a/src/rpp/rpp/operators/details/strategy.hpp +++ b/src/rpp/rpp/operators/details/strategy.hpp @@ -45,8 +45,8 @@ class lift_operator typename... Args> static auto apply(Observer&& observer, const Args&... vals) { - static_assert(rpp::constraint::observer_of_type, typename Operator::template operator_traits_for_upstream_type::result_type>); - return rpp::observer::template observer_strategy>>{std::forward(observer), vals...}; + static_assert(rpp::constraint::observer_of_type, typename Operator::template operator_traits::result_type>); + return rpp::observer::template observer_strategy>>{std::forward(observer), vals...}; } private: diff --git a/src/rpp/rpp/operators/distinct.hpp b/src/rpp/rpp/operators/distinct.hpp index 4169c48f4..aa51172cf 100644 --- a/src/rpp/rpp/operators/distinct.hpp +++ b/src/rpp/rpp/operators/distinct.hpp @@ -50,7 +50,7 @@ struct distinct_observer_strategy struct distinct_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::hashable, "T is not hashable"); diff --git a/src/rpp/rpp/operators/distinct_until_changed.hpp b/src/rpp/rpp/operators/distinct_until_changed.hpp index 8a4d9e106..5caf9aa6a 100644 --- a/src/rpp/rpp/operators/distinct_until_changed.hpp +++ b/src/rpp/rpp/operators/distinct_until_changed.hpp @@ -51,7 +51,7 @@ template struct distinct_until_changed_t : public operators::details::lift_operator, EqualityFn> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::invocable_r_v, "EqualityFn is not invocable with T and T returning bool"); diff --git a/src/rpp/rpp/operators/filter.hpp b/src/rpp/rpp/operators/filter.hpp index fa22b088e..599a3dc29 100644 --- a/src/rpp/rpp/operators/filter.hpp +++ b/src/rpp/rpp/operators/filter.hpp @@ -47,7 +47,7 @@ template struct filter_t final : public operators::details::lift_operator, Fn> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); diff --git a/src/rpp/rpp/operators/first.hpp b/src/rpp/rpp/operators/first.hpp index 5a4c18e1d..64b78543e 100644 --- a/src/rpp/rpp/operators/first.hpp +++ b/src/rpp/rpp/operators/first.hpp @@ -46,7 +46,7 @@ struct first_observer_strategy struct first_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/group_by.hpp b/src/rpp/rpp/operators/group_by.hpp index 52bf1f7dd..292d8f75b 100644 --- a/src/rpp/rpp/operators/group_by.hpp +++ b/src/rpp/rpp/operators/group_by.hpp @@ -167,7 +167,7 @@ struct group_by_t final : public operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator>::lift_operator; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::invocable, "KeySelector is not invocacble with T"); static_assert(std::invocable, "ValueSelector is not invocable with T"); diff --git a/src/rpp/rpp/operators/last.hpp b/src/rpp/rpp/operators/last.hpp index 8a520e7a0..f74407323 100644 --- a/src/rpp/rpp/operators/last.hpp +++ b/src/rpp/rpp/operators/last.hpp @@ -54,7 +54,7 @@ struct last_observer_strategy struct last_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/map.hpp b/src/rpp/rpp/operators/map.hpp index cfb9fb0a7..6c74266fa 100644 --- a/src/rpp/rpp/operators/map.hpp +++ b/src/rpp/rpp/operators/map.hpp @@ -46,7 +46,7 @@ template struct map_t final : public operators::details::lift_operator, Fn> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::invocable, "Fn is not invocable with T"); diff --git a/src/rpp/rpp/operators/merge.hpp b/src/rpp/rpp/operators/merge.hpp index 31d04e7d5..0491ca8c9 100644 --- a/src/rpp/rpp/operators/merge.hpp +++ b/src/rpp/rpp/operators/merge.hpp @@ -133,7 +133,7 @@ class merge_observer_strategy final : public merge_observer_base_strategy - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::observable, "T is not observable"); @@ -161,7 +161,7 @@ struct merge_with_t RPP_NO_UNIQUE_ADDRESS rpp::utils::tuple observables{}; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert((std::same_as> && ...), "T is not same as values of other observables"); diff --git a/src/rpp/rpp/operators/reduce.hpp b/src/rpp/rpp/operators/reduce.hpp index 5b7cbb4c8..8f5cbdb09 100644 --- a/src/rpp/rpp/operators/reduce.hpp +++ b/src/rpp/rpp/operators/reduce.hpp @@ -52,7 +52,7 @@ struct reduce_t final : public operators::details::lift_operator, Seed, Accumulator>::lift_operator; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); @@ -102,7 +102,7 @@ template struct reduce_no_seed_t final : public operators::details::lift_operator, Accumulator> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); diff --git a/src/rpp/rpp/operators/scan.hpp b/src/rpp/rpp/operators/scan.hpp index 873d6b323..96f1d5a85 100644 --- a/src/rpp/rpp/operators/scan.hpp +++ b/src/rpp/rpp/operators/scan.hpp @@ -57,7 +57,7 @@ struct scan_t final : public operators::details::lift_operator, InitialValue, Fn>::lift_operator; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with Seed&& abnd T returning Seed"); @@ -106,7 +106,7 @@ template struct scan_no_seed_t final : public operators::details::lift_operator, Fn> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Accumulator is not invocable with T&& abnd T returning T"); diff --git a/src/rpp/rpp/operators/skip.hpp b/src/rpp/rpp/operators/skip.hpp index 6f5bdb81d..bcc7987bf 100644 --- a/src/rpp/rpp/operators/skip.hpp +++ b/src/rpp/rpp/operators/skip.hpp @@ -48,7 +48,7 @@ struct skip_observer_strategy struct skip_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/subscribe_on.hpp b/src/rpp/rpp/operators/subscribe_on.hpp index 9bb01fab0..a6b722187 100644 --- a/src/rpp/rpp/operators/subscribe_on.hpp +++ b/src/rpp/rpp/operators/subscribe_on.hpp @@ -36,7 +36,7 @@ template struct subscribe_on_t { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; }; diff --git a/src/rpp/rpp/operators/switch_on_next.hpp b/src/rpp/rpp/operators/switch_on_next.hpp index e6fcd9188..20eb4e5ec 100644 --- a/src/rpp/rpp/operators/switch_on_next.hpp +++ b/src/rpp/rpp/operators/switch_on_next.hpp @@ -137,7 +137,7 @@ class switch_on_next_observer_strategy struct switch_on_next_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::observable, "T is not observable"); diff --git a/src/rpp/rpp/operators/take.hpp b/src/rpp/rpp/operators/take.hpp index 8b5548de0..8a39237c2 100644 --- a/src/rpp/rpp/operators/take.hpp +++ b/src/rpp/rpp/operators/take.hpp @@ -52,7 +52,7 @@ struct take_observer_strategy struct take_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/take_last.hpp b/src/rpp/rpp/operators/take_last.hpp index dfffe89c8..e30890216 100644 --- a/src/rpp/rpp/operators/take_last.hpp +++ b/src/rpp/rpp/operators/take_last.hpp @@ -83,7 +83,7 @@ class take_last_observer_strategy struct take_last_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/take_until.hpp b/src/rpp/rpp/operators/take_until.hpp index 3534fc490..b8156f79b 100644 --- a/src/rpp/rpp/operators/take_until.hpp +++ b/src/rpp/rpp/operators/take_until.hpp @@ -90,7 +90,7 @@ struct take_until_t RPP_NO_UNIQUE_ADDRESS TObservable observable{}; template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; }; diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index 5903ed9d5..507e10aa1 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -47,7 +47,7 @@ template struct take_while_t final : public operators::details::lift_operator, Fn> { template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::is_invocable_r_v, "Fn is not invocable with T returning bool"); diff --git a/src/rpp/rpp/operators/tap.hpp b/src/rpp/rpp/operators/tap.hpp index 62610e596..ea4098e4f 100644 --- a/src/rpp/rpp/operators/tap.hpp +++ b/src/rpp/rpp/operators/tap.hpp @@ -64,7 +64,7 @@ struct tap_t : public operators::details::lift_operator, OnNext, OnError, OnCompleted>::lift_operator; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(rpp::constraint::invocable_r_v, "OnNext is not invocable with T"); diff --git a/src/rpp/rpp/operators/throttle.hpp b/src/rpp/rpp/operators/throttle.hpp index 808b83f21..d00258ed8 100644 --- a/src/rpp/rpp/operators/throttle.hpp +++ b/src/rpp/rpp/operators/throttle.hpp @@ -54,7 +54,7 @@ template struct throttle_t final : public operators::details::lift_operator, rpp::schedulers::duration> { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = T; diff --git a/src/rpp/rpp/operators/window.hpp b/src/rpp/rpp/operators/window.hpp index a43398e7d..18db1a098 100644 --- a/src/rpp/rpp/operators/window.hpp +++ b/src/rpp/rpp/operators/window.hpp @@ -105,7 +105,7 @@ class window_observer_strategy struct window_t final : public operators::details::lift_operator { template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = window_observable; diff --git a/src/rpp/rpp/operators/window_toggle.hpp b/src/rpp/rpp/operators/window_toggle.hpp index ba1bb2b87..8517d959e 100644 --- a/src/rpp/rpp/operators/window_toggle.hpp +++ b/src/rpp/rpp/operators/window_toggle.hpp @@ -191,7 +191,7 @@ struct window_toggle_t RPP_NO_UNIQUE_ADDRESS TClosingsSelectorFn closings_selector; template - struct operator_traits_for_upstream_type + struct operator_traits { using result_type = rpp::window_toggle_observable; }; diff --git a/src/rpp/rpp/operators/with_latest_from.hpp b/src/rpp/rpp/operators/with_latest_from.hpp index e5c93ebf6..ba3814526 100644 --- a/src/rpp/rpp/operators/with_latest_from.hpp +++ b/src/rpp/rpp/operators/with_latest_from.hpp @@ -131,7 +131,7 @@ struct with_latest_from_t RPP_NO_UNIQUE_ADDRESS TSelector selector; template - struct operator_traits_for_upstream_type + struct operator_traits { static_assert(std::invocable...>, "TSelector is not invocable with T and types of rest observables"); From 5a3b1d3956fa384d5fee8bca6b3dfb1e726b9d71 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 16:15:54 +0300 Subject: [PATCH 18/19] revert map --- src/examples/rpp/doxygen/map.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/examples/rpp/doxygen/map.cpp b/src/examples/rpp/doxygen/map.cpp index cf7b082cf..d6bae5bcc 100644 --- a/src/examples/rpp/doxygen/map.cpp +++ b/src/examples/rpp/doxygen/map.cpp @@ -10,15 +10,15 @@ int main() // NOLINT(bugprone-exception-escape) { //! [Same type] rpp::source::just(42) - | rpp::operators::map([](std::string value) { return value; }); - // | rpp::operators::subscribe([](int v) { std::cout << v << std::endl; }); + | rpp::operators::map([](int value) { return value + 10; }) + | rpp::operators::subscribe([](int v) { std::cout << v << std::endl; }); // Output: 52 //! [Same type] //! [Changed type] - rpp::source::just(std::vector{}) - | rpp::operators::distinct(); - // | rpp::operators::subscribe([](const std::string& v) { std::cout << v << std::endl; }); + rpp::source::just(42) + | rpp::operators::map([](int value) { return std::to_string(value) + " VAL"; }) + | rpp::operators::subscribe([](const std::string& v) { std::cout << v << std::endl; }); // Output: 42 VAL //! [Changed type] return 0; From 35af08bf722e8c83831fe1e4998d56b77763bd8d Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Thu, 15 Feb 2024 16:17:29 +0300 Subject: [PATCH 19/19] remove unnecessary final --- src/rpp/rpp/operators/buffer.hpp | 2 +- src/rpp/rpp/operators/concat.hpp | 2 +- src/rpp/rpp/operators/distinct.hpp | 2 +- src/rpp/rpp/operators/filter.hpp | 2 +- src/rpp/rpp/operators/first.hpp | 2 +- src/rpp/rpp/operators/group_by.hpp | 2 +- src/rpp/rpp/operators/last.hpp | 2 +- src/rpp/rpp/operators/map.hpp | 2 +- src/rpp/rpp/operators/reduce.hpp | 4 ++-- src/rpp/rpp/operators/scan.hpp | 4 ++-- src/rpp/rpp/operators/skip.hpp | 2 +- src/rpp/rpp/operators/switch_on_next.hpp | 2 +- src/rpp/rpp/operators/take.hpp | 2 +- src/rpp/rpp/operators/take_last.hpp | 2 +- src/rpp/rpp/operators/take_while.hpp | 2 +- src/rpp/rpp/operators/throttle.hpp | 2 +- src/rpp/rpp/operators/window.hpp | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/rpp/rpp/operators/buffer.hpp b/src/rpp/rpp/operators/buffer.hpp index c100f17b4..de0e9553a 100644 --- a/src/rpp/rpp/operators/buffer.hpp +++ b/src/rpp/rpp/operators/buffer.hpp @@ -64,7 +64,7 @@ class buffer_observer_strategy mutable std::vector m_bucket; }; -struct buffer_t final : public operators::details::lift_operator +struct buffer_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/concat.hpp b/src/rpp/rpp/operators/concat.hpp index 5113f886f..4f365faa1 100644 --- a/src/rpp/rpp/operators/concat.hpp +++ b/src/rpp/rpp/operators/concat.hpp @@ -195,7 +195,7 @@ struct concat_observer_strategy : public concat_observer_strategy_base +struct concat_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/distinct.hpp b/src/rpp/rpp/operators/distinct.hpp index aa51172cf..0446e01d4 100644 --- a/src/rpp/rpp/operators/distinct.hpp +++ b/src/rpp/rpp/operators/distinct.hpp @@ -47,7 +47,7 @@ struct distinct_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct distinct_t final : public operators::details::lift_operator +struct distinct_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/filter.hpp b/src/rpp/rpp/operators/filter.hpp index 599a3dc29..6ebcddb6c 100644 --- a/src/rpp/rpp/operators/filter.hpp +++ b/src/rpp/rpp/operators/filter.hpp @@ -44,7 +44,7 @@ struct filter_observer_strategy }; template -struct filter_t final : public operators::details::lift_operator, Fn> +struct filter_t : lift_operator, Fn> { template struct operator_traits diff --git a/src/rpp/rpp/operators/first.hpp b/src/rpp/rpp/operators/first.hpp index 64b78543e..6fcad3145 100644 --- a/src/rpp/rpp/operators/first.hpp +++ b/src/rpp/rpp/operators/first.hpp @@ -43,7 +43,7 @@ struct first_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct first_t final : public operators::details::lift_operator +struct first_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/group_by.hpp b/src/rpp/rpp/operators/group_by.hpp index 292d8f75b..6efe5099e 100644 --- a/src/rpp/rpp/operators/group_by.hpp +++ b/src/rpp/rpp/operators/group_by.hpp @@ -162,7 +162,7 @@ struct group_by_observable_strategy }; template -struct group_by_t final : public operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator> +struct group_by_t : lift_operator, KeySelector, ValueSelector, KeyComparator> { using operators::details::lift_operator, KeySelector, ValueSelector, KeyComparator>::lift_operator; diff --git a/src/rpp/rpp/operators/last.hpp b/src/rpp/rpp/operators/last.hpp index f74407323..e971f3ddf 100644 --- a/src/rpp/rpp/operators/last.hpp +++ b/src/rpp/rpp/operators/last.hpp @@ -51,7 +51,7 @@ struct last_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct last_t final : public operators::details::lift_operator +struct last_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/map.hpp b/src/rpp/rpp/operators/map.hpp index 6c74266fa..9cf964fd2 100644 --- a/src/rpp/rpp/operators/map.hpp +++ b/src/rpp/rpp/operators/map.hpp @@ -43,7 +43,7 @@ struct map_observer_strategy }; template -struct map_t final : public operators::details::lift_operator, Fn> +struct map_t : lift_operator, Fn> { template struct operator_traits diff --git a/src/rpp/rpp/operators/reduce.hpp b/src/rpp/rpp/operators/reduce.hpp index 8f5cbdb09..36ab5e04d 100644 --- a/src/rpp/rpp/operators/reduce.hpp +++ b/src/rpp/rpp/operators/reduce.hpp @@ -47,7 +47,7 @@ struct reduce_observer_strategy }; template -struct reduce_t final : public operators::details::lift_operator, Seed, Accumulator> +struct reduce_t : lift_operator, Seed, Accumulator> { using operators::details::lift_operator, Seed, Accumulator>::lift_operator; @@ -99,7 +99,7 @@ struct reduce_no_seed_observer_strategy }; template -struct reduce_no_seed_t final : public operators::details::lift_operator, Accumulator> +struct reduce_no_seed_t : lift_operator, Accumulator> { template struct operator_traits diff --git a/src/rpp/rpp/operators/scan.hpp b/src/rpp/rpp/operators/scan.hpp index 96f1d5a85..005972de8 100644 --- a/src/rpp/rpp/operators/scan.hpp +++ b/src/rpp/rpp/operators/scan.hpp @@ -52,7 +52,7 @@ struct scan_observer_strategy }; template -struct scan_t final : public operators::details::lift_operator, InitialValue, Fn> +struct scan_t : lift_operator, InitialValue, Fn> { using operators::details::lift_operator, InitialValue, Fn>::lift_operator; @@ -103,7 +103,7 @@ struct scan_no_seed_observer_strategy }; template -struct scan_no_seed_t final : public operators::details::lift_operator, Fn> +struct scan_no_seed_t : lift_operator, Fn> { template struct operator_traits diff --git a/src/rpp/rpp/operators/skip.hpp b/src/rpp/rpp/operators/skip.hpp index bcc7987bf..7ef47f385 100644 --- a/src/rpp/rpp/operators/skip.hpp +++ b/src/rpp/rpp/operators/skip.hpp @@ -45,7 +45,7 @@ struct skip_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct skip_t final : public operators::details::lift_operator +struct skip_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/switch_on_next.hpp b/src/rpp/rpp/operators/switch_on_next.hpp index 20eb4e5ec..934036385 100644 --- a/src/rpp/rpp/operators/switch_on_next.hpp +++ b/src/rpp/rpp/operators/switch_on_next.hpp @@ -134,7 +134,7 @@ class switch_on_next_observer_strategy mutable rpp::composite_disposable_wrapper m_last_refcount = composite_disposable_wrapper::empty(); }; -struct switch_on_next_t final : public operators::details::lift_operator +struct switch_on_next_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/take.hpp b/src/rpp/rpp/operators/take.hpp index 8a39237c2..aed98fe54 100644 --- a/src/rpp/rpp/operators/take.hpp +++ b/src/rpp/rpp/operators/take.hpp @@ -49,7 +49,7 @@ struct take_observer_strategy bool is_disposed() const { return observer.is_disposed(); } }; -struct take_t final : public operators::details::lift_operator +struct take_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/take_last.hpp b/src/rpp/rpp/operators/take_last.hpp index e30890216..c4ffaf032 100644 --- a/src/rpp/rpp/operators/take_last.hpp +++ b/src/rpp/rpp/operators/take_last.hpp @@ -80,7 +80,7 @@ class take_last_observer_strategy mutable size_t m_current_end{}; }; -struct take_last_t final : public operators::details::lift_operator +struct take_last_t : lift_operator { template struct operator_traits diff --git a/src/rpp/rpp/operators/take_while.hpp b/src/rpp/rpp/operators/take_while.hpp index 507e10aa1..b8acc9867 100644 --- a/src/rpp/rpp/operators/take_while.hpp +++ b/src/rpp/rpp/operators/take_while.hpp @@ -44,7 +44,7 @@ struct take_while_observer_strategy }; template -struct take_while_t final : public operators::details::lift_operator, Fn> +struct take_while_t : lift_operator, Fn> { template struct operator_traits diff --git a/src/rpp/rpp/operators/throttle.hpp b/src/rpp/rpp/operators/throttle.hpp index d00258ed8..55e5aaf56 100644 --- a/src/rpp/rpp/operators/throttle.hpp +++ b/src/rpp/rpp/operators/throttle.hpp @@ -51,7 +51,7 @@ struct throttle_observer_strategy }; template -struct throttle_t final : public operators::details::lift_operator, rpp::schedulers::duration> +struct throttle_t : lift_operator, rpp::schedulers::duration> { template struct operator_traits diff --git a/src/rpp/rpp/operators/window.hpp b/src/rpp/rpp/operators/window.hpp index 18db1a098..f5d32a074 100644 --- a/src/rpp/rpp/operators/window.hpp +++ b/src/rpp/rpp/operators/window.hpp @@ -102,7 +102,7 @@ class window_observer_strategy mutable size_t m_items_in_current_window = m_window_size; }; -struct window_t final : public operators::details::lift_operator +struct window_t : lift_operator { template struct operator_traits