exception_wrapper::get_object<>
authorYedidya Feldblum <yfeldblum@fb.com>
Fri, 12 May 2017 21:14:22 +0000 (14:14 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Fri, 12 May 2017 21:21:06 +0000 (14:21 -0700)
Summary:
[Folly] `exception_wrapper::get_object<>`.

Returns a pointer to the stored object, if the template type parameter is of the right sort.

Reviewed By: jsedgwick

Differential Revision: D5000720

fbshipit-source-id: 2869439085e8dfb56e6cb439794b03876b7d715c

folly/ExceptionWrapper-inl.h
folly/ExceptionWrapper.h
folly/test/ExceptionWrapperTest.cpp

index 99cbd9d..aca35f2 100644 (file)
@@ -350,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.
index a1adfec..82dfde7 100644 (file)
@@ -457,6 +457,18 @@ class exception_wrapper final {
   //! \overload
   std::exception const* get_exception() const noexcept;
 
+  //! \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`.
+  //! \note This function does not mutate the `exception_wrapper` object.
+  //! \note This function may cause an exception to be thrown and immediately
+  //!     caught internally, affecting runtime performance.
+  template <typename Ex>
+  Ex* get_object() noexcept;
+  //! \overload
+  template <typename Ex>
+  Ex const* get_object() const noexcept;
+
   //! \return A `std::exception_ptr` that references either the exception held
   //!     by `*this`, or a copy of same.
   //! \note This function may need to throw an exception to complete the action.
index 67f14c5..fde0e8a 100644 (file)
@@ -215,6 +215,8 @@ TEST(ExceptionWrapper, with_exception_ptr_empty) {
   EXPECT_EQ(exception_wrapper::none(), ew.type());
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_FALSE(ew.has_exception_ptr());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_FALSE(ew.has_exception_ptr());
@@ -230,6 +232,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) {
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(typeid(std::runtime_error), ew.type());
   EXPECT_NE(nullptr, ew.get_exception());
+  EXPECT_NE(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_FALSE(ew.has_exception_ptr());
   EXPECT_NE(nullptr, ew.to_exception_ptr());
   EXPECT_TRUE(ew.has_exception_ptr());
@@ -244,6 +248,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) {
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(exception_wrapper::none(), ew.type());
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_EQ("", ew.class_name());
   EXPECT_EQ("", ew.what());
@@ -258,6 +264,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(typeid(std::runtime_error), ew.type());
   EXPECT_NE(nullptr, ew.get_exception());
+  EXPECT_NE(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_TRUE(ew.has_exception_ptr());
   EXPECT_EQ(ep, ew.to_exception_ptr());
   EXPECT_TRUE(ew.has_exception_ptr());
@@ -272,6 +280,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(exception_wrapper::none(), ew.type());
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_EQ("", ew.class_name());
   EXPECT_EQ("", ew.what());
@@ -285,6 +295,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) {
   auto ew = exception_wrapper(ep, from_eptr<int>(ep));
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_NE(nullptr, ew.get_object<int>());
   EXPECT_TRUE(ew.has_exception_ptr());
   EXPECT_EQ(ep, ew.to_exception_ptr());
   EXPECT_TRUE(ew.has_exception_ptr());
@@ -298,6 +310,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) {
   exception_wrapper(std::move(ew));
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_FALSE(ew.has_exception_ptr());
   EXPECT_EQ("", ew.class_name());
@@ -311,6 +325,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) {
   auto ew = exception_wrapper(folly::in_place, 42);
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_NE(nullptr, ew.get_object<int>());
   EXPECT_FALSE(ew.has_exception_ptr());
   EXPECT_EQ("int", ew.class_name());
   EXPECT_EQ("int", ew.what());
@@ -326,6 +342,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) {
   exception_wrapper(std::move(ew));
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_FALSE(ew.has_exception_ptr());
   EXPECT_EQ("", ew.class_name());
@@ -340,6 +358,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
   auto ew = exception_wrapper(ep); // concrete type is erased
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_NE(nullptr, ew.get_object<int>());
   EXPECT_EQ(ep, ew.to_exception_ptr());
   EXPECT_EQ("<unknown exception>", ew.class_name()); // because concrete type is
   // erased
@@ -352,6 +372,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
   exception_wrapper(std::move(ew));
   EXPECT_FALSE(bool(ew));
   EXPECT_EQ(nullptr, ew.get_exception());
+  EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+  EXPECT_EQ(nullptr, ew.get_object<int>());
   EXPECT_EQ(nullptr, ew.to_exception_ptr());
   EXPECT_EQ("", ew.class_name());
   EXPECT_EQ("", ew.what());