Try::tryGetExceptionObject
authorYedidya Feldblum <yfeldblum@fb.com>
Wed, 7 Jun 2017 07:05:51 +0000 (00:05 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 7 Jun 2017 07:21:19 +0000 (00:21 -0700)
Summary:
[Folly] `Try::tryGetExceptionObject`.

If the `Try` has a `std::exception` for the non-template overload or a `From` where `is_convertible<From*, Ex*>` for the template overload parameterized by `typename Ex`, returns a pointer to it. Otherwise returns `nullptr`.

Reviewed By: spacedentist

Differential Revision: D5180848

fbshipit-source-id: b7593b7459259f9a1e1e78b36d548e55d086e722

folly/Try.h
folly/test/TryTest.cpp

index fe96375..e5af11f 100644 (file)
@@ -211,6 +211,31 @@ class Try {
     return e_;
   }
 
+  /*
+   * @returns a pointer to the `std::exception` held by `*this`, if one is held;
+   *          otherwise, returns `nullptr`.
+   */
+  std::exception* tryGetExceptionObject() {
+    return hasException() ? e_.get_exception() : nullptr;
+  }
+  std::exception const* tryGetExceptionObject() const {
+    return hasException() ? e_.get_exception() : nullptr;
+  }
+
+  /*
+   * @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`.
+   */
+  template <class E>
+  E* tryGetExceptionObject() {
+    return hasException() ? e_.get_exception<E>() : nullptr;
+  }
+  template <class E>
+  E const* tryGetExceptionObject() const {
+    return hasException() ? e_.get_exception<E>() : nullptr;
+  }
+
   /*
    * If the Try contains an exception and it is of type Ex, execute func(Ex)
    *
@@ -339,6 +364,31 @@ class Try<void> {
     return e_;
   }
 
+  /*
+   * @returns a pointer to the `std::exception` held by `*this`, if one is held;
+   *          otherwise, returns `nullptr`.
+   */
+  std::exception* tryGetExceptionObject() {
+    return hasException() ? e_.get_exception() : nullptr;
+  }
+  std::exception const* tryGetExceptionObject() const {
+    return hasException() ? e_.get_exception() : nullptr;
+  }
+
+  /*
+   * @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`.
+   */
+  template <class E>
+  E* tryGetExceptionObject() {
+    return hasException() ? e_.get_exception<E>() : nullptr;
+  }
+  template <class E>
+  E const* tryGetExceptionObject() const {
+    return hasException() ? e_.get_exception<E>() : nullptr;
+  }
+
   /*
    * If the Try contains an exception and it is of type Ex, execute func(Ex)
    *
index c986f40..e67761b 100644 (file)
  * limitations under the License.
  */
 
-#include <folly/Memory.h>
 #include <folly/Try.h>
+
+#include <glog/logging.h>
+
+#include <folly/Memory.h>
 #include <folly/portability/GTest.h>
 
 using namespace folly;
@@ -89,3 +92,106 @@ TEST(Try, makeTryWithVoidThrow) {
   auto result = makeTryWith(func);
   EXPECT_TRUE(result.hasException<std::runtime_error>());
 }
+
+template <typename E>
+static E* get_exception(std::exception_ptr eptr) {
+  try {
+    std::rethrow_exception(eptr);
+  } catch (E& e) {
+    return &e;
+  } catch (...) {
+    return nullptr;
+  }
+}
+
+TEST(Try, tryGetExceptionObject) {
+  auto epexn = std::make_exception_ptr(std::range_error("oops"));
+  auto epnum = std::make_exception_ptr(17);
+
+  auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
+  auto num = CHECK_NOTNULL(get_exception<int>(epnum));
+
+  {
+    auto t = Try<bool>(true);
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto t = Try<bool>(exception_wrapper(epexn, *exn));
+    EXPECT_EQ(exn, t.tryGetExceptionObject());
+    EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto t = Try<bool>(exception_wrapper(epnum, *num));
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto t = Try<void>();
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto t = Try<void>(exception_wrapper(epexn, *exn));
+    EXPECT_EQ(exn, t.tryGetExceptionObject());
+    EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto t = Try<void>(exception_wrapper(epnum, *num));
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<bool>(true);
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<bool>(exception_wrapper(epexn, *exn));
+    EXPECT_EQ(exn, t.tryGetExceptionObject());
+    EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<bool>(exception_wrapper(epnum, *num));
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<void>();
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<void>(exception_wrapper(epexn, *exn));
+    EXPECT_EQ(exn, t.tryGetExceptionObject());
+    EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+  }
+
+  {
+    auto const t = Try<void>(exception_wrapper(epnum, *num));
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+    EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+    EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+  }
+}