Fix the build

This commit is contained in:
Denis Blank 2018-11-27 16:38:19 +01:00
parent f1f9d61952
commit bb7112eec2
2 changed files with 143 additions and 58 deletions

View File

@ -326,7 +326,7 @@ constexpr auto invoker_of(traits::identity<std::tuple<Args...>>) {
inline auto exception_invoker_of(traits::identity<void>) noexcept {
return [](auto&& callback, auto&& next_callback, auto&&... args) {
CONTINUABLE_BLOCK_TRY_BEGIN
util::partial_invoke(std::forward<decltype(callback)>(callback),
util::invoke(std::forward<decltype(callback)>(callback),
std::forward<decltype(args)>(args)...);
// The legacy behaviour is not to proceed the chain
@ -336,9 +336,81 @@ inline auto exception_invoker_of(traits::identity<void>) noexcept {
};
}
template <typename Other>
auto exception_invoker_of(Other other) noexcept {
return invoker_of(other);
/*template <typename... Args>
auto exception_invoker_of(traits::identity<result<Args...>> id) noexcept {
return invoker_of(id);
}*/
/// - empty_result -> <cancel>
inline auto exception_invoker_of(traits::identity<empty_result>) {
return make_invoker(
[](auto&& callback, auto&& next_callback, auto&&... args) {
(void)next_callback;
CONTINUABLE_BLOCK_TRY_BEGIN
empty_result result =
util::invoke(std::forward<decltype(callback)>(callback),
std::forward<decltype(args)>(args)...);
// Don't invoke anything here since returning an empty result
// cancels the asynchronous chain effectively.
(void)result;
CONTINUABLE_BLOCK_TRY_END
},
traits::identity<>{});
}
/// - exceptional_result -> <throw>
inline auto exception_invoker_of(traits::identity<exceptional_result>) {
return make_invoker(
[](auto&& callback, auto&& next_callback, auto&&... args) {
util::unused(callback, next_callback, args...);
CONTINUABLE_BLOCK_TRY_BEGIN
exceptional_result result =
util::invoke(std::forward<decltype(callback)>(callback),
std::forward<decltype(args)>(args)...);
// Forward the exception to the next available handler
invoke_no_except(std::forward<decltype(next_callback)>(next_callback),
exception_arg_t{},
std::move(result).get_exception());
CONTINUABLE_BLOCK_TRY_END
},
traits::identity<>{});
}
/// - result<?...> -> next_callback(?...)
template <typename... Args>
auto exception_invoker_of(traits::identity<result<Args...>>) {
return make_invoker(
[](auto&& callback, auto&& next_callback, auto&&... args) {
CONTINUABLE_BLOCK_TRY_BEGIN
result<Args...> result =
util::invoke(std::forward<decltype(callback)>(callback),
std::forward<decltype(args)>(args)...);
if (result.is_value()) {
// Workaround for MSVC not capturing the reference
// correctly inside the lambda.
using Next = decltype(next_callback);
result_trait<Args...>::visit(
std::move(result), //
[&](auto&&... values) {
invoke_no_except(std::forward<Next>(next_callback),
std::forward<decltype(values)>(values)...);
});
} else if (result.is_exception()) {
// Forward the exception to the next available handler
invoke_no_except(
std::forward<decltype(next_callback)>(next_callback),
exception_arg_t{}, std::move(result).get_exception());
}
// Otherwise the result is empty and we are cancelling our
// asynchronous chain.
CONTINUABLE_BLOCK_TRY_END
},
traits::identity<Args...>{});
}
#undef CONTINUABLE_BLOCK_TRY_BEGIN
@ -587,16 +659,25 @@ next_hint_of(std::integral_constant<handle_results, handle_results::no>,
return current;
}
namespace detail {
template <typename Callable>
struct exception_stripper_proxy {
Callable callable_;
template <typename... Args>
auto operator()(exception_arg_t, Args&&... args)
-> decltype(util::invoke(std::declval<Callable>(), //
std::declval<Args>()...)) {
return util::invoke(std::move(callable_), //
std::forward<decltype(args)>(args)...);
};
};
} // namespace detail
/// Removes the exception_arg_t from the arguments passed to the given callable
template <typename Callable>
auto strip_exception_arg(Callable&& callable) {
return [callable = std::forward<Callable>(callable)] //
(exception_arg_t, auto&&... args) mutable
-> decltype(util::invoke(std::declval<Callable>(), //
std::declval<decltype(args)>()...)) {
return util::invoke(std::move(callable), //
std::forward<decltype(args)>(args)...);
};
using proxy = detail::exception_stripper_proxy<traits::unrefcv_t<Callable>>;
return proxy{std::forward<Callable>(callable)};
}
/// Chains a callback together with a continuation and returns a continuation:

View File

@ -64,17 +64,19 @@ auto forward_except_last(T&& sequenceable) {
return forward_except_last_impl(std::forward<T>(sequenceable), sequence);
}
/// We are able to call the callable with the arguments given in the tuple
template <typename T, typename... Args>
auto partial_invoke_impl(std::true_type, T&& callable,
template <std::size_t Keep>
struct invocation_env {
/// We are able to call the callable with the arguments given in the tuple
template <typename T, typename... Args>
static auto partial_invoke_impl(std::true_type, T&& callable,
std::tuple<Args...> args) {
return traits::unpack(std::forward<T>(callable), std::move(args));
}
}
/// We were unable to call the callable with the arguments in the tuple.
/// Remove the last argument from the tuple and try it again.
template <typename T, typename... Args>
auto partial_invoke_impl(std::false_type, T&& callable,
/// We were unable to call the callable with the arguments in the tuple.
/// Remove the last argument from the tuple and try it again.
template <typename T, typename... Args>
static auto partial_invoke_impl(std::false_type, T&& callable,
std::tuple<Args...> args) {
// If you are encountering this assertion you tried to attach a callback
@ -85,7 +87,7 @@ auto partial_invoke_impl(std::false_type, T&& callable,
// std::move(c).then([](std::vector<int> v) { /*...*/ })
// ```
static_assert(
sizeof...(Args) > 0,
sizeof...(Args) > Keep,
"There is no way to call the given object with these arguments!");
// Remove the last argument from the tuple
@ -97,26 +99,27 @@ auto partial_invoke_impl(std::false_type, T&& callable,
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
std::move(next));
}
}
/// Shortcut - we can call the callable directly
template <typename T, typename... Args>
auto partial_invoke_impl_shortcut(std::true_type, T&& callable,
/// Shortcut - we can call the callable directly
template <typename T, typename... Args>
static auto partial_invoke_impl_shortcut(std::true_type, T&& callable,
Args&&... args) {
return std::forward<T>(callable)(std::forward<Args>(args)...);
}
}
/// Failed shortcut - we were unable to invoke the callable with the
/// original arguments.
template <typename T, typename... Args>
auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
/// Failed shortcut - we were unable to invoke the callable with the
/// original arguments.
template <typename T, typename... Args>
static auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
Args&&... args) {
// Our shortcut failed, convert the arguments into a forwarding tuple
return partial_invoke_impl(
failed, std::forward<T>(callable),
std::forward_as_tuple(std::forward<Args>(args)...));
}
}
};
} // namespace detail
/// Partially invokes the given callable with the given arguments.
@ -131,7 +134,8 @@ template <typename T, typename... Args>
// The implementation is done in a shortcut way so there are less
// type instantiations needed to call the callable with its full signature.
return detail::partial_invoke_impl_shortcut(
using env = detail::invocation_env<0U>;
return env::partial_invoke_impl_shortcut(
is_invokable, std::forward<T>(callable), std::forward<Args>(args)...);
}