mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
More
This commit is contained in:
parent
1cbfcbea6d
commit
96c9f7af99
@ -835,7 +835,7 @@ constexpr auto make_continuable(Continuation&& continuation) {
|
||||
template <typename... Args>
|
||||
auto make_ready_continuable(Args&&... args) {
|
||||
using detail::base::ready_continuation;
|
||||
using detail::traits::identity;
|
||||
using detail::identity;
|
||||
using detail::traits::unrefcv_t;
|
||||
return detail::base::attorney::create_from_raw(
|
||||
ready_continuation<unrefcv_t<Args>...>{std::forward<Args>(args)...},
|
||||
|
||||
@ -51,7 +51,7 @@ namespace std {
|
||||
namespace experimental {
|
||||
template <typename Data, typename... Args, typename... FunctionArgs>
|
||||
struct coroutine_traits<
|
||||
cti::continuable_base<Data, cti::detail::traits::identity<Args...>>,
|
||||
cti::continuable_base<Data, cti::detail::identity<Args...>>,
|
||||
FunctionArgs...> {
|
||||
|
||||
using promise_type =
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
||||
|
||||
#include <continuable/detail/core/types.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
namespace cti {
|
||||
/// \defgroup Primitives Primitives
|
||||
@ -56,6 +57,13 @@ namespace cti {
|
||||
/// ```
|
||||
/// \{
|
||||
|
||||
/// Represents the tag type that is used to specify the signature hint
|
||||
/// of a continuable_base or promise_base.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
template <typename... Args>
|
||||
using signature_arg_t = detail::identity<Args...>;
|
||||
|
||||
/// Represents the tag type that is used to query the continuation
|
||||
/// for whether it resolves the callback instantly with its arguments
|
||||
/// without having side effects.
|
||||
|
||||
@ -62,7 +62,7 @@ class promise_base
|
||||
/// \cond false
|
||||
;
|
||||
template <typename Data, typename... Args>
|
||||
class promise_base<Data, detail::traits::identity<Args...>>
|
||||
class promise_base<Data, detail::identity<Args...>>
|
||||
: detail::util::non_copyable
|
||||
/// \endcond
|
||||
{ // clang-format on
|
||||
|
||||
@ -158,7 +158,7 @@
|
||||
/// \since 1.0.0
|
||||
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
||||
cti::detail::testing::assert_async_types( \
|
||||
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
||||
CONTINUABLE, cti::detail::identity<__VA_ARGS__>{})
|
||||
|
||||
/// Asserts that the continuable is finished with the given exception
|
||||
///
|
||||
|
||||
@ -59,17 +59,12 @@ namespace cti {
|
||||
template <template <std::size_t, typename...> class CallbackWrapper,
|
||||
template <std::size_t, typename...> class ContinuationWrapper,
|
||||
typename... Args>
|
||||
class continuable_trait {
|
||||
|
||||
struct continuable_trait {
|
||||
using callback = CallbackWrapper<0U, void(Args...)&&,
|
||||
void(exception_arg_t, exception_t) &&>;
|
||||
|
||||
public:
|
||||
/// The promise type which is used to resolve continuations
|
||||
using promise = promise_base<callback, detail::traits::identity<Args...>>;
|
||||
|
||||
/// The continuable type for the given parameters.
|
||||
using continuable = continuable_base<
|
||||
using continuation = continuable_base<
|
||||
ContinuationWrapper<
|
||||
// Size the buffer for the small functor optimization so the
|
||||
// result itself fits in and guarantee that a pointer can
|
||||
@ -81,7 +76,7 @@ public:
|
||||
bool(is_ready_arg_t) const, //
|
||||
std::tuple<Args...>(query_arg_t) //
|
||||
>,
|
||||
detail::traits::identity<Args...>>;
|
||||
detail::identity<Args...>>;
|
||||
};
|
||||
/// \}
|
||||
} // namespace cti
|
||||
|
||||
@ -33,7 +33,10 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <function2/function2.hpp>
|
||||
#include <continuable/continuable-trait.hpp>
|
||||
#include <continuable/continuable-base.hpp>
|
||||
#include <continuable/continuable-primitives.hpp>
|
||||
#include <continuable/continuable-promise-base.hpp>
|
||||
#include <continuable/detail/other/erasure.hpp>
|
||||
|
||||
namespace cti {
|
||||
/// \defgroup Types Types
|
||||
@ -41,66 +44,40 @@ namespace cti {
|
||||
/// cti::promise promise\endlink facility for type erasure.
|
||||
/// \{
|
||||
|
||||
namespace detail {
|
||||
/// A type erasure which isn't size adjusted and move only
|
||||
template <std::size_t, typename... Args>
|
||||
class type_erasure : public fu2::unique_function<Args...> {
|
||||
public:
|
||||
using fu2::unique_function<Args...>::unique_function;
|
||||
using fu2::unique_function<Args...>::operator=;
|
||||
using fu2::unique_function<Args...>::operator();
|
||||
};
|
||||
|
||||
/// A function which is size adjusted and move only
|
||||
template <std::size_t Size, typename... Args>
|
||||
class sized_type_erasure
|
||||
: public fu2::function_base<true, false, Size, true, false, Args...> {
|
||||
|
||||
public:
|
||||
using fu2::function_base<true, false, Size, //
|
||||
true, false, Args...>::function_base;
|
||||
using fu2::function_base<true, false, Size, //
|
||||
true, false, Args...>::operator=;
|
||||
using fu2::function_base<true, false, Size, //
|
||||
true, false, Args...>::operator();
|
||||
};
|
||||
|
||||
/// We adjust the internal capacity of the outer function wrapper so
|
||||
/// we don't have to allocate twice when using `continuable<...>`.
|
||||
template <typename... Args>
|
||||
using unique_trait_of = continuable_trait< //
|
||||
type_erasure, sized_type_erasure,
|
||||
Args... //
|
||||
>;
|
||||
|
||||
/// A type erasure for work objects
|
||||
class work_type_erasure : public fu2::unique_function<void()> {
|
||||
public:
|
||||
using fu2::unique_function<void()>::unique_function;
|
||||
using fu2::unique_function<void()>::operator=;
|
||||
using fu2::unique_function<void()>::operator();
|
||||
};
|
||||
} // namespace detail
|
||||
/// Deduces to the preferred continuation capacity for a possible
|
||||
/// small functor optimization. The given capacity size is always enough to
|
||||
/// to avoid any allocation when storing ready a continuable_base.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
// template <typename... Args>
|
||||
// using continuation_capacity = detail::erasure::continuation_capacity<Args...>;
|
||||
|
||||
/// Defines a non-copyable continuation type which uses the
|
||||
/// function2 backend for type erasure.
|
||||
///
|
||||
/// Usable like: `continuable<int, float>`
|
||||
template <typename... Args>
|
||||
using continuable = typename detail::unique_trait_of<Args...>::continuable;
|
||||
using continuable = continuable_base<detail::erasure::continuation<Args...>, //
|
||||
signature_arg_t<Args...>>;
|
||||
|
||||
/// Defines a non-copyable promise type which is using the
|
||||
/// function2 backend for type erasure.
|
||||
///
|
||||
/// Usable like: `promise<int, float>`
|
||||
template <typename... Args>
|
||||
using promise = typename detail::unique_trait_of<Args...>::promise;
|
||||
using promise = promise_base<detail::erasure::callback<Args...>, //
|
||||
signature_arg_t<Args...>>;
|
||||
|
||||
/// Defines a non-copyable type erasure which is capable of carrying
|
||||
/// callable objects passed to executors.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
using work = detail::work_type_erasure;
|
||||
class work : public fu2::unique_function<void()> {
|
||||
public:
|
||||
using fu2::unique_function<void()>::unique_function;
|
||||
using fu2::unique_function<void()>::operator=;
|
||||
using fu2::unique_function<void()>::operator();
|
||||
};
|
||||
|
||||
// TODO channel
|
||||
// TODO sink
|
||||
|
||||
@ -52,7 +52,6 @@ namespace cti {}
|
||||
#include <continuable/continuable-promise-base.hpp>
|
||||
#include <continuable/continuable-promisify.hpp>
|
||||
#include <continuable/continuable-result.hpp>
|
||||
#include <continuable/continuable-trait.hpp>
|
||||
#include <continuable/continuable-transforms.hpp>
|
||||
#include <continuable/continuable-traverse-async.hpp>
|
||||
#include <continuable/continuable-traverse.hpp>
|
||||
|
||||
@ -75,13 +75,13 @@ T&& unpack_lazy(container::flat_variant<T>&& value) {
|
||||
template <typename Continuable>
|
||||
class continuable_box;
|
||||
template <typename Data>
|
||||
class continuable_box<continuable_base<Data, traits::identity<>>> {
|
||||
class continuable_box<continuable_base<Data, identity<>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<>> continuable_;
|
||||
continuable_base<Data, identity<>> continuable_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<>>&& continuable)
|
||||
continuable_base<Data, identity<>>&& continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
|
||||
@ -101,14 +101,14 @@ public:
|
||||
}
|
||||
};
|
||||
template <typename Data, typename First>
|
||||
class continuable_box<continuable_base<Data, traits::identity<First>>> {
|
||||
class continuable_box<continuable_base<Data, identity<First>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<First>> continuable_;
|
||||
continuable_base<Data, identity<First>> continuable_;
|
||||
lazy_value_t<First> first_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<First>>&& continuable)
|
||||
continuable_base<Data, identity<First>>&& continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
|
||||
@ -130,14 +130,14 @@ public:
|
||||
};
|
||||
template <typename Data, typename First, typename Second, typename... Rest>
|
||||
class continuable_box<
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>>> {
|
||||
continuable_base<Data, identity<First, Second, Rest...>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>> continuable_;
|
||||
continuable_base<Data, identity<First, Second, Rest...>> continuable_;
|
||||
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>>&&
|
||||
continuable_base<Data, identity<First, Second, Rest...>>&&
|
||||
continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
@ -209,12 +209,12 @@ constexpr auto unbox_continuables(Args&&... args) {
|
||||
|
||||
namespace detail {
|
||||
template <typename Callback, typename Data>
|
||||
constexpr auto finalize_impl(traits::identity<void>, Callback&& callback,
|
||||
constexpr auto finalize_impl(identity<void>, Callback&& callback,
|
||||
Data&&) {
|
||||
return std::forward<Callback>(callback)();
|
||||
}
|
||||
template <typename... Args, typename Callback, typename Data>
|
||||
constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||
constexpr auto finalize_impl(identity<std::tuple<Args...>>,
|
||||
Callback&& callback, Data&& data) {
|
||||
// Call the final callback with the cleaned result
|
||||
return traits::unpack(std::forward<Callback>(callback),
|
||||
@ -223,7 +223,7 @@ constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||
|
||||
struct hint_mapper {
|
||||
template <typename... T>
|
||||
constexpr auto operator()(T...) -> traits::identity<T...> {
|
||||
constexpr auto operator()(T...) -> identity<T...> {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
@ -233,7 +233,7 @@ template <typename Callback, typename Data>
|
||||
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
||||
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
||||
// Guard the final result against void
|
||||
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
||||
return detail::finalize_impl(identity<std::decay_t<result_t>>{},
|
||||
std::forward<Callback>(callback),
|
||||
std::forward<Data>(data));
|
||||
}
|
||||
|
||||
@ -88,30 +88,30 @@ private:
|
||||
|
||||
struct result_deducer {
|
||||
template <typename T>
|
||||
static auto deduce_one(std::false_type, traits::identity<T>) {
|
||||
static auto deduce_one(std::false_type, identity<T>) {
|
||||
static_assert(traits::fail<T>::value,
|
||||
"Non continuable types except tuple like and homogeneous "
|
||||
"containers aren't allowed inside an any expression!");
|
||||
}
|
||||
template <typename T>
|
||||
static auto deduce_one(std::true_type, traits::identity<T> id) {
|
||||
static auto deduce_one(std::true_type, identity<T> id) {
|
||||
return base::annotation_of(id);
|
||||
}
|
||||
template <typename T>
|
||||
static auto deduce(traversal::container_category_tag<false, false>,
|
||||
traits::identity<T> id) {
|
||||
identity<T> id) {
|
||||
return deduce_one<T>(base::is_continuable<T>{}, id);
|
||||
}
|
||||
|
||||
/// Deduce a homogeneous container
|
||||
template <bool IsTupleLike, typename T>
|
||||
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
||||
traits::identity<T>) {
|
||||
identity<T>) {
|
||||
|
||||
// Deduce the containing type
|
||||
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
||||
return deduce(traversal::container_category_of_t<element_t>{},
|
||||
traits::identity<element_t>{});
|
||||
identity<element_t>{});
|
||||
}
|
||||
|
||||
template <typename First, typename... T>
|
||||
@ -125,19 +125,19 @@ struct result_deducer {
|
||||
|
||||
template <std::size_t... I, typename T>
|
||||
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
||||
traits::identity<T>) {
|
||||
identity<T>) {
|
||||
|
||||
return deduce_same_hints(deduce(
|
||||
traversal::container_category_of_t<
|
||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
||||
traits::identity<
|
||||
identity<
|
||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
||||
}
|
||||
|
||||
/// Traverse tuple like container
|
||||
template <typename T>
|
||||
static auto deduce(traversal::container_category_tag<false, true>,
|
||||
traits::identity<T> id) {
|
||||
identity<T> id) {
|
||||
|
||||
constexpr auto const size = std::tuple_size<T>::value;
|
||||
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
||||
@ -172,7 +172,7 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
||||
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
||||
traits::identity<std::decay_t<Connection>>{})){};
|
||||
identity<std::decay_t<Connection>>{})){};
|
||||
|
||||
return base::attorney::create_from(
|
||||
[connection =
|
||||
|
||||
@ -42,7 +42,7 @@ struct annotation_trait;
|
||||
|
||||
/// Specialization for a present signature hint
|
||||
template <typename... Args>
|
||||
struct annotation_trait<traits::identity<Args...>> {
|
||||
struct annotation_trait<identity<Args...>> {
|
||||
template <typename Continuable>
|
||||
static Continuable&& finish(Continuable&& continuable) {
|
||||
return std::forward<Continuable>(continuable);
|
||||
@ -55,9 +55,9 @@ namespace hints {
|
||||
///
|
||||
/// This is the overload taking an arbitrary amount of args
|
||||
template <typename... HintArgs>
|
||||
struct from_args : std::common_type<traits::identity<HintArgs...>> {};
|
||||
struct from_args : std::common_type<identity<HintArgs...>> {};
|
||||
template <>
|
||||
struct from_args<void> : std::common_type<traits::identity<>> {};
|
||||
struct from_args<void> : std::common_type<identity<>> {};
|
||||
} // namespace hints
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -122,7 +122,7 @@ struct ready_continuation<> {
|
||||
template <typename Hint, typename Continuation>
|
||||
struct proxy_continuable;
|
||||
template <typename... Args, typename Continuation>
|
||||
struct proxy_continuable<traits::identity<Args...>, Continuation>
|
||||
struct proxy_continuable<identity<Args...>, Continuation>
|
||||
: Continuation {
|
||||
|
||||
explicit proxy_continuable(Continuation continuation)
|
||||
@ -192,9 +192,9 @@ struct attorney {
|
||||
|
||||
/// Returns the signature hint of the given continuable
|
||||
template <typename Data, typename... Args>
|
||||
constexpr traits::identity<Args...>
|
||||
annotation_of(traits::identity<continuable_base<Data, //
|
||||
traits::identity<Args...>>>) {
|
||||
constexpr identity<Args...>
|
||||
annotation_of(identity<continuable_base<Data, //
|
||||
identity<Args...>>>) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -275,30 +275,30 @@ constexpr void invoke_no_except(T&& callable, Args&&... args) noexcept {
|
||||
}
|
||||
|
||||
template <typename... Args, typename T>
|
||||
void invoke_void_no_except(traits::identity<exception_arg_t, Args...>,
|
||||
void invoke_void_no_except(identity<exception_arg_t, Args...>,
|
||||
T&& /*callable*/) noexcept {
|
||||
// Don't invoke the next failure handler when being in an exception handler
|
||||
}
|
||||
template <typename... Args, typename T>
|
||||
void invoke_void_no_except(traits::identity<Args...>, T&& callable) noexcept {
|
||||
void invoke_void_no_except(identity<Args...>, T&& callable) noexcept {
|
||||
std::forward<T>(callable)();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_invoker(T&& invoke, traits::identity<Args...>) {
|
||||
return invoker<std::decay_t<T>, traits::identity<Args...>>(
|
||||
constexpr auto make_invoker(T&& invoke, identity<Args...>) {
|
||||
return invoker<std::decay_t<T>, identity<Args...>>(
|
||||
std::forward<T>(invoke));
|
||||
}
|
||||
|
||||
/// - continuable<?...> -> result(next_callback);
|
||||
template <typename Data, typename Annotation>
|
||||
constexpr auto
|
||||
invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||
invoker_of(identity<continuable_base<Data, Annotation>>) {
|
||||
/// Get the hint of the unwrapped returned continuable
|
||||
using Type =
|
||||
decltype(std::declval<continuable_base<Data, Annotation>>().finish());
|
||||
|
||||
auto constexpr const hint = base::annotation_of(traits::identify<Type>{});
|
||||
auto constexpr const hint = base::annotation_of(identify<Type>{});
|
||||
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
@ -317,7 +317,7 @@ invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||
|
||||
/// - ? -> next_callback(?)
|
||||
template <typename T>
|
||||
constexpr auto invoker_of(traits::identity<T>) {
|
||||
constexpr auto invoker_of(identity<T>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -329,26 +329,26 @@ constexpr auto invoker_of(traits::identity<T>) {
|
||||
std::move(result));
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identify<T>{});
|
||||
identify<T>{});
|
||||
}
|
||||
|
||||
/// - void -> next_callback()
|
||||
inline auto invoker_of(traits::identity<void>) {
|
||||
inline auto invoker_of(identity<void>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
invoke_callback(std::forward<decltype(callback)>(callback),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
invoke_void_no_except(
|
||||
traits::identity<traits::unrefcv_t<decltype(args)>...>{},
|
||||
identity<traits::unrefcv_t<decltype(args)>...>{},
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - empty_result -> <cancel>
|
||||
inline auto invoker_of(traits::identity<empty_result>) {
|
||||
inline auto invoker_of(identity<empty_result>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
(void)next_callback;
|
||||
@ -362,11 +362,11 @@ inline auto invoker_of(traits::identity<empty_result>) {
|
||||
(void)result;
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - exceptional_result -> <throw>
|
||||
inline auto invoker_of(traits::identity<exceptional_result>) {
|
||||
inline auto invoker_of(identity<exceptional_result>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
util::unused(callback, next_callback, args...);
|
||||
@ -381,12 +381,12 @@ inline auto invoker_of(traits::identity<exceptional_result>) {
|
||||
std::move(result).get_exception());
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - result<?...> -> next_callback(?...)
|
||||
template <typename... Args>
|
||||
auto invoker_of(traits::identity<result<Args...>>) {
|
||||
auto invoker_of(identity<result<Args...>>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -416,7 +416,7 @@ auto invoker_of(traits::identity<result<Args...>>) {
|
||||
// asynchronous chain.
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<Args...>{});
|
||||
identity<Args...>{});
|
||||
}
|
||||
|
||||
/// Returns a sequenced invoker which is able to invoke
|
||||
@ -443,15 +443,15 @@ inline auto sequenced_unpack_invoker() {
|
||||
|
||||
// - std::pair<?, ?> -> next_callback(?, ?)
|
||||
template <typename First, typename Second>
|
||||
constexpr auto invoker_of(traits::identity<std::pair<First, Second>>) {
|
||||
constexpr auto invoker_of(identity<std::pair<First, Second>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(),
|
||||
traits::identity<First, Second>{});
|
||||
identity<First, Second>{});
|
||||
}
|
||||
|
||||
// - std::tuple<?...> -> next_callback(?...)
|
||||
template <typename... Args>
|
||||
constexpr auto invoker_of(traits::identity<std::tuple<Args...>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(), traits::identity<Args...>{});
|
||||
constexpr auto invoker_of(identity<std::tuple<Args...>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(), identity<Args...>{});
|
||||
}
|
||||
|
||||
#undef CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -510,7 +510,7 @@ template <handle_results HandleResults, typename Base, typename Hint>
|
||||
struct result_handler_base;
|
||||
template <typename Base, typename... Args>
|
||||
struct result_handler_base<handle_results::no, Base,
|
||||
traits::identity<Args...>> {
|
||||
identity<Args...>> {
|
||||
void operator()(Args... args) && {
|
||||
// Forward the arguments to the next callback
|
||||
std::move(static_cast<Base*>(this)->next_callback_)(std::move(args)...);
|
||||
@ -518,13 +518,13 @@ struct result_handler_base<handle_results::no, Base,
|
||||
};
|
||||
template <typename Base, typename... Args>
|
||||
struct result_handler_base<handle_results::yes, Base,
|
||||
traits::identity<Args...>> {
|
||||
identity<Args...>> {
|
||||
/// The operator which is called when the result was provided
|
||||
void operator()(Args... args) && {
|
||||
// In order to retrieve the correct decorator we must know what the
|
||||
// result type is.
|
||||
constexpr auto result =
|
||||
traits::identify<decltype(decoration::invoke_callback(
|
||||
identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_),
|
||||
std::move(args)...))>{};
|
||||
|
||||
@ -556,7 +556,7 @@ struct error_handler_base<handle_errors::forward, Base> {
|
||||
/// The operator which is called when an error occurred
|
||||
void operator()(exception_arg_t, exception_t exception) && {
|
||||
constexpr auto result =
|
||||
traits::identify<decltype(decoration::invoke_callback(
|
||||
identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_), exception_arg_t{},
|
||||
std::move(exception)))>{};
|
||||
|
||||
@ -580,16 +580,16 @@ struct callback_base;
|
||||
template <typename... Args, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||
typename NextCallback>
|
||||
struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
struct callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>
|
||||
: proto::result_handler_base<
|
||||
HandleResults,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>,
|
||||
traits::identity<Args...>>,
|
||||
identity<Args...>>,
|
||||
proto::error_handler_base<
|
||||
HandleErrors,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>>,
|
||||
util::non_copyable {
|
||||
|
||||
@ -606,14 +606,14 @@ struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
/// Pull the result handling operator() in
|
||||
using proto::result_handler_base<
|
||||
HandleResults,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>,
|
||||
traits::identity<Args...>>::operator();
|
||||
identity<Args...>>::operator();
|
||||
|
||||
/// Pull the error handling operator() in
|
||||
using proto::error_handler_base<
|
||||
HandleErrors,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>>::operator();
|
||||
|
||||
/// Resolves the continuation with the given values
|
||||
@ -684,21 +684,21 @@ struct final_callback : util::non_copyable {
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto
|
||||
next_hint_of(std::integral_constant<handle_results, handle_results::yes>,
|
||||
traits::identity<T> /*callback*/,
|
||||
traits::identity<Args...> /*current*/) {
|
||||
identity<T> /*callback*/,
|
||||
identity<Args...> /*current*/) {
|
||||
// Partial Invoke the given callback
|
||||
using Result = decltype(
|
||||
decoration::invoke_callback(std::declval<T>(), std::declval<Args>()...));
|
||||
|
||||
// Return the hint of thr given invoker
|
||||
return decltype(decoration::invoker_of(traits::identify<Result>{}).hint()){};
|
||||
return decltype(decoration::invoker_of(identify<Result>{}).hint()){};
|
||||
}
|
||||
/// Don't progress the hint when we don't continue
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto
|
||||
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
|
||||
traits::identity<T> /*callback*/,
|
||||
traits::identity<Args...> current) {
|
||||
identity<T> /*callback*/,
|
||||
identity<Args...> current) {
|
||||
return current;
|
||||
}
|
||||
|
||||
@ -730,8 +730,8 @@ struct chained_continuation;
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Continuation, typename Callback,
|
||||
typename Executor>
|
||||
struct chained_continuation<traits::identity<Args...>,
|
||||
traits::identity<NextArgs...>, HandleResults,
|
||||
struct chained_continuation<identity<Args...>,
|
||||
identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, Continuation, Callback, Executor> {
|
||||
|
||||
Continuation continuation_;
|
||||
@ -761,7 +761,7 @@ struct chained_continuation<traits::identity<Args...>,
|
||||
// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||
// - Callback: [](std::string) { }
|
||||
// - NextCallback: []() { }
|
||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
||||
auto proxy = callbacks::make_callback<identity<Args...>,
|
||||
HandleResults, HandleErrors>(
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
@ -793,7 +793,7 @@ struct chained_continuation<traits::identity<Args...>,
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor>
|
||||
struct chained_continuation<
|
||||
traits::identity<Args...>, traits::identity<NextArgs...>, HandleResults,
|
||||
identity<Args...>, identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, ready_continuation<Args...>, Callback, Executor> {
|
||||
|
||||
ready_continuation<Args...> continuation_;
|
||||
@ -815,7 +815,7 @@ struct chained_continuation<
|
||||
|
||||
template <typename NextCallback>
|
||||
void operator()(NextCallback&& next_callback) {
|
||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
||||
auto proxy = callbacks::make_callback<identity<Args...>,
|
||||
HandleResults, HandleErrors>(
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
@ -851,10 +851,10 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||
static_assert(is_continuable<std::decay_t<Continuation>>{},
|
||||
"Expected a continuation!");
|
||||
|
||||
using Hint = decltype(base::annotation_of(traits::identify<Continuation>()));
|
||||
using Hint = decltype(base::annotation_of(identify<Continuation>()));
|
||||
constexpr auto next_hint =
|
||||
next_hint_of(std::integral_constant<handle_results, HandleResults>{},
|
||||
traits::identify<decltype(callback)>{}, Hint{});
|
||||
identify<decltype(callback)>{}, Hint{});
|
||||
|
||||
auto ownership = attorney::ownership_of(continuation);
|
||||
auto data =
|
||||
@ -885,11 +885,11 @@ void finalize_continuation(Continuation&& continuation) {
|
||||
template <typename Data, typename Annotation, typename Continuation>
|
||||
struct can_accept_continuation : std::false_type {};
|
||||
template <typename Data, typename... Args, typename Continuation>
|
||||
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
|
||||
struct can_accept_continuation<Data, identity<Args...>, Continuation>
|
||||
: traits::conjunction<
|
||||
traits::is_invocable<Continuation, callbacks::final_callback>,
|
||||
std::is_convertible<
|
||||
proxy_continuable<traits::identity<Args...>, Continuation>,
|
||||
proxy_continuable<identity<Args...>, Continuation>,
|
||||
Data>> {};
|
||||
|
||||
/// Workaround for GCC bug:
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
#include <utility>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||
|
||||
@ -57,7 +57,7 @@ using std::experimental::coroutine_handle;
|
||||
template <typename T>
|
||||
struct result_from_identity;
|
||||
template <typename... T>
|
||||
struct result_from_identity<traits::identity<T...>> {
|
||||
struct result_from_identity<identity<T...>> {
|
||||
using result_t = result<T...>;
|
||||
};
|
||||
|
||||
@ -65,7 +65,7 @@ struct result_from_identity<traits::identity<T...>> {
|
||||
/// for waiting on a continuable in a stackless coroutine.
|
||||
template <typename Continuable>
|
||||
class awaitable {
|
||||
using hint_t = decltype(base::annotation_of(traits::identify<Continuable>{}));
|
||||
using hint_t = decltype(base::annotation_of(identify<Continuable>{}));
|
||||
using result_t = typename result_from_identity<hint_t>::result_t;
|
||||
|
||||
/// The continuable which is invoked upon suspension
|
||||
|
||||
97
include/continuable/detail/other/erasure.hpp
Normal file
97
include/continuable/detail/other/erasure.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
#define CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
#include <function2/function2.hpp>
|
||||
#include <continuable/detail/core/base.hpp>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/traits.hpp>
|
||||
#include <continuable/detail/utility/util.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
namespace erasure {
|
||||
/*template <typename... Args>
|
||||
using continuation_capacity = std::integral_constant<
|
||||
std::size_t, (sizeof(base::ready_continuation<Args...>) < sizeof(void*)
|
||||
? sizeof(void*)
|
||||
: sizeof(base::ready_continuation<Args...>))>;*/
|
||||
|
||||
template <std::size_t Size>
|
||||
struct sized {
|
||||
template <typename... Args>
|
||||
using erasure_base_t = //
|
||||
fu2::function_base<true, false, Size, //
|
||||
true, false, Args...>;
|
||||
};
|
||||
|
||||
template <template <typename...> class Wrapper, typename... Args>
|
||||
using callback_of_t = Wrapper<void(Args...)&&, //
|
||||
void(exception_arg_t, exception_t) &&>;
|
||||
|
||||
template <typename... Args>
|
||||
using callback_base_t = callback_of_t<sized<0>::erasure_base_t, Args...>;
|
||||
|
||||
template <typename... Args>
|
||||
class callback : public callback_base_t<Args...> {
|
||||
public:
|
||||
using callback_base_t<Args...>::callback_base_t;
|
||||
using callback_base_t<Args...>::operator=;
|
||||
using callback_base_t<Args...>::operator();
|
||||
};
|
||||
|
||||
template <template <typename...> class Wrapper, typename Promise,
|
||||
typename... Args>
|
||||
using continuation_of_t = Wrapper<void(Promise), //
|
||||
bool(is_ready_arg_t) const, //
|
||||
std::tuple<Args...>(query_arg_t)>;
|
||||
|
||||
template <typename... Args>
|
||||
using continuation_base_t =
|
||||
continuation_of_t<sized<0 /*
|
||||
continuation_capacity<Args...>::value*/>::erasure_base_t,
|
||||
promise_base<callback<Args...>, signature_arg_t<Args>...>,
|
||||
Args...>;
|
||||
|
||||
template <typename... Args>
|
||||
class continuation : public continuation_base_t<Args...> {
|
||||
public:
|
||||
using continuation_base_t<Args...>::callback_base_t;
|
||||
using continuation_base_t<Args...>::operator=;
|
||||
using continuation_base_t<Args...>::operator();
|
||||
};
|
||||
} // namespace erasure
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
@ -179,15 +179,15 @@ template <typename... Expected>
|
||||
struct assert_async_types_validator {
|
||||
template <typename... Actual>
|
||||
void operator()(Actual...) {
|
||||
static_assert(std::is_same<traits::identity<Actual...>,
|
||||
traits::identity<Expected...>>::value,
|
||||
static_assert(std::is_same<identity<Actual...>,
|
||||
identity<Expected...>>::value,
|
||||
"The called arguments don't match with the expected ones!");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C, typename... Args>
|
||||
void assert_async_types(C&& continuable,
|
||||
traits::identity<Args...> /*expected*/) {
|
||||
identity<Args...> /*expected*/) {
|
||||
assert_async_validation(std::forward<C>(continuable),
|
||||
assert_async_types_validator<Args...>{});
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ template <typename Hint>
|
||||
class promise_callback;
|
||||
|
||||
template <typename... Args>
|
||||
class promise_callback<traits::identity<Args...>>
|
||||
class promise_callback<identity<Args...>>
|
||||
: public future_trait<Args...> {
|
||||
|
||||
typename future_trait<Args...>::promise_t promise_;
|
||||
@ -119,7 +119,7 @@ template <typename Data, typename Annotation>
|
||||
auto as_future(continuable_base<Data, Annotation>&& continuable) {
|
||||
// Create the promise which is able to supply the current arguments
|
||||
constexpr auto const hint =
|
||||
base::annotation_of(traits::identify<decltype(continuable)>{});
|
||||
base::annotation_of(identify<decltype(continuable)>{});
|
||||
|
||||
promise_callback<std::decay_t<decltype(hint)>> callback;
|
||||
(void)hint;
|
||||
|
||||
@ -62,7 +62,7 @@ template <typename T>
|
||||
using align_of_helper = std::integral_constant<std::size_t, alignof(T)>;
|
||||
|
||||
template <typename... T>
|
||||
constexpr auto storage_of_impl(traits::identity<T...>) {
|
||||
constexpr auto storage_of_impl(identity<T...>) {
|
||||
constexpr auto size = max_element_of({(size_of_helper<T>::value)...});
|
||||
constexpr auto align = max_element_of({(align_of_helper<T>::value)...});
|
||||
return std::aligned_storage_t<size, align>{};
|
||||
@ -70,7 +70,7 @@ constexpr auto storage_of_impl(traits::identity<T...>) {
|
||||
|
||||
/// Declares the aligned storage union for the given types
|
||||
template <typename... T>
|
||||
using storage_of_t = decltype(storage_of_impl(traits::identity<T...>{}));
|
||||
using storage_of_t = decltype(storage_of_impl(identity<T...>{}));
|
||||
|
||||
/// The value fpr the empty slot
|
||||
using slot_t = std::uint8_t;
|
||||
|
||||
54
include/continuable/detail/utility/identity.hpp
Normal file
54
include/continuable/detail/utility/identity.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
#define CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
#include <continuable/detail/features.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
/// A tagging type for wrapping other types
|
||||
template <typename... T>
|
||||
struct identity {};
|
||||
|
||||
template <typename>
|
||||
struct is_identity : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_identity<identity<Args...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||
identity<std::decay_t<T>>>;
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
@ -36,6 +36,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
@ -69,19 +70,6 @@ auto make_flat_tuple(T&&... args) {
|
||||
return std::tuple<T...>{std::forward<T>(args)...};
|
||||
}
|
||||
|
||||
/// A tagging type for wrapping other types
|
||||
template <typename... T>
|
||||
struct identity {};
|
||||
|
||||
template <typename>
|
||||
struct is_identity : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_identity<identity<Args...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||
identity<std::decay_t<T>>>;
|
||||
|
||||
#if defined(CONTINUABLE_HAS_CXX17_VOID_T)
|
||||
using std::void_t;
|
||||
#else
|
||||
|
||||
@ -134,7 +134,7 @@ TYPED_TEST(single_dimension_tests, are_exceptions_partial_applyable) {
|
||||
handled = false;
|
||||
ASSERT_ASYNC_INCOMPLETION(
|
||||
this->supply_exception(supply_test_exception(),
|
||||
detail::traits::identity<int, int>{})
|
||||
detail::identity<int, int>{})
|
||||
.fail([&]() -> result<int, int> {
|
||||
EXPECT_FALSE(handled);
|
||||
handled = true;
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include <continuable/continuable-testing.hpp>
|
||||
#include <continuable/continuable.hpp>
|
||||
|
||||
using cti::detail::traits::identity;
|
||||
using cti::detail::identity;
|
||||
using cti::detail::util::unused;
|
||||
|
||||
inline auto to_hint(identity<> /*hint*/) {
|
||||
@ -48,7 +48,7 @@ auto to_hint(identity<Args...> hint) {
|
||||
template <typename... Args>
|
||||
auto supplier_of(Args&&... args) {
|
||||
return [values = std::make_tuple(std::forward<Args>(args)...)](
|
||||
auto&& promise) mutable {
|
||||
auto&& promise) mutable {
|
||||
cti::detail::traits::unpack(
|
||||
[&](auto&&... passed) {
|
||||
promise.set_value(std::forward<decltype(passed)>(passed)...);
|
||||
@ -113,12 +113,12 @@ struct provide_copyable {
|
||||
struct provide_unique {
|
||||
template <typename... Args, typename... Hint, typename T>
|
||||
auto make(identity<Args...>, identity<Hint...>, T&& callback) {
|
||||
return cti::make_continuable<Hint...>(
|
||||
[callback = std::forward<T>(callback),
|
||||
guard = std::make_unique<int>(0)](auto&&... args) mutable {
|
||||
(void)(*guard);
|
||||
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
return cti::make_continuable<Hint...>([
|
||||
callback = std::forward<T>(callback), guard = std::make_unique<int>(0)
|
||||
](auto&&... args) mutable {
|
||||
(void)(*guard);
|
||||
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user