+ 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.
+ //! \note The non-const overload of this function mutates `*this` to cache the
+ //! computed `std::exception_ptr`; that is, this function may cause
+ //! `has_exception_ptr()` to change from `false` to `true`.
+ std::exception_ptr const& to_exception_ptr() noexcept;
+ //! \overload
+ std::exception_ptr to_exception_ptr() const noexcept;
+
+ //! \return the `typeid` of an unspecified type used by
+ //! `exception_wrapper::type()` to denote an empty `exception_wrapper`.
+ static std::type_info const& none() noexcept;
+ //! \return the `typeid` of an unspecified type used by
+ //! `exception_wrapper::type()` to denote an `exception_wrapper` that
+ //! holds an exception of unknown type.
+ static std::type_info const& unknown() noexcept;
+
+ //! Returns the `typeid` of the wrapped exception object. If there is no
+ //! wrapped exception object, returns `exception_wrapper::none()`. If
+ //! this instance wraps an exception of unknown type not derived from
+ //! `std::exception`, returns `exception_wrapper::unknown()`.
+ std::type_info const& type() const noexcept;
+
+ //! \return If `get_exception() != nullptr`, `class_name() + ": " +
+ //! get_exception()->what()`; otherwise, `class_name()`.
+ folly::fbstring what() const;
+
+ //! \return If `!*this`, the empty string; otherwise, if
+ //! `type() == unknown()`, the string `"<unknown exception>"`; otherwise,
+ //! the result of `type().name()` after demangling.
+ folly::fbstring class_name() const;
+
+ //! \tparam Ex The expression type to check for compatibility with.
+ //! \return `true` if and only if `*this` wraps an exception that would be
+ //! caught with a `catch(Ex const&)` clause.
+ //! \note If `*this` is empty, this function returns `false`.
+ template <class Ex>
+ bool is_compatible_with() const noexcept;
+
+ //! \pre `bool(*this)`
+ //! Throws the wrapped expression.
+ [[noreturn]] void throw_exception() const;
+
+ //! Call `fn` with the wrapped exception (if any), if `fn` can accept it.
+ //! \par Example
+ //! \code
+ //! exception_wrapper ew{std::runtime_error("goodbye cruel world")};
+ //!
+ //! assert( ew.with_exception([](std::runtime_error& e){/*...*/}) );
+ //!
+ //! assert( !ew.with_exception([](int& e){/*...*/}) );
+ //!
+ //! assert( !exception_wrapper{}.with_exception([](int& e){/*...*/}) );
+ //! \endcode
+ //! \tparam Ex Optionally, the type of the exception that `fn` accepts.
+ //! \tparam Fn The type of a monomophic function object.
+ //! \param fn A function object to call with the wrapped exception
+ //! \return `true` if and only if `fn` was called.
+ //! \note Optionally, you may explicitly specify the type of the exception
+ //! that `fn` expects, as in
+ //! \code
+ //! ew.with_exception<std::runtime_error>([](auto&& e) { /*...*/; });
+ //! \endcode
+ //! \note The handler may or may not be 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
+ //! a handler so long as you specify the exception to throw, as in
+ //! `throw e;`.)
+ template <class Ex = void const, class Fn>
+ bool with_exception(Fn fn);
+ //! \overload
+ template <class Ex = void const, class Fn>
+ bool with_exception(Fn fn) const;
+
+ //! Handle the wrapped expression as if with a series of `catch` clauses,
+ //! propagating the exception if no handler matches.
+ //! \par Example
+ //! \code
+ //! exception_wrapper ew{std::runtime_error("goodbye cruel world")};
+ //!
+ //! ew.handle(
+ //! [&](std::logic_error const& e) {
+ //! LOG(DFATAL) << "ruh roh";
+ //! ew.throw_exception(); // rethrow the active exception without
+ //! // slicing it. Will not be caught by other
+ //! // handlers in this call.
+ //! },
+ //! [&](std::exception const& e) {
+ //! LOG(ERROR) << ew.what();
+ //! });
+ //! \endcode
+ //! In the above example, any exception _not_ derived from `std::exception`
+ //! will be propagated. To specify a catch-all clause, pass a lambda that
+ //! takes a C-style elipses, as in:
+ //! \code
+ //! ew.handle(/*...* /, [](...) { /* handle unknown exception */ } )
+ //! \endcode
+ //! \pre `!*this`
+ //! \tparam CatchFns... A pack of unary monomorphic function object types.
+ //! \param fns A pack of unary monomorphic function objects to be treated as
+ //! an ordered list of potential exception handlers.
+ //! \note The handlers may or may not be 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
+ //! a handler so long as you specify the exception to throw, as in
+ //! `throw e;`.)
+ template <class... CatchFns>
+ void handle(CatchFns... fns);
+ //! \overload
+ template <class... CatchFns>
+ void handle(CatchFns... fns) const;