mirror of
https://github.com/Naios/continuable.git
synced 2025-12-08 09:47:43 +08:00
Fix the immediate return type of chained continuables
* Statically resolve ready continuables
This commit is contained in:
parent
7273891a4c
commit
bdada99096
@ -119,10 +119,13 @@ public:
|
||||
|
||||
/// Constructor accepting any object convertible to the data object,
|
||||
/// while erasing the annotation
|
||||
template <typename OData, std::enable_if_t<std::is_convertible<
|
||||
std::decay_t<OData>, Data>::value>* = nullptr>
|
||||
template <typename OData,
|
||||
std::enable_if_t<detail::base::can_accept_continuation<
|
||||
Data, Annotation, detail::traits::unrefcv_t<OData>>::value>* =
|
||||
nullptr>
|
||||
continuable_base(OData&& data) // NOLINT(misc-forwarding-reference-overload)
|
||||
: data_(std::forward<OData>(data)) {
|
||||
: data_(detail::base::proxy_continuable<Annotation, OData>(
|
||||
std::forward<OData>(data))) {
|
||||
}
|
||||
|
||||
/// Constructor taking the data of other continuable_base objects
|
||||
|
||||
@ -714,15 +714,17 @@ auto strip_exception_arg(Callable&& callable) {
|
||||
return proxy{std::forward<Callable>(callable)};
|
||||
}
|
||||
|
||||
template <typename Hint, handle_results HandleResults,
|
||||
template <typename Hint, typename NextHint, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Continuation, typename Callback,
|
||||
typename Executor>
|
||||
struct chained_continuation;
|
||||
template <typename... Args, handle_results HandleResults,
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Continuation, typename Callback,
|
||||
typename Executor>
|
||||
struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
struct chained_continuation<traits::identity<Args...>,
|
||||
traits::identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, Continuation, Callback, Executor> {
|
||||
|
||||
Continuation continuation_;
|
||||
Callback callback_;
|
||||
Executor executor_;
|
||||
@ -755,9 +757,9 @@ struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(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<traits::identity<Args...>, HandleResults,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tuple<Args...> operator()(query_arg_t) {
|
||||
std::tuple<NextArgs...> operator()(query_arg_t) {
|
||||
util::unreachable();
|
||||
}
|
||||
};
|
||||
// Specialization to unpack ready continuables directly
|
||||
template <typename... Args, handle_results HandleResults,
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor>
|
||||
struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
HandleErrors, ready_continuation<Args...>, Callback,
|
||||
Executor> {
|
||||
struct chained_continuation<
|
||||
traits::identity<Args...>, traits::identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, ready_continuation<Args...>, Callback, Executor> {
|
||||
|
||||
ready_continuation<Args...> continuation_;
|
||||
Callback callback_;
|
||||
Executor executor_;
|
||||
@ -816,7 +819,7 @@ struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tuple<Args...> operator()(query_arg_t) {
|
||||
std::tuple<NextArgs...> operator()(query_arg_t) {
|
||||
util::unreachable();
|
||||
}
|
||||
};
|
||||
@ -848,10 +851,9 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||
auto data =
|
||||
attorney::consume(std::forward<Continuation>(continuation).finish());
|
||||
|
||||
using continuation_t =
|
||||
chained_continuation<Hint, HandleResults, HandleErrors, decltype(data),
|
||||
traits::unrefcv_t<Callback>,
|
||||
traits::unrefcv_t<Executor>>;
|
||||
using continuation_t = chained_continuation<
|
||||
Hint, traits::unrefcv_t<decltype(next_hint)>, HandleResults, HandleErrors,
|
||||
decltype(data), traits::unrefcv_t<Callback>, traits::unrefcv_t<Executor>>;
|
||||
|
||||
return attorney::create_from_raw(
|
||||
continuation_t(std::move(data), std::forward<Callback>(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 <typename Data, typename Annotation, typename Continuation,
|
||||
typename = void>
|
||||
struct can_accept_continuation : std::false_type {};
|
||||
template <typename Data, typename... Args, typename Continuation>
|
||||
struct can_accept_continuation<
|
||||
Data, traits::identity<Args...>, Continuation,
|
||||
traits::void_t<
|
||||
std::enable_if_t<traits::is_invocable<
|
||||
Continuation, callbacks::final_callback>::value>,
|
||||
std::enable_if_t<std::is_convertible<
|
||||
proxy_continuable<traits::identity<Args...>, Continuation>,
|
||||
Data>::value>>> : std::true_type
|
||||
|
||||
{};
|
||||
|
||||
/// Workaround for GCC bug:
|
||||
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
||||
template <typename T>
|
||||
|
||||
@ -148,16 +148,16 @@ struct is_invokable_impl<
|
||||
/// arguments inside lambda closures.
|
||||
///
|
||||
/// ```cpp
|
||||
/// traits::is_invokable<object, std::tuple<Args...>>
|
||||
/// traits::is_invocable<object, std::tuple<Args...>>
|
||||
/// ```
|
||||
template <typename T, typename Args>
|
||||
using is_invokable_from_tuple =
|
||||
using is_invocable_from_tuple =
|
||||
typename detail::is_invokable_impl<T, Args>::type;
|
||||
|
||||
// Checks whether the given callable object is invocable with the given
|
||||
// arguments. This doesn't take member functions into account!
|
||||
template <typename T, typename... Args>
|
||||
using is_invocable = is_invokable_from_tuple<T, std::tuple<Args...>>;
|
||||
using is_invocable = is_invocable_from_tuple<T, std::tuple<Args...>>;
|
||||
|
||||
/// Deduces to a std::false_type
|
||||
template <typename T>
|
||||
|
||||
@ -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<decltype(callable), decltype(next)>
|
||||
is_invokable;
|
||||
traits::is_invocable_from_tuple<decltype(callable), decltype(next)>
|
||||
is_invocable;
|
||||
|
||||
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
|
||||
return partial_invoke_impl(is_invocable, std::forward<T>(callable),
|
||||
std::move(next));
|
||||
}
|
||||
|
||||
@ -132,15 +132,15 @@ template <std::size_t KeepArgs, typename T, typename... Args>
|
||||
partial_invoke(std::integral_constant<std::size_t, KeepArgs>, T&& callable,
|
||||
Args&&... args) {
|
||||
// Test whether we are able to call the function with the given arguments.
|
||||
constexpr traits::is_invokable_from_tuple<decltype(callable),
|
||||
constexpr traits::is_invocable_from_tuple<decltype(callable),
|
||||
std::tuple<Args...>>
|
||||
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<KeepArgs>;
|
||||
return env::partial_invoke_impl_shortcut(
|
||||
is_invokable, std::forward<T>(callable), std::forward<Args>(args)...);
|
||||
is_invocable, std::forward<T>(callable), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Invokes the given callable object with the given arguments
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user