exception_wrapper::get_object<>
[folly.git] / folly / ExceptionWrapper-inl.h
index 175484454bf596968d43f5dfcf19cfc1d74e3474..aca35f2cb255c7ae8cc3958173b3cf54f153e9f1 100644 (file)
 namespace folly {
 
 template <class Fn>
-struct exception_wrapper::arg_type2_ {};
+struct exception_wrapper::arg_type_
+    : public arg_type_<decltype(&Fn::operator())> {
+};
 template <class Ret, class Class, class Arg>
-struct exception_wrapper::arg_type2_<Ret (Class::*)(Arg)> {
+struct exception_wrapper::arg_type_<Ret (Class::*)(Arg)> {
   using type = Arg;
 };
 template <class Ret, class Class, class Arg>
-struct exception_wrapper::arg_type2_<Ret (Class::*)(Arg) const> {
+struct exception_wrapper::arg_type_<Ret (Class::*)(Arg) const> {
+  using type = Arg;
+};
+template <class Ret, class Arg>
+struct exception_wrapper::arg_type_<Ret (Arg)> {
+  using type = Arg;
+};
+template <class Ret, class Arg>
+struct exception_wrapper::arg_type_<Ret (*)(Arg)> {
   using type = Arg;
 };
 template <class Ret, class Class>
-struct exception_wrapper::arg_type2_<Ret (Class::*)(...)> {
+struct exception_wrapper::arg_type_<Ret (Class::*)(...)> {
   using type = AnyException;
 };
 template <class Ret, class Class>
-struct exception_wrapper::arg_type2_<Ret (Class::*)(...) const> {
+struct exception_wrapper::arg_type_<Ret (Class::*)(...) const> {
   using type = AnyException;
 };
-
-template <class Fn, class>
-struct exception_wrapper::arg_type_ {};
-template <class Fn>
-struct exception_wrapper::arg_type_<Fn, void_t<decltype(&Fn::operator())>>
-    : public arg_type2_<decltype(&Fn::operator())> {};
-template <class Ret, class Arg>
-struct exception_wrapper::arg_type_<Ret (*)(Arg)> {
-  using type = Arg;
+template <class Ret>
+struct exception_wrapper::arg_type_<Ret (...)> {
+  using type = AnyException;
 };
 template <class Ret>
 struct exception_wrapper::arg_type_<Ret (*)(...)> {
@@ -283,32 +287,38 @@ inline exception_wrapper::exception_wrapper(std::exception_ptr ptr, Ex& ex)
   assert(eptr_.ptr_);
 }
 
+namespace exception_wrapper_detail {
+template <class Ex>
+Ex&& dont_slice(Ex&& ex) {
+  assert(typeid(ex) == typeid(_t<std::decay<Ex>>) ||
+       !"Dynamic and static exception types don't match. Exception would "
+        "be sliced when storing in exception_wrapper.");
+  return std::forward<Ex>(ex);
+}
+}
+
 template <
     class Ex,
     class Ex_,
     FOLLY_REQUIRES_DEF(
         Conjunction<
             exception_wrapper::IsStdException<Ex_>,
-            exception_wrapper::IsRegularExceptionType<Ex_>>())>
+            exception_wrapper::IsRegularExceptionType<Ex_>>::value)>
 inline exception_wrapper::exception_wrapper(Ex&& ex)
-    : exception_wrapper{std::forward<Ex>(ex), PlacementOf<Ex_>{}} {
-  // Don't slice!!!
-  assert(typeid(ex) == typeid(Ex_) ||
-       !"Dynamic and static exception types don't match. Exception would "
-        "be sliced when storing in exception_wrapper.");
+    : exception_wrapper{
+        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex)),
+        PlacementOf<Ex_>{}} {
 }
 
 template <
     class Ex,
     class Ex_,
     FOLLY_REQUIRES_DEF(
-        exception_wrapper::IsRegularExceptionType<Ex_>())>
+        exception_wrapper::IsRegularExceptionType<Ex_>::value)>
 inline exception_wrapper::exception_wrapper(in_place_t, Ex&& ex)
-    : exception_wrapper{std::forward<Ex>(ex), PlacementOf<Ex_>{}} {
-  // Don't slice!!!
-  assert(typeid(ex) == typeid(Ex_) ||
-       !"Dynamic and static exception types don't match. Exception would "
-        "be sliced when storing in exception_wrapper.");
+    : exception_wrapper{
+        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex)),
+        PlacementOf<Ex_>{}} {
 }
 
 inline void exception_wrapper::swap(exception_wrapper& that) noexcept {
@@ -340,6 +350,20 @@ inline std::exception const* exception_wrapper::get_exception() const noexcept {
   return vptr_->get_exception_(this);
 }
 
+template <typename Ex>
+inline Ex* exception_wrapper::get_object() noexcept {
+  Ex* object{nullptr};
+  with_exception([&](Ex& ex) { object = &ex; });
+  return object;
+}
+
+template <typename Ex>
+inline Ex const* exception_wrapper::get_object() const noexcept {
+  Ex const* object{nullptr};
+  with_exception([&](Ex const& ex) { object = &ex; });
+  return object;
+}
+
 inline std::exception_ptr const& exception_wrapper::to_exception_ptr()
     noexcept {
   // Computing an exception_ptr is expensive so cache the result.
@@ -379,7 +403,7 @@ inline bool exception_wrapper::is_compatible_with() const noexcept {
   return with_exception([](Ex const&) {});
 }
 
-[[noreturn]] inline void exception_wrapper::throwException() const {
+[[noreturn]] inline void exception_wrapper::throw_exception() const {
   vptr_->throw_(this);
   onNoExceptionError();
 }
@@ -494,7 +518,7 @@ inline void exception_wrapper::handle_(
   bool handled = false;
   auto impl = exception_wrapper_detail::fold(
       HandleReduce<std::is_const<This>::value>{&handled},
-      [&] { this_.throwException(); },
+      [&] { this_.throw_exception(); },
       fns...);
   impl();
 }