From: Yedidya Feldblum Date: Wed, 7 Jun 2017 07:05:51 +0000 (-0700) Subject: Try::tryGetExceptionObject X-Git-Tag: v2017.06.12.00~21 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=717713f2c8cc1c75cc883189139cd23be61f5525 Try::tryGetExceptionObject Summary: [Folly] `Try::tryGetExceptionObject`. If the `Try` has a `std::exception` for the non-template overload or a `From` where `is_convertible` 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 --- diff --git a/folly/Try.h b/folly/Try.h index fe963753..e5af11fa 100644 --- a/folly/Try.h +++ b/folly/Try.h @@ -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`; otherwise, + * returns `nullptr`. + */ + template + E* tryGetExceptionObject() { + return hasException() ? e_.get_exception() : nullptr; + } + template + E const* tryGetExceptionObject() const { + return hasException() ? e_.get_exception() : nullptr; + } + /* * If the Try contains an exception and it is of type Ex, execute func(Ex) * @@ -339,6 +364,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`; otherwise, + * returns `nullptr`. + */ + template + E* tryGetExceptionObject() { + return hasException() ? e_.get_exception() : nullptr; + } + template + E const* tryGetExceptionObject() const { + return hasException() ? e_.get_exception() : nullptr; + } + /* * If the Try contains an exception and it is of type Ex, execute func(Ex) * diff --git a/folly/test/TryTest.cpp b/folly/test/TryTest.cpp index c986f40d..e67761b1 100644 --- a/folly/test/TryTest.cpp +++ b/folly/test/TryTest.cpp @@ -14,8 +14,11 @@ * limitations under the License. */ -#include #include + +#include + +#include #include using namespace folly; @@ -89,3 +92,106 @@ TEST(Try, makeTryWithVoidThrow) { auto result = makeTryWith(func); EXPECT_TRUE(result.hasException()); } + +template +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(epexn)); + auto num = CHECK_NOTNULL(get_exception(epnum)); + + { + auto t = Try(true); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto t = Try(exception_wrapper(epexn, *exn)); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto t = Try(exception_wrapper(epnum, *num)); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(num, t.tryGetExceptionObject()); + } + + { + auto t = Try(); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto t = Try(exception_wrapper(epexn, *exn)); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto t = Try(exception_wrapper(epnum, *num)); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(num, t.tryGetExceptionObject()); + } + + { + auto const t = Try(true); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto const t = Try(exception_wrapper(epexn, *exn)); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto const t = Try(exception_wrapper(epnum, *num)); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(num, t.tryGetExceptionObject()); + } + + { + auto const t = Try(); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto const t = Try(exception_wrapper(epexn, *exn)); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(exn, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + } + + { + auto const t = Try(exception_wrapper(epnum, *num)); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(nullptr, t.tryGetExceptionObject()); + EXPECT_EQ(num, t.tryGetExceptionObject()); + } +}