Try::exception overload for Try&&
authorYedidya Feldblum <yfeldblum@fb.com>
Thu, 24 Aug 2017 07:42:16 +0000 (00:42 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 24 Aug 2017 08:02:36 +0000 (01:02 -0700)
Summary:
[Folly] `Try::exception` overload for `Try&&`.

For consistency with `Try::value`.

Reviewed By: WillerZ

Differential Revision: D5691758

fbshipit-source-id: 9904b2a5c90f4575a3c09dc012658d359d11fdd9

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

index fb783b010a0f9ff303332139b694423026bbb49f..6d219a738661fa40e71a705809eeec74a4ad6db5 100644 (file)
@@ -201,20 +201,34 @@ class Try {
     return hasException() && e_.is_compatible_with<Ex>();
   }
 
-  exception_wrapper& exception() {
+  exception_wrapper& exception() {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
-  const exception_wrapper& exception() const {
+  exception_wrapper&& exception() && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
+  const exception_wrapper& exception() const & {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
+  const exception_wrapper&& exception() const && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
   /*
    * @returns a pointer to the `std::exception` held by `*this`, if one is held;
    *          otherwise, returns `nullptr`.
@@ -370,20 +384,34 @@ class Try<void> {
    *
    * @returns mutable reference to the exception contained by this Try
    */
-  exception_wrapper& exception() {
+  exception_wrapper& exception() {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
-  const exception_wrapper& exception() const {
+  exception_wrapper&& exception() && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
+  const exception_wrapper& exception() const & {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
+  const exception_wrapper&& exception() const && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
   /*
    * @returns a pointer to the `std::exception` held by `*this`, if one is held;
    *          otherwise, returns `nullptr`.
index ae9e301fadc7542de42ddc7d33aba6b6e5a996f2..5fdd231d501014e170d54d8b1e520511ad3c63a1 100644 (file)
@@ -109,6 +109,69 @@ TEST(Try, makeTryWithVoidThrow) {
   EXPECT_TRUE(result.hasException<std::runtime_error>());
 }
 
+TEST(Try, exception) {
+  using ML = exception_wrapper&;
+  using MR = exception_wrapper&&;
+  using CL = exception_wrapper const&;
+  using CR = exception_wrapper const&&;
+
+  {
+    auto obj = Try<int>();
+    using ActualML = decltype(obj.exception());
+    using ActualMR = decltype(std::move(obj).exception());
+    using ActualCL = decltype(as_const(obj).exception());
+    using ActualCR = decltype(std::move(as_const(obj)).exception());
+    EXPECT_TRUE((std::is_same<ML, ActualML>::value));
+    EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
+    EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
+    EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
+  }
+
+  {
+    auto obj = Try<int>(3);
+    EXPECT_THROW(obj.exception(), TryException);
+    EXPECT_THROW(std::move(obj).exception(), TryException);
+    EXPECT_THROW(as_const(obj).exception(), TryException);
+    EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
+  }
+
+  {
+    auto obj = Try<int>(make_exception_wrapper<int>(-3));
+    EXPECT_EQ(-3, *obj.exception().get_exception<int>());
+    EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
+    EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
+    EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
+  }
+
+  {
+    auto obj = Try<void>();
+    using ActualML = decltype(obj.exception());
+    using ActualMR = decltype(std::move(obj).exception());
+    using ActualCL = decltype(as_const(obj).exception());
+    using ActualCR = decltype(std::move(as_const(obj)).exception());
+    EXPECT_TRUE((std::is_same<ML, ActualML>::value));
+    EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
+    EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
+    EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
+  }
+
+  {
+    auto obj = Try<void>();
+    EXPECT_THROW(obj.exception(), TryException);
+    EXPECT_THROW(std::move(obj).exception(), TryException);
+    EXPECT_THROW(as_const(obj).exception(), TryException);
+    EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
+  }
+
+  {
+    auto obj = Try<void>(make_exception_wrapper<int>(-3));
+    EXPECT_EQ(-3, *obj.exception().get_exception<int>());
+    EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
+    EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
+    EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
+  }
+}
+
 template <typename E>
 static E* get_exception(std::exception_ptr eptr) {
   try {