+ //! Default-constructs an empty `exception_wrapper`
+ //! \post `type() == none()`
+ exception_wrapper() noexcept {}
+
+ //! Move-constructs an `exception_wrapper`
+ //! \post `*this` contains the value of `that` prior to the move
+ //! \post `that.type() == none()`
+ exception_wrapper(exception_wrapper&& that) noexcept;
+
+ //! Copy-constructs an `exception_wrapper`
+ //! \post `*this` contains a copy of `that`, and `that` is unmodified
+ //! \post `type() == that.type()`
+ exception_wrapper(exception_wrapper const& that);
+
+ //! Move-assigns an `exception_wrapper`
+ //! \pre `this != &that`
+ //! \post `*this` contains the value of `that` prior to the move
+ //! \post `that.type() == none()`
+ exception_wrapper& operator=(exception_wrapper&& that) noexcept;
+
+ //! Copy-assigns an `exception_wrapper`
+ //! \post `*this` contains a copy of `that`, and `that` is unmodified
+ //! \post `type() == that.type()`
+ exception_wrapper& operator=(exception_wrapper const& that);
+
+ ~exception_wrapper();
+
+ //! \pre `ptr` is empty, or it holds a reference to an exception that is not
+ //! derived from `std::exception`.
+ //! \post `!ptr || bool(*this)`
+ //! \post `hasThrownException() == true`
+ //! \post `type() == unknown()`
+ explicit exception_wrapper(std::exception_ptr ptr) noexcept;
+
+ //! \pre `ptr` holds a reference to `ex`.
+ //! \post `hasThrownException() == true`
+ //! \post `bool(*this)`
+ //! \post `type() == typeid(ex)`
+ template <class Ex>
+ exception_wrapper(std::exception_ptr ptr, Ex& ex);
+
+ //! \pre `typeid(ex) == typeid(typename decay<Ex>::type)`
+ //! \post `bool(*this)`
+ //! \post `hasThrownException() == false`
+ //! \post `type() == typeid(ex)`
+ //! \note Exceptions of types derived from `std::exception` can be implicitly
+ //! converted to an `exception_wrapper`.
+ template <
+ class Ex,
+ class Ex_ = _t<std::decay<Ex>>,
+ FOLLY_REQUIRES(
+ Conjunction<IsStdException<Ex_>, IsRegularExceptionType<Ex_>>::value)>
+ /* implicit */ exception_wrapper(Ex&& ex);
+
+ //! \pre `typeid(ex) == typeid(typename decay<Ex>::type)`
+ //! \post `bool(*this)`
+ //! \post `hasThrownException() == false`
+ //! \post `type() == typeid(ex)`
+ //! \note Exceptions of types not derived from `std::exception` can still be
+ //! used to construct an `exception_wrapper`, but you must specify
+ //! `folly::in_place` as the first parameter.
+ template <
+ class Ex,
+ class Ex_ = _t<std::decay<Ex>>,
+ FOLLY_REQUIRES(IsRegularExceptionType<Ex_>::value)>
+ exception_wrapper(in_place_t, Ex&& ex);
+
+ //! 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.
+ explicit operator bool() const noexcept;
+
+ //! \return `!bool(*this)`
+ bool operator!() const noexcept;
+
+ //! Make this `exception_wrapper` empty
+ //! \post `!*this`
+ void reset();
+
+ //! \return `true` if this `exception_wrapper` holds a reference to an
+ //! exception that was thrown (i.e., if it was constructed with
+ //! a `std::exception_ptr`, or if `to_exception_ptr()` was called on a
+ //! (non-const) reference to `*this`).
+ bool has_exception_ptr() const noexcept;
+
+ //! \return a pointer to the `std::exception` held by `*this`, if it holds
+ //! one; otherwise, returns `nullptr`.
+ //! \note This function does not mutate the `exception_wrapper` object.
+ //! \note This function never causes an exception to be thrown.
+ std::exception* get_exception() noexcept;
+ //! \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_object() noexcept;
+ //! \overload
+ template <typename Ex>
+ Ex const* get_object() 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;
+
+ [[noreturn]] FOLLY_DEPRECATED(
+ "use throw_exception") void throwException() const {
+ throw_exception();