+
+ private:
+ template <typename F>
+ struct functor_traits {
+ template <typename T>
+ struct impl;
+ template <typename C, typename R, typename A>
+ struct impl<R(C::*)(A)> { using arg_type = A; };
+ template <typename C, typename R, typename A>
+ struct impl<R(C::*)(A) const> { using arg_type = A; };
+ using functor_op = decltype(&_t<std::decay<F>>::operator());
+ using arg_type = typename impl<functor_op>::arg_type;
+ };
+
+ template <class T>
+ class Thrower {
+ public:
+ static void doThrow(std::exception& obj) {
+ throw static_cast<T&>(obj);
+ }
+ };
+
+ template <typename T, typename F>
+ static _t<std::enable_if<is_exception_<T>::value, T*>>
+ try_dynamic_cast_exception(F* from) {
+ return dynamic_cast<T*>(from);
+ }
+ template <typename T, typename F>
+ static _t<std::enable_if<!is_exception_<T>::value, T*>>
+ try_dynamic_cast_exception(F*) {
+ return nullptr;
+ }
+
+ // What makes this useful is that T can be exception_wrapper* or
+ // const exception_wrapper*, and the compiler will use the
+ // instantiation which works with F.
+ template <class Ex, class F, class T>
+ static bool with_exception1(F f, T* that) {
+ using CEx = _t<std::conditional<std::is_const<T>::value, const Ex, Ex>>;
+ if (is_exception_<Ex>::value &&
+ (that->item_ || (that->eptr_ && that->eobj_))) {
+ auto raw =
+ that->item_ ? that->item_.get() : that->eptr_ ? that->eobj_ : nullptr;
+ if (auto ex = try_dynamic_cast_exception<CEx>(raw)) {
+ f(*ex);
+ return true;
+ }
+ } else if (that->eptr_) {
+ try {
+ std::rethrow_exception(that->eptr_);
+ } catch (CEx& e) {
+ f(e);
+ return true;
+ } catch (...) {
+ // fall through
+ }
+ }
+ return false;
+ }