#include <typeinfo>
#include <utility>
-#include <folly/Assume.h>
#include <folly/CPortability.h>
#include <folly/Demangle.h>
#include <folly/ExceptionString.h>
#include <folly/FBString.h>
+#include <folly/Portability.h>
#include <folly/Traits.h>
+#include <folly/Utility.h>
+#include <folly/lang/Assume.h>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpotentially-evaluated-expression"
// GCC gets confused about lambda scopes and issues shadow-local warnings for
// parameters in totally different functions.
-#pragma GCC diagnostic ignored "-Wshadow-local"
-#pragma GCC diagnostic ignored "-Wshadow-compatible-local"
+FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS
#endif
#define FOLLY_EXCEPTION_WRAPPER_H_INCLUDED
//! // Thread2: Exceptions are ok!
//! void processResult() {
//! try {
-//! globalExceptionWrapper.throwException();
+//! globalExceptionWrapper.throw_exception();
//! } catch (const FacePlantException& e) {
//! LOG(ERROR) << "FACEPLANT!";
//! } catch (const FailWhaleException& e) {
};
template <class Fn>
- struct arg_type2_;
- template <class Fn, class = void>
struct arg_type_;
template <class Fn>
using arg_type = _t<arg_type_<Fn>>;
exception_wrapper (*get_exception_ptr_)(exception_wrapper const*);
};
- [[noreturn]] static void onNoExceptionError();
+ [[noreturn]] static void onNoExceptionError(char const* name);
template <class Ret, class... Args>
static Ret noop_(Args...);
static std::type_info const* uninit_type_(exception_wrapper const*);
- static constexpr VTable const uninit_{
- &noop_<void, exception_wrapper const*, exception_wrapper*>,
- &noop_<void, exception_wrapper*, exception_wrapper*>,
- &noop_<void, exception_wrapper*>,
- &noop_<void, exception_wrapper const*>,
- &uninit_type_,
- &noop_<std::exception const*, exception_wrapper const*>,
- &noop_<exception_wrapper, exception_wrapper const*>};
+ static VTable const uninit_;
template <class Ex>
using IsStdException = std::is_base_of<std::exception, _t<std::decay<Ex>>>;
Buffer() : buff_{} {}
- template <class Ex, class DEx = _t<std::decay<Ex>>>
- Buffer(in_place_t, Ex&& ex);
+ template <class Ex, typename... As>
+ Buffer(in_place_type_t<Ex>, As&&... as_);
template <class Ex>
Ex& as() noexcept;
template <class Ex>
"Surprise! std::exception and std::type_info don't have alignment "
"greater than one. as_int_ below will not work!");
- static std::uintptr_t as_int_(std::exception const& e);
- static std::uintptr_t as_int_(AnyException e);
+ static std::uintptr_t as_int_(
+ std::exception_ptr const& ptr,
+ std::exception const& e);
+ static std::uintptr_t as_int_(
+ std::exception_ptr const& ptr,
+ AnyException e);
bool has_exception_() const;
std::exception const* as_exception_() const;
std::type_info const* as_type_() const;
static std::type_info const* type_(exception_wrapper const* that);
static std::exception const* get_exception_(exception_wrapper const* that);
static exception_wrapper get_exception_ptr_(exception_wrapper const* that);
- static constexpr VTable const ops_{copy_,
- move_,
- delete_,
- throw_,
- type_,
- get_exception_,
- get_exception_ptr_};
+ static VTable const ops_;
};
template <class Ex>
struct Impl final : public Base {
Ex ex_;
Impl() = default;
- explicit Impl(Ex const& ex) : Base{typeid(ex)}, ex_(ex) {}
- explicit Impl(Ex&& ex)
- : Base{typeid(ex)},
- ex_(std::move(ex)){}[[noreturn]] void throw_() const override;
+ template <typename... As>
+ explicit Impl(As&&... as)
+ : Base{typeid(Ex)}, ex_(std::forward<As>(as)...) {}
+ [[noreturn]] void throw_() const override;
std::exception const* get_exception_() const noexcept override;
exception_wrapper get_exception_ptr_() const noexcept override;
};
static std::type_info const* type_(exception_wrapper const* that);
static std::exception const* get_exception_(exception_wrapper const* that);
static exception_wrapper get_exception_ptr_(exception_wrapper const* that);
- static constexpr VTable ops_{copy_,
- move_,
- delete_,
- throw_,
- type_,
- get_exception_,
- get_exception_ptr_};
+ static VTable const ops_;
};
union {
};
VTable const* vptr_{&uninit_};
- template <class Ex, class DEx = _t<std::decay<Ex>>>
- exception_wrapper(Ex&& ex, OnHeapTag);
+ template <class Ex, typename... As>
+ exception_wrapper(OnHeapTag, in_place_type_t<Ex>, As&&... as);
- template <class Ex, class DEx = _t<std::decay<Ex>>>
- exception_wrapper(Ex&& ex, InSituTag);
+ template <class Ex, typename... As>
+ exception_wrapper(InSituTag, in_place_type_t<Ex>, As&&... as);
template <class T>
struct IsRegularExceptionType
static bool with_exception_(This& this_, Fn fn_);
public:
+ static exception_wrapper from_exception_ptr(
+ std::exception_ptr const& eptr) noexcept;
+
//! Default-constructs an empty `exception_wrapper`
//! \post `type() == none()`
exception_wrapper() noexcept {}
class Ex,
class Ex_ = _t<std::decay<Ex>>,
FOLLY_REQUIRES(
- Conjunction<IsStdException<Ex_>, IsRegularExceptionType<Ex_>>())>
+ Conjunction<IsStdException<Ex_>, IsRegularExceptionType<Ex_>>::value)>
/* implicit */ exception_wrapper(Ex&& ex);
//! \pre `typeid(ex) == typeid(typename decay<Ex>::type)`
template <
class Ex,
class Ex_ = _t<std::decay<Ex>>,
- FOLLY_REQUIRES(IsRegularExceptionType<Ex_>())>
+ FOLLY_REQUIRES(IsRegularExceptionType<Ex_>::value)>
exception_wrapper(in_place_t, Ex&& ex);
+ template <
+ class Ex,
+ typename... As,
+ FOLLY_REQUIRES(IsRegularExceptionType<Ex>::value)>
+ exception_wrapper(in_place_type_t<Ex>, As&&... as);
+
//! Swaps the value of `*this` with the value of `that`
void swap(exception_wrapper& that) noexcept;
- //! \return `true` if `*this` is not holding an exception.
+ //! \return `true` if `*this` is holding an exception.
explicit operator bool() const noexcept;
//! \return `!bool(*this)`
//! \overload
std::exception const* get_exception() const noexcept;
+ //! \returns a pointer to the `Ex` held by `*this`, if it holds an object
+ //! whose type `From` permits `std::is_convertible<From*, Ex*>`;
+ //! otherwise, returns `nullptr`.
+ //! \note This function does not mutate the `exception_wrapper` object.
+ //! \note This function may cause an exception to be thrown and immediately
+ //! caught internally, affecting runtime performance.
+ template <typename Ex>
+ Ex* get_exception() noexcept;
+ //! \overload
+ template <typename Ex>
+ Ex const* get_exception() const noexcept;
+
//! \return A `std::exception_ptr` that references either the exception held
//! by `*this`, or a copy of same.
//! \note This function may need to throw an exception to complete the action.
//! \pre `bool(*this)`
//! Throws the wrapped expression.
- [[noreturn]] void throwException() const;
+ [[noreturn]] void throw_exception() const;
//! Call `fn` with the wrapped exception (if any), if `fn` can accept it.
//! \par Example
//! ew.handle(
//! [&](std::logic_error const& e) {
//! LOG(DFATAL) << "ruh roh";
- //! ew.throwException(); // rethrow the active exception without
+ //! ew.throw_exception(); // rethrow the active exception without
//! // slicing it. Will not be caught by other
//! // handlers in this call.
//! },
*/
template <class Ex, typename... As>
exception_wrapper make_exception_wrapper(As&&... as) {
- return exception_wrapper{Ex{std::forward<As>(as)...}};
+ return exception_wrapper{in_place_type<Ex>, std::forward<As>(as)...};
}
/**
return exception_wrapper(std::current_exception(), ex);
}
}
-} // detail
+} // namespace detail
//! `try_and_catch` is a simple replacement for `try {} catch(){}`` that allows
//! you to specify which derived exceptions you would like to catch and store in
//!
//! \par Example Usage:
//! \code
-//! // This catches my runtime_error and if I call throwException() on ew, it
+//! // This catches my runtime_error and if I call throw_exception() on ew, it
//! // will throw a runtime_error
//! auto ew = folly::try_and_catch<std::exception, std::runtime_error>([=]() {
//! if (badThingHappens()) {
//! }
//! });
//!
-//! // This will catch the exception and if I call throwException() on ew, it
+//! // This will catch the exception and if I call throw_exception() on ew, it
//! // will throw a std::exception
//! auto ew = folly::try_and_catch<std::exception, std::runtime_error>([=]() {
//! if (badThingHappens()) {
exception_wrapper try_and_catch(F&& fn) {
return detail::try_and_catch_<F, Exceptions...>(std::forward<F>(fn));
}
-} // folly
+} // namespace folly
#include <folly/ExceptionWrapper-inl.h>