Fixes for Try::withException
authorYedidya Feldblum <yfeldblum@fb.com>
Tue, 27 Jun 2017 21:27:31 +0000 (14:27 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 27 Jun 2017 21:35:42 +0000 (14:35 -0700)
Summary:
[Folly] Fixes for `Try::withException`.

* Fix the overload with the exception type specified so that the specified exception type is checked. A mismatch between the specified exception type and the parameter type of the passed invokable will result in the expected compiler error.
* Add an overload where the exception type is deduced intentionally, as opposed to accidentally.

Of course, these simply forward to their corresponding `exception_wrapper::withException` overloads.

Reviewed By: ericniebler

Differential Revision: D5216691

fbshipit-source-id: 7e85c906c3aa17dfede6e0980c6ac8bf75034073

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

index e5af11fa5fe4fb7aef845ca0ca9349325056acf7..f115a34ab333db0961556f3571415cfd36773366 100644 (file)
@@ -248,9 +248,32 @@ class Try {
     if (!hasException()) {
       return false;
     }
-    return e_.with_exception(std::move(func));
+    return e_.with_exception<Ex>(std::move(func));
   }
   template <class Ex, class F>
+  bool withException(F func) const {
+    if (!hasException()) {
+      return false;
+    }
+    return e_.with_exception<Ex>(std::move(func));
+  }
+
+  /*
+   * If the Try contains an exception and it is of type compatible with Ex as
+   * deduced from the first parameter of func, execute func(Ex)
+   *
+   * @param func a function that takes a single parameter of type const Ex&
+   *
+   * @returns True if the Try held an Ex and func was executed, false otherwise
+   */
+  template <class F>
+  bool withException(F func) {
+    if (!hasException()) {
+      return false;
+    }
+    return e_.with_exception(std::move(func));
+  }
+  template <class F>
   bool withException(F func) const {
     if (!hasException()) {
       return false;
@@ -401,9 +424,32 @@ class Try<void> {
     if (!hasException()) {
       return false;
     }
-    return e_.with_exception(std::move(func));
+    return e_.with_exception<Ex>(std::move(func));
   }
   template <class Ex, class F>
+  bool withException(F func) const {
+    if (!hasException()) {
+      return false;
+    }
+    return e_.with_exception<Ex>(std::move(func));
+  }
+
+  /*
+   * If the Try contains an exception and it is of type compatible with Ex as
+   * deduced from the first parameter of func, execute func(Ex)
+   *
+   * @param func a function that takes a single parameter of type const Ex&
+   *
+   * @returns True if the Try held an Ex and func was executed, false otherwise
+   */
+  template <class F>
+  bool withException(F func) {
+    if (!hasException()) {
+      return false;
+    }
+    return e_.with_exception(std::move(func));
+  }
+  template <class F>
   bool withException(F func) const {
     if (!hasException()) {
       return false;
index e67761b128352edb39eb41a1b904e6faae8c1516..49517bf5b58bd7b7cb5efb032f2fd5acb81c61f3 100644 (file)
@@ -195,3 +195,71 @@ TEST(Try, tryGetExceptionObject) {
     EXPECT_EQ(num, t.tryGetExceptionObject<int>());
   }
 }
+
+TEST(Try, withException) {
+  auto ew = make_exception_wrapper<std::range_error>("oops");
+
+  {
+    auto t = Try<bool>(true);
+    EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+  }
+
+  {
+    auto t = Try<bool>(ew);
+    EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+  }
+
+  {
+    auto t = Try<void>();
+    EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+  }
+
+  {
+    auto t = Try<void>(ew);
+    EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+  }
+
+  {
+    auto const t = Try<bool>(true);
+    EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+  }
+
+  {
+    auto const t = Try<bool>(ew);
+    EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+  }
+
+  {
+    auto const t = Try<void>();
+    EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+  }
+
+  {
+    auto const t = Try<void>(ew);
+    EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+    EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+    EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
+    EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+  }
+}