From bdada990966d717b80b096dd2c4d8d40234d1a32 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Sun, 9 Dec 2018 16:48:08 +0100 Subject: [PATCH] Fix the immediate return type of chained continuables * Statically resolve ready continuables --- include/continuable/continuable-base.hpp | 9 ++-- include/continuable/detail/core/base.hpp | 47 +++++++++++++------ include/continuable/detail/utility/traits.hpp | 6 +-- include/continuable/detail/utility/util.hpp | 12 ++--- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 8d9cb86..51fb189 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -119,10 +119,13 @@ public: /// Constructor accepting any object convertible to the data object, /// while erasing the annotation - template , Data>::value>* = nullptr> + template >::value>* = + nullptr> continuable_base(OData&& data) // NOLINT(misc-forwarding-reference-overload) - : data_(std::forward(data)) { + : data_(detail::base::proxy_continuable( + std::forward(data))) { } /// Constructor taking the data of other continuable_base objects diff --git a/include/continuable/detail/core/base.hpp b/include/continuable/detail/core/base.hpp index 0db7e00..e5db7a3 100644 --- a/include/continuable/detail/core/base.hpp +++ b/include/continuable/detail/core/base.hpp @@ -714,15 +714,17 @@ auto strip_exception_arg(Callable&& callable) { return proxy{std::forward(callable)}; } -template struct chained_continuation; -template -struct chained_continuation, HandleResults, +struct chained_continuation, + traits::identity, HandleResults, HandleErrors, Continuation, Callback, Executor> { + Continuation continuation_; Callback callback_; Executor executor_; @@ -755,9 +757,9 @@ struct chained_continuation, HandleResults, std::move(callback_), std::move(executor_), std::forward(next_callback)); - // TODO Detect statically whether we have a raw ready continuable here // Check whether the continuation is ready bool const is_ready = util::as_const(continuation_)(is_ready_arg_t{}); + if (is_ready) { // Invoke the proxy callback directly with the result to // avoid a potential type erasure. @@ -774,16 +776,17 @@ struct chained_continuation, HandleResults, return false; } - std::tuple operator()(query_arg_t) { + std::tuple operator()(query_arg_t) { util::unreachable(); } }; // Specialization to unpack ready continuables directly -template -struct chained_continuation, HandleResults, - HandleErrors, ready_continuation, Callback, - Executor> { +struct chained_continuation< + traits::identity, traits::identity, HandleResults, + HandleErrors, ready_continuation, Callback, Executor> { + ready_continuation continuation_; Callback callback_; Executor executor_; @@ -816,7 +819,7 @@ struct chained_continuation, HandleResults, return false; } - std::tuple operator()(query_arg_t) { + std::tuple operator()(query_arg_t) { util::unreachable(); } }; @@ -848,10 +851,9 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback, auto data = attorney::consume(std::forward(continuation).finish()); - using continuation_t = - chained_continuation, - traits::unrefcv_t>; + using continuation_t = chained_continuation< + Hint, traits::unrefcv_t, HandleResults, HandleErrors, + decltype(data), traits::unrefcv_t, traits::unrefcv_t>; return attorney::create_from_raw( continuation_t(std::move(data), std::forward(callback), @@ -869,6 +871,23 @@ void finalize_continuation(Continuation&& continuation) { callbacks::final_callback{}); } +/// Deduces to a true type if the given callable data can be wrapped +/// with the given hint and converted to the given Data. +template +struct can_accept_continuation : std::false_type {}; +template +struct can_accept_continuation< + Data, traits::identity, Continuation, + traits::void_t< + std::enable_if_t::value>, + std::enable_if_t, Continuation>, + Data>::value>>> : std::true_type + +{}; + /// Workaround for GCC bug: /// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 template diff --git a/include/continuable/detail/utility/traits.hpp b/include/continuable/detail/utility/traits.hpp index e22eddb..602220b 100644 --- a/include/continuable/detail/utility/traits.hpp +++ b/include/continuable/detail/utility/traits.hpp @@ -148,16 +148,16 @@ struct is_invokable_impl< /// arguments inside lambda closures. /// /// ```cpp -/// traits::is_invokable> +/// traits::is_invocable> /// ``` template -using is_invokable_from_tuple = +using is_invocable_from_tuple = typename detail::is_invokable_impl::type; // Checks whether the given callable object is invocable with the given // arguments. This doesn't take member functions into account! template -using is_invocable = is_invokable_from_tuple>; +using is_invocable = is_invocable_from_tuple>; /// Deduces to a std::false_type template diff --git a/include/continuable/detail/utility/util.hpp b/include/continuable/detail/utility/util.hpp index 0600d7d..0dba222 100644 --- a/include/continuable/detail/utility/util.hpp +++ b/include/continuable/detail/utility/util.hpp @@ -95,10 +95,10 @@ struct invocation_env { auto next = forward_except_last(std::move(args)); // Test whether we are able to call the function with the given tuple - traits::is_invokable_from_tuple - is_invokable; + traits::is_invocable_from_tuple + is_invocable; - return partial_invoke_impl(is_invokable, std::forward(callable), + return partial_invoke_impl(is_invocable, std::forward(callable), std::move(next)); } @@ -132,15 +132,15 @@ template partial_invoke(std::integral_constant, T&& callable, Args&&... args) { // Test whether we are able to call the function with the given arguments. - constexpr traits::is_invokable_from_tuple> - is_invokable; + is_invocable; // The implementation is done in a shortcut way so there are less // type instantiations needed to call the callable with its full signature. using env = detail::invocation_env; return env::partial_invoke_impl_shortcut( - is_invokable, std::forward(callable), std::forward(args)...); + is_invocable, std::forward(callable), std::forward(args)...); } /// Invokes the given callable object with the given arguments