From 80d9938e96a688c860fd84225091492eb6d8e246 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 27 Sep 2017 18:15:26 +0300 Subject: [PATCH] Support and use not type-erased consumers. --- Telegram/SourceFiles/base/observer.h | 4 +- .../info/profile/info_profile_values.cpp | 2 +- Telegram/SourceFiles/rpl/after_next.h | 2 +- Telegram/SourceFiles/rpl/combine.h | 71 +- Telegram/SourceFiles/rpl/combine_previous.h | 10 +- Telegram/SourceFiles/rpl/complete.h | 3 +- Telegram/SourceFiles/rpl/consumer.h | 813 ++++++++++++------ Telegram/SourceFiles/rpl/deferred.h | 2 +- .../SourceFiles/rpl/distinct_until_changed.h | 2 +- Telegram/SourceFiles/rpl/event_stream.h | 3 +- Telegram/SourceFiles/rpl/fail.h | 3 +- Telegram/SourceFiles/rpl/filter.h | 6 +- Telegram/SourceFiles/rpl/flatten_latest.h | 3 +- Telegram/SourceFiles/rpl/map.h | 28 +- Telegram/SourceFiles/rpl/never.h | 4 +- Telegram/SourceFiles/rpl/producer.h | 22 +- Telegram/SourceFiles/rpl/range.h | 16 +- Telegram/SourceFiles/rpl/then.h | 3 +- 18 files changed, 651 insertions(+), 346 deletions(-) diff --git a/Telegram/SourceFiles/base/observer.h b/Telegram/SourceFiles/base/observer.h index 79f8149b3c..81a394a13b 100644 --- a/Telegram/SourceFiles/base/observer.h +++ b/Telegram/SourceFiles/base/observer.h @@ -466,7 +466,7 @@ template < typename = std::enable_if_t>> inline auto ObservableViewer(base::Observable &observable) { return rpl::make_producer([&observable]( - const rpl::consumer &consumer) { + const auto &consumer) { auto lifetime = rpl::lifetime(); lifetime.make_state( observable.add_subscription([consumer](auto &&update) { @@ -479,7 +479,7 @@ inline auto ObservableViewer(base::Observable &observable) { inline auto ObservableViewer(base::Observable &observable) { return rpl::make_producer<>([&observable]( - const rpl::consumer<> &consumer) { + const auto &consumer) { auto lifetime = rpl::lifetime(); lifetime.make_state( observable.add_subscription([consumer]() { diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index a6d7d0d9f1..f9f036e013 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -34,7 +34,7 @@ namespace Profile { rpl::producer PeerUpdateViewer( Notify::PeerUpdate::Flags flags) { - return [=](const rpl::consumer &consumer) { + return [=](const auto &consumer) { auto lifetime = rpl::lifetime(); lifetime.make_state( Notify::PeerUpdated().add_subscription({ flags, [=]( diff --git a/Telegram/SourceFiles/rpl/after_next.h b/Telegram/SourceFiles/rpl/after_next.h index 5ceee13e4b..6ddb0cd178 100644 --- a/Telegram/SourceFiles/rpl/after_next.h +++ b/Telegram/SourceFiles/rpl/after_next.h @@ -38,7 +38,7 @@ public: return make_producer([ initial = std::move(initial), method = std::move(_method) - ](const consumer &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( [method = std::move(method), consumer](auto &&value) { auto copy = method; diff --git a/Telegram/SourceFiles/rpl/combine.h b/Telegram/SourceFiles/rpl/combine.h index 5e001483fc..2d16bf9432 100644 --- a/Telegram/SourceFiles/rpl/combine.h +++ b/Telegram/SourceFiles/rpl/combine.h @@ -107,7 +107,7 @@ inline void combine_subscribe( const consumer_type &consumer, combine_state *state, std::index_sequence, - producer &&...producers) { + std::tuple...> &&saved) { auto consume = { ( details::combine_subscribe_one< I, @@ -116,10 +116,53 @@ inline void combine_subscribe( >( consumer, state - ).subscribe(std::move(producers)), 0)... }; + ).subscribe(std::get(std::move(saved))), 0)... }; (void)consume; } +template +class combine_implementation_helper; + +template +combine_implementation_helper...> +make_combine_implementation_helper(Producers &&...producers) { + return combine_implementation_helper...>( + std::forward(producers)...); +} + +template < + typename ...Values, + typename ...Errors, + typename ...Generators> +class combine_implementation_helper...> { +public: + using CombinedValue = std::tuple; + using CombinedError = details::normalized_variant_t; + + combine_implementation_helper( + producer &&...producers) + : _saved(std::make_tuple(std::move(producers)...)) { + } + + template + lifetime operator()(const consumer &consumer) { + auto state = consumer.template make_state< + details::combine_state>(); + constexpr auto kArity = sizeof...(Values); + details::combine_subscribe( + consumer, + state, + std::make_index_sequence(), + std::move(_saved)); + + return lifetime(); + } + +private: + std::tuple...> _saved; + +}; + template < typename ...Values, typename ...Errors, @@ -128,26 +171,9 @@ inline auto combine_implementation( producer &&...producers) { using CombinedValue = std::tuple; using CombinedError = details::normalized_variant_t; - using consumer_type = consumer; - auto result = []( - const consumer_type &consumer, - producer &...producers) { - auto state = consumer.template make_state< - details::combine_state>(); - constexpr auto kArity = sizeof...(Values); - details::combine_subscribe( - consumer, - state, - std::make_index_sequence(), - std::move(producers)...); - - return lifetime(); - }; - return make_producer(std::bind( - result, - std::placeholders::_1, - std::move(producers)...)); + return make_producer( + make_combine_implementation_helper(std::move(producers)...)); } template @@ -290,10 +316,9 @@ template inline auto combine( std::vector> &&producers) { using state_type = details::combine_vector_state; - using consumer_type = consumer, Error>; return make_producer, Error>([ producers = std::move(producers) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { auto count = producers.size(); auto state = consumer.template make_state(); state->accumulated.resize(count); diff --git a/Telegram/SourceFiles/rpl/combine_previous.h b/Telegram/SourceFiles/rpl/combine_previous.h index f74a209980..93f593b1c7 100644 --- a/Telegram/SourceFiles/rpl/combine_previous.h +++ b/Telegram/SourceFiles/rpl/combine_previous.h @@ -31,12 +31,9 @@ public: template auto operator()( producer &&initial) const { - using consumer_type = consumer< - std::tuple, - Error>; return make_producer, Error>([ initial = std::move(initial) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { auto previous = consumer.template make_state< base::optional >(); @@ -74,13 +71,10 @@ public: template auto operator()(producer &&initial) { - using consumer_type = consumer< - std::tuple, - Error>; return make_producer, Error>([ initial = std::move(initial), value = Value(std::move(_value)) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { auto previous = consumer.template make_state( std::move(value)); return std::move(initial).start( diff --git a/Telegram/SourceFiles/rpl/complete.h b/Telegram/SourceFiles/rpl/complete.h index ada04f8642..0205db739b 100644 --- a/Telegram/SourceFiles/rpl/complete.h +++ b/Telegram/SourceFiles/rpl/complete.h @@ -26,8 +26,7 @@ namespace rpl { template inline auto complete() { - return make_producer([]( - const consumer &consumer) { + return make_producer([](const auto &consumer) { consumer.put_done(); return lifetime(); }); diff --git a/Telegram/SourceFiles/rpl/consumer.h b/Telegram/SourceFiles/rpl/consumer.h index f39369b03c..7f65f8b2dd 100644 --- a/Telegram/SourceFiles/rpl/consumer.h +++ b/Telegram/SourceFiles/rpl/consumer.h @@ -25,6 +25,241 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include namespace rpl { +namespace details { + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +class consumer_handlers; + +template +class type_erased_handlers { +public: + template < + typename OnNext, + typename OnError, + typename OnDone> + static std::shared_ptr create( + OnNext &&next, + OnError &&error, + OnDone &&done) { + return std::make_shared, + std::decay_t, + std::decay_t>>( + std::forward(next), + std::forward(error), + std::forward(done)); + } + + virtual bool put_next(Value &&value) = 0; + virtual bool put_next_copy(const Value &value) = 0; + virtual void put_error(Error &&error) = 0; + virtual void put_error_copy(const Error &error) = 0; + virtual void put_done() = 0; + + void add_lifetime(lifetime &&lifetime); + + template + Type *make_state(Args&& ...args); + + void terminate(); + +protected: + lifetime _lifetime; + bool _terminated = false; + +}; + +template +struct is_type_erased_handlers + : std::false_type { +}; + +template +struct is_type_erased_handlers> + : std::true_type { +}; + +template +class consumer_handlers final + : public type_erased_handlers { +public: + template < + typename OnNextOther, + typename OnErrorOther, + typename OnDoneOther> + consumer_handlers( + OnNextOther &&next, + OnErrorOther &&error, + OnDoneOther &&done) + : _next(std::forward(next)) + , _error(std::forward(error)) + , _done(std::forward(done)) { + } + + template < + typename OnNextOther, + typename OnErrorOther, + typename OnDoneOther> + static std::shared_ptr create( + OnNextOther &&next, + OnErrorOther &&error, + OnDoneOther &&done) { + return std::make_shared( + std::forward(next), + std::forward(error), + std::forward(done)); + } + + bool put_next(Value &&value) final override; + bool put_next_copy(const Value &value) final override; + void put_error(Error &&error) final override; + void put_error_copy(const Error &error) final override; + void put_done() final override; + +private: + OnNext _next; + OnError _error; + OnDone _done; + +}; + +template +inline void type_erased_handlers::add_lifetime( + lifetime &&lifetime) { + if (_terminated) { + lifetime.destroy(); + } else { + _lifetime.add(std::move(lifetime)); + } +} + +template +template +inline Type *type_erased_handlers::make_state( + Args&& ...args) { + Expects(!_terminated); + return _lifetime.make_state(std::forward(args)...); +} + +template +inline void type_erased_handlers::terminate() { + if (!_terminated) { + _terminated = true; + base::take(_lifetime).destroy(); + } +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +bool consumer_handlers< + Value, + Error, + OnNext, + OnError, + OnDone +>::put_next(Value &&value) { + if (this->_terminated) { + return false; + } + auto handler = this->_next; + details::callable_invoke(std::move(handler), std::move(value)); + return true; +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +bool consumer_handlers< + Value, + Error, + OnNext, + OnError, + OnDone +>::put_next_copy(const Value &value) { + if (this->_terminated) { + return false; + } + auto handler = this->_next; + details::const_ref_call_invoke(std::move(handler), value); + return true; +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +void consumer_handlers< + Value, + Error, + OnNext, + OnError, + OnDone +>::put_error(Error &&error) { + if (!this->_terminated) { + details::callable_invoke( + std::move(this->_error), + std::move(error)); + this->terminate(); + } +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +void consumer_handlers< + Value, + Error, + OnNext, + OnError, + OnDone +>::put_error_copy(const Error &error) { + if (!this->_terminated) { + details::const_ref_call_invoke( + std::move(this->_error), + error); + this->terminate(); + } +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone> +void consumer_handlers< + Value, + Error, + OnNext, + OnError, + OnDone +>::put_done() { + if (!this->_terminated) { + std::move(this->_done)(); + this->terminate(); + } +} + +} // namespace details struct no_value { no_value() = delete; @@ -40,19 +275,24 @@ struct empty_value { struct empty_error { }; -template -class consumer { +template < + typename Value = empty_value, + typename Error = no_error, + typename Handlers = details::type_erased_handlers> +class consumer; + +namespace details { + +template +class consumer_base { + using is_type_erased = is_type_erased_handlers; + public: template < typename OnNext, typename OnError, - typename OnDone, - typename = std::enable_if_t< - details::is_callable_v>, - typename = decltype(std::declval()( - std::declval())), - typename = decltype(std::declval()())> - consumer( + typename OnDone> + consumer_base( OnNext &&next, OnError &&error, OnDone &&done); @@ -82,104 +322,322 @@ public: void terminate() const; - bool operator==(const consumer &other) const { - return _instance == other._instance; - } - bool operator!=(const consumer &other) const { - return !(*this == other); - } - bool operator<(const consumer &other) const { - return _instance < other._instance; - } - bool operator>(const consumer &other) const { - return other < *this; - } - bool operator<=(const consumer &other) const { - return !(other < *this); - } - bool operator>=(const consumer &other) const { - return !(*this < other); + const details::type_erased_handlers *comparable() const { + return _handlers.get(); } private: - class abstract_instance; - - template - class instance; - - template - std::shared_ptr ConstructInstance( - OnNext &&next, - OnError &&error, - OnDone &&done); - - mutable std::shared_ptr _instance; - -}; - - -template -class consumer::abstract_instance { -public: - virtual bool put_next(Value &&value) = 0; - virtual bool put_next_copy(const Value &value) = 0; - virtual void put_error(Error &&error) = 0; - virtual void put_error_copy(const Error &error) = 0; - virtual void put_done() = 0; - - void add_lifetime(lifetime &&lifetime); - - template - Type *make_state(Args&& ...args); - - void terminate(); - -protected: - lifetime _lifetime; - bool _terminated = false; - -}; - -template -template -class consumer::instance - : public consumer::abstract_instance { -public: template < - typename OnNextImpl, - typename OnErrorImpl, - typename OnDoneImpl> - instance( - OnNextImpl &&next, - OnErrorImpl &&error, - OnDoneImpl &&done) - : _next(std::forward(next)) - , _error(std::forward(error)) - , _done(std::forward(done)) { + typename OtherHandlers, + typename = std::enable_if_t< + std::is_base_of_v>> + consumer_base(const std::shared_ptr &handlers) + : _handlers(handlers) { } - bool put_next(Value &&value) override; - bool put_next_copy(const Value &value) override; - void put_error(Error &&error) override; - void put_error_copy(const Error &error) override; - void put_done() override; + template < + typename OtherHandlers, + typename = std::enable_if_t< + std::is_base_of_v>> + consumer_base(std::shared_ptr &&handlers) + : _handlers(std::move(handlers)) { + } -private: - OnNext _next; - OnError _error; - OnDone _done; + mutable std::shared_ptr _handlers; + + bool handlers_put_next(Value &&value, std::true_type) const { + return _handlers->put_next(std::move(value)); + } + bool handlers_put_next_copy( + const Value &value, + std::true_type) const { + return _handlers->put_next_copy(value); + } + void handlers_put_error(Error &&error, std::true_type) const { + return std::exchange(_handlers, nullptr)->put_error(std::move(error)); + } + void handlers_put_error_copy( + const Error &error, + std::true_type) const { + return std::exchange(_handlers, nullptr)->put_error_copy(error); + } + void handlers_put_done(std::true_type) const { + return std::exchange(_handlers, nullptr)->put_done(); + } + + bool handlers_put_next(Value &&value, std::false_type) const { + return _handlers->Handlers::put_next(std::move(value)); + } + bool handlers_put_next_copy( + const Value &value, + std::false_type) const { + return _handlers->Handlers::put_next_copy(value); + } + void handlers_put_error(Error &&error, std::false_type) const { + return std::exchange(_handlers, nullptr)->Handlers::put_error(std::move(error)); + } + void handlers_put_error_copy( + const Error &error, + std::false_type) const { + return std::exchange(_handlers, nullptr)->Handlers::put_error_copy(error); + } + void handlers_put_done(std::false_type) const { + return std::exchange(_handlers, nullptr)->Handlers::put_done(); + } + + template < + typename OtherValue, + typename OtherError, + typename OtherHandlers> + friend class ::rpl::consumer; + +}; + +template +template +inline consumer_base::consumer_base( + OnNext &&next, + OnError &&error, + OnDone &&done) : _handlers(Handlers::create( + std::forward(next), + std::forward(error), + std::forward(done))) { +} + +template +inline bool consumer_base::put_next( + Value &&value) const { + if (_handlers) { + if (handlers_put_next(std::move(value), is_type_erased())) { + return true; + } + _handlers = nullptr; + } + return false; +} + +template +inline bool consumer_base::put_next_copy( + const Value &value) const { + if (_handlers) { + if (handlers_put_next_copy(value, is_type_erased())) { + return true; + } + _handlers = nullptr; + } + return false; +} + +template +inline void consumer_base::put_error( + Error &&error) const { + if (_handlers) { + handlers_put_error(std::move(error), is_type_erased()); + } +} + +template +inline void consumer_base::put_error_copy( + const Error &error) const { + if (_handlers) { + handlers_put_error_copy(error, is_type_erased()); + } +} + +template +inline void consumer_base::put_done() const { + if (_handlers) { + handlers_put_done(is_type_erased()); + } +} + +template +inline void consumer_base::add_lifetime( + lifetime &&lifetime) const { + if (_handlers) { + _handlers->add_lifetime(std::move(lifetime)); + } else { + lifetime.destroy(); + } +} + +template +template +inline Type *consumer_base::make_state( + Args&& ...args) const { + Expects(_handlers != nullptr); + return _handlers->template make_state( + std::forward(args)...); +} + +template +inline void consumer_base::terminate() const { + if (_handlers) { + std::exchange(_handlers, nullptr)->terminate(); + } +} + +template +using consumer_base_type_erased = consumer_base< + Value, + Error, + details::type_erased_handlers>; + +template +constexpr bool is_specific_handlers_v = !std::is_same_v< + details::type_erased_handlers, + Handlers +> && std::is_base_of_v< + details::type_erased_handlers, + Handlers +>; + +} // namespace details + +template +class consumer final +: public details::consumer_base { + using parent_type = details::consumer_base< + Value, + Error, + Handlers>; + +public: + using parent_type::parent_type; }; template -template -inline std::shared_ptr< - typename consumer::abstract_instance> -consumer::ConstructInstance( +class consumer> final +: public details::consumer_base_type_erased { + using parent_type = details::consumer_base_type_erased< + Value, + Error>; + +public: + using parent_type::parent_type; + + template < + typename Handlers, + typename = std::enable_if_t< + details::is_specific_handlers_v>> + consumer(const details::consumer_base &other) + : parent_type(other._handlers) { + } + + template < + typename Handlers, + typename = std::enable_if_t< + details::is_specific_handlers_v>> + consumer(details::consumer_base &&other) + : parent_type(std::move(other._handlers)) { + } + + template < + typename Handlers, + typename = std::enable_if_t< + details::is_specific_handlers_v>> + consumer &operator=( + const details::consumer_base &other) { + _handlers = other._handlers; + return *this; + } + + template < + typename Handlers, + typename = std::enable_if_t< + details::is_specific_handlers_v>> + consumer &operator=( + details::consumer_base &&other) { + _handlers = std::move(other._handlers); + return *this; + } + +}; + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator==( + const consumer &a, + const consumer &b) { + return a.comparable() == b.comparable(); +} + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator<( + const consumer &a, + const consumer &b) { + return a.comparable() < b.comparable(); +} + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator!=( + const consumer &a, + const consumer &b) { + return !(a == b); +} + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator>( + const consumer &a, + const consumer &b) { + return b < a; +} + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator<=( + const consumer &a, + const consumer &b) { + return !(b < a); +} + +template < + typename Value, + typename Error, + typename Handlers1, + typename Handlers2> +inline bool operator>=( + const consumer &a, + const consumer &b) { + return !(a < b); +} + +template < + typename Value, + typename Error, + typename OnNext, + typename OnError, + typename OnDone, + typename = std::enable_if_t< + details::is_callable_v && + details::is_callable_v && + details::is_callable_v>> +inline auto make_consumer( OnNext &&next, OnError &&error, OnDone &&done) { - return std::make_shared, std::decay_t, std::decay_t>>( @@ -188,173 +646,4 @@ consumer::ConstructInstance( std::forward(done)); } -template -template < - typename OnNext, - typename OnError, - typename OnDone, - typename, - typename, - typename> -inline consumer::consumer( - OnNext &&next, - OnError &&error, - OnDone &&done) : _instance(ConstructInstance( - std::forward(next), - std::forward(error), - std::forward(done))) { -} - -template -inline bool consumer::put_next(Value &&value) const { - if (_instance) { - if (_instance->put_next(std::move(value))) { - return true; - } - _instance = nullptr; - } - return false; -} - -template -inline bool consumer::put_next_copy( - const Value &value) const { - if (_instance) { - if (_instance->put_next_copy(value)) { - return true; - } - _instance = nullptr; - } - return false; -} - -template -inline void consumer::put_error(Error &&error) const { - if (_instance) { - std::exchange(_instance, nullptr)->put_error( - std::move(error)); - } -} - -template -inline void consumer::put_error_copy( - const Error &error) const { - if (_instance) { - std::exchange(_instance, nullptr)->put_error_copy(error); - } -} - -template -inline void consumer::put_done() const { - if (_instance) { - std::exchange(_instance, nullptr)->put_done(); - } -} - -template -inline void consumer::add_lifetime(lifetime &&lifetime) const { - if (_instance) { - _instance->add_lifetime(std::move(lifetime)); - } else { - lifetime.destroy(); - } -} - -template -template -inline Type *consumer::make_state(Args&& ...args) const { - Expects(_instance != nullptr); - return _instance->template make_state(std::forward(args)...); -} - -template -inline void consumer::terminate() const { - if (_instance) { - std::exchange(_instance, nullptr)->terminate(); - } -} - -template -inline void consumer::abstract_instance::add_lifetime( - lifetime &&lifetime) { - if (_terminated) { - lifetime.destroy(); - } else { - _lifetime.add(std::move(lifetime)); - } -} - -template -template -inline Type *consumer::abstract_instance::make_state( - Args&& ...args) { - Expects(!_terminated); - return _lifetime.make_state(std::forward(args)...); -} - -template -inline void consumer::abstract_instance::terminate() { - if (!_terminated) { - _terminated = true; - base::take(_lifetime).destroy(); - } -} - -template -template -bool consumer::instance::put_next( - Value &&value) { - if (this->_terminated) { - return false; - } - auto handler = this->_next; - details::callable_invoke(std::move(handler), std::move(value)); - return true; -} - -template -template -bool consumer::instance::put_next_copy( - const Value &value) { - if (this->_terminated) { - return false; - } - auto handler = this->_next; - details::const_ref_call_invoke(std::move(handler), value); - return true; -} - -template -template -void consumer::instance::put_error( - Error &&error) { - if (!this->_terminated) { - details::callable_invoke( - std::move(this->_error), - std::move(error)); - this->terminate(); - } -} - -template -template -void consumer::instance::put_error_copy( - const Error &error) { - if (!this->_terminated) { - details::const_ref_call_invoke( - std::move(this->_error), - error); - this->terminate(); - } -} - -template -template -void consumer::instance::put_done() { - if (!this->_terminated) { - std::move(this->_done)(); - this->terminate(); - } -} - } // namespace rpl diff --git a/Telegram/SourceFiles/rpl/deferred.h b/Telegram/SourceFiles/rpl/deferred.h index 62ae2e63f1..6d89c75e1a 100644 --- a/Telegram/SourceFiles/rpl/deferred.h +++ b/Telegram/SourceFiles/rpl/deferred.h @@ -31,7 +31,7 @@ template < inline auto deferred(Creator &&creator) { return make_producer([ creator = std::forward(creator) - ](const consumer &consumer) mutable { + ](const auto &consumer) mutable { return std::move(creator)().start_existing(consumer); }); } diff --git a/Telegram/SourceFiles/rpl/distinct_until_changed.h b/Telegram/SourceFiles/rpl/distinct_until_changed.h index 329d2d35c0..35f9b92f8f 100644 --- a/Telegram/SourceFiles/rpl/distinct_until_changed.h +++ b/Telegram/SourceFiles/rpl/distinct_until_changed.h @@ -33,7 +33,7 @@ public: producer &&initial) const { return make_producer([ initial = std::move(initial) - ](const consumer &consumer) mutable { + ](const auto &consumer) mutable { auto previous = consumer.template make_state< base::optional >(); diff --git a/Telegram/SourceFiles/rpl/event_stream.h b/Telegram/SourceFiles/rpl/event_stream.h index 36c0d99532..5580352d35 100644 --- a/Telegram/SourceFiles/rpl/event_stream.h +++ b/Telegram/SourceFiles/rpl/event_stream.h @@ -47,9 +47,8 @@ public: return fire_forward(value); } auto events() const { - using consumer_type = consumer; return make_producer([weak = weak()]( - const consumer_type &consumer) { + const auto &consumer) { if (auto strong = weak.lock()) { auto result = [weak, consumer] { if (auto strong = weak.lock()) { diff --git a/Telegram/SourceFiles/rpl/fail.h b/Telegram/SourceFiles/rpl/fail.h index 0573276230..1efc344818 100644 --- a/Telegram/SourceFiles/rpl/fail.h +++ b/Telegram/SourceFiles/rpl/fail.h @@ -26,10 +26,9 @@ namespace rpl { template inline auto fail(Error &&error) { - using consumer_t = consumer>; return make_producer>([ error = std::forward(error) - ](const consumer_t &consumer) mutable { + ](const auto &consumer) mutable { consumer.put_error(std::move(error)); return lifetime(); }); diff --git a/Telegram/SourceFiles/rpl/filter.h b/Telegram/SourceFiles/rpl/filter.h index bbff03f9dd..fe2ea1fb06 100644 --- a/Telegram/SourceFiles/rpl/filter.h +++ b/Telegram/SourceFiles/rpl/filter.h @@ -43,11 +43,10 @@ public: typename = std::enable_if_t< details::is_callable_v>> auto operator()(producer &&initial) { - using consumer_type = consumer; return make_producer([ initial = std::move(initial), predicate = std::move(_predicate) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( [ consumer, @@ -126,10 +125,9 @@ public: base::optional, Error, Generator> &&initial) const { - using consumer_type = consumer; return make_producer([ initial = std::move(initial) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( [consumer](auto &&value) { if (value) { diff --git a/Telegram/SourceFiles/rpl/flatten_latest.h b/Telegram/SourceFiles/rpl/flatten_latest.h index 5a882d4fde..921124f454 100644 --- a/Telegram/SourceFiles/rpl/flatten_latest.h +++ b/Telegram/SourceFiles/rpl/flatten_latest.h @@ -36,10 +36,9 @@ public: producer, Error, MetaGenerator> &&initial) const { - using consumer_type = consumer; return make_producer([ initial = std::move(initial) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { auto state = std::make_shared(); return std::move(initial).start( [consumer, state](producer &&inner) { diff --git a/Telegram/SourceFiles/rpl/map.h b/Telegram/SourceFiles/rpl/map.h index 644e096550..9158726eea 100644 --- a/Telegram/SourceFiles/rpl/map.h +++ b/Telegram/SourceFiles/rpl/map.h @@ -28,12 +28,13 @@ namespace details { template < typename Transform, typename NewValue, - typename Error> + typename Error, + typename Handlers> class map_transform_helper { public: map_transform_helper( Transform &&transform, - const consumer &consumer) + const consumer &consumer) : _consumer(consumer) , _transform(std::move(transform)) { } @@ -55,7 +56,7 @@ public: } private: - consumer _consumer; + consumer _consumer; Transform _transform; }; @@ -64,12 +65,13 @@ template < typename Transform, typename NewValue, typename Error, + typename Handlers, typename = std::enable_if_t< std::is_rvalue_reference_v>> -inline map_transform_helper +inline map_transform_helper map_transform( Transform &&transform, - const consumer &consumer) { + const consumer &consumer) { return { std::move(transform), consumer }; } @@ -92,7 +94,7 @@ public: return make_producer([ initial = std::move(initial), transform = std::move(_transform) - ](const consumer &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( map_transform( std::move(transform), @@ -125,12 +127,13 @@ namespace details { template < typename Transform, typename Value, - typename NewError> + typename NewError, + typename Handlers> class map_error_transform_helper { public: map_error_transform_helper( Transform &&transform, - const consumer &consumer) + const consumer &consumer) : _transform(std::move(transform)) , _consumer(consumer) { } @@ -152,7 +155,7 @@ public: } private: - consumer _consumer; + consumer _consumer; Transform _transform; }; @@ -161,12 +164,13 @@ template < typename Transform, typename Value, typename NewError, + typename Handlers, typename = std::enable_if_t< std::is_rvalue_reference_v>> -inline map_error_transform_helper +inline map_error_transform_helper map_error_transform( Transform &&transform, - const consumer &consumer) { + const consumer &consumer) { return { std::move(transform), consumer }; } @@ -189,7 +193,7 @@ public: return make_producer([ initial = std::move(initial), transform = std::move(_transform) - ](const consumer &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( [consumer](auto &&value) { consumer.put_next_forward( diff --git a/Telegram/SourceFiles/rpl/never.h b/Telegram/SourceFiles/rpl/never.h index f9091355fb..cc42198465 100644 --- a/Telegram/SourceFiles/rpl/never.h +++ b/Telegram/SourceFiles/rpl/never.h @@ -26,9 +26,7 @@ namespace rpl { template inline auto never() { - using consumer_type = consumer; - return make_producer([]( - const consumer_type &consumer) { + return make_producer([](const auto &consumer) { return lifetime(); }); } diff --git a/Telegram/SourceFiles/rpl/producer.h b/Telegram/SourceFiles/rpl/producer.h index 9248d82d90..a70c74eb25 100644 --- a/Telegram/SourceFiles/rpl/producer.h +++ b/Telegram/SourceFiles/rpl/producer.h @@ -60,9 +60,10 @@ private: template class type_erased_generator final { public: + template + using consumer_type = consumer; using value_type = Value; using error_type = Error; - using consumer_type = consumer; type_erased_generator( const type_erased_generator &other) = default; @@ -102,12 +103,13 @@ public: return *this; } - lifetime operator()(const consumer_type &consumer) { + template + lifetime operator()(const consumer_type &consumer) { return _implementation(consumer); } private: - base::lambda _implementation; + base::lambda> &)> _implementation; }; @@ -162,9 +164,10 @@ namespace details { template class producer_base { public: + template + using consumer_type = consumer; using value_type = Value; using error_type = Error; - using consumer_type = consumer; template < typename OtherGenerator, @@ -203,7 +206,9 @@ public: OnError &&error, OnDone &&done) const &; - lifetime start_existing(const consumer_type &consumer) &&; + template + lifetime start_existing( + const consumer_type &consumer) &&; private: Generator _generator; @@ -233,7 +238,7 @@ inline lifetime producer_base::start( OnNext &&next, OnError &&error, OnDone &&done) && { - return std::move(*this).start_existing(consumer( + return std::move(*this).start_existing(make_consumer( std::forward(next), std::forward(error), std::forward(done))); @@ -257,8 +262,9 @@ inline lifetime producer_base::start_copy( } template +template inline lifetime producer_base::start_existing( - const consumer_type &consumer) && { + const consumer_type &consumer) && { consumer.add_lifetime(std::move(_generator)(consumer)); return [consumer] { consumer.terminate(); }; } @@ -278,6 +284,7 @@ class producer final Value, Error, Generator>; + public: using parent_type::parent_type; @@ -292,6 +299,7 @@ class producer< using parent_type = details::producer_base_type_erased< Value, Error>; + public: using parent_type::parent_type;; diff --git a/Telegram/SourceFiles/rpl/range.h b/Telegram/SourceFiles/rpl/range.h index 6f5cc5a4a9..da6026c915 100644 --- a/Telegram/SourceFiles/rpl/range.h +++ b/Telegram/SourceFiles/rpl/range.h @@ -26,10 +26,9 @@ namespace rpl { template inline auto single(Value &&value) { - using consumer_type = consumer, no_error>; return make_producer>([ value = std::forward(value) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { consumer.put_next(std::move(value)); consumer.put_done(); return lifetime(); @@ -37,9 +36,7 @@ inline auto single(Value &&value) { } inline auto single() { - using consumer_type = consumer; - return make_producer<>([]( - const consumer_type &consumer) { + return make_producer<>([](const auto &consumer) { consumer.put_next({}); consumer.put_done(); return lifetime(); @@ -48,10 +45,9 @@ inline auto single() { template inline auto vector(std::vector &&values) { - using consumer_type = consumer; return make_producer([ values = std::move(values) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { for (auto &value : values) { consumer.put_next(std::move(value)); } @@ -61,10 +57,9 @@ inline auto vector(std::vector &&values) { } inline auto vector(std::vector &&values) { - using consumer_type = consumer; return make_producer([ values = std::move(values) - ](const consumer_type &consumer) { + ](const auto &consumer) { for (auto value : values) { consumer.put_next_copy(value); } @@ -85,8 +80,7 @@ inline auto range(Range &&range) { inline auto ints(int from, int till) { Expects(from <= till); - return make_producer([from, till]( - const consumer &consumer) { + return make_producer([from, till](const auto &consumer) { for (auto i = from; i != till; ++i) { consumer.put_next_copy(i); } diff --git a/Telegram/SourceFiles/rpl/then.h b/Telegram/SourceFiles/rpl/then.h index c066c906b8..91d3dbb506 100644 --- a/Telegram/SourceFiles/rpl/then.h +++ b/Telegram/SourceFiles/rpl/then.h @@ -41,11 +41,10 @@ public: auto operator()( producer &&initial ) { - using consumer_type = consumer; return make_producer([ initial = std::move(initial), following = std::move(_following) - ](const consumer_type &consumer) mutable { + ](const auto &consumer) mutable { return std::move(initial).start( [consumer](auto &&value) { consumer.put_next_forward(