Commit 98c2c6f1 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

implement exception_wrapper::with_exception directly

Summary: Rather than implementing it via `handle`, which is complex. Works now that exact casting can always be done without `catch`.

Reviewed By: luciang

Differential Revision: D27987594

fbshipit-source-id: 9961b55089f58df1b06793390817e497c6da54ae
parent 5ec574fe
......@@ -94,6 +94,16 @@ struct exception_wrapper::arg_type_<Ret (*)(...) noexcept> {
};
#endif
struct exception_wrapper::with_exception_from_fn_ {
template <typename, typename Fn>
using apply = arg_type<Fn>;
};
struct exception_wrapper::with_exception_from_ex_ {
template <typename Ex, typename>
using apply = Ex;
};
template <class Ret, class... Args>
inline Ret exception_wrapper::noop_(Args...) {
return Ret();
......@@ -598,34 +608,14 @@ inline void exception_wrapper::handle_(
}
}
namespace exception_wrapper_detail {
template <class Ex, class Fn>
struct catch_fn {
Fn fn_;
auto operator()(Ex& ex) { return fn_(ex); }
};
template <class Ex, class Fn>
inline catch_fn<Ex, Fn> catch_(Ex*, Fn fn) {
return {std::move(fn)};
}
template <class Fn>
inline Fn catch_(void const*, Fn fn) {
return fn;
}
} // namespace exception_wrapper_detail
template <class Ex, class This, class Fn>
inline bool exception_wrapper::with_exception_(This& this_, Fn fn_) {
if (!this_) {
return false;
}
bool handled = true;
auto fn = exception_wrapper_detail::catch_(
static_cast<Ex*>(nullptr), std::move(fn_));
auto&& all = [&](...) { handled = false; };
handle_(IsStdException<arg_type<decltype(fn)>>{}, this_, fn, all);
return handled;
using from_fn = with_exception_from_fn_;
using from_ex = with_exception_from_ex_;
using from = conditional_t<std::is_void<Ex>::value, from_fn, from_ex>;
using type = typename from::template apply<Ex, Fn>;
auto ptr = this_.template get_exception<remove_cvref_t<type>>();
return ptr && (void(fn_(static_cast<type&>(*ptr))), true);
}
template <class Ex, class Fn>
......
......@@ -173,6 +173,9 @@ class exception_wrapper final {
template <class Fn>
using arg_type = _t<arg_type_<Fn>>;
struct with_exception_from_fn_;
struct with_exception_from_ex_;
// exception_wrapper is implemented as a simple variant over four
// different representations:
// 0. Empty, no exception.
......@@ -538,7 +541,7 @@ class exception_wrapper final {
//! \code
//! ew.with_exception<std::runtime_error>([](auto&& e) { /*...*/; });
//! \endcode
//! \note The handler may or may not be invoked with an active exception.
//! \note The handler is not invoked with an active exception.
//! **Do not try to rethrow the exception with `throw;` from within your
//! handler -- that is, a throw expression with no operand.** This may
//! cause your process to terminate. (It is perfectly ok to throw from
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment