Commit f0daf647 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

exception_wrapper::get_object<>

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
parent 4762a35e
...@@ -350,6 +350,20 @@ inline std::exception const* exception_wrapper::get_exception() const noexcept { ...@@ -350,6 +350,20 @@ inline std::exception const* exception_wrapper::get_exception() const noexcept {
return vptr_->get_exception_(this); 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() inline std::exception_ptr const& exception_wrapper::to_exception_ptr()
noexcept { noexcept {
// Computing an exception_ptr is expensive so cache the result. // Computing an exception_ptr is expensive so cache the result.
......
...@@ -457,6 +457,18 @@ class exception_wrapper final { ...@@ -457,6 +457,18 @@ class exception_wrapper final {
//! \overload //! \overload
std::exception const* get_exception() const noexcept; 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 //! \return A `std::exception_ptr` that references either the exception held
//! by `*this`, or a copy of same. //! by `*this`, or a copy of same.
//! \note This function may need to throw an exception to complete the action. //! \note This function may need to throw an exception to complete the action.
......
...@@ -215,6 +215,8 @@ TEST(ExceptionWrapper, with_exception_ptr_empty) { ...@@ -215,6 +215,8 @@ TEST(ExceptionWrapper, with_exception_ptr_empty) {
EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_EQ(exception_wrapper::none(), ew.type());
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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_FALSE(ew.has_exception_ptr());
EXPECT_EQ(nullptr, ew.to_exception_ptr()); EXPECT_EQ(nullptr, ew.to_exception_ptr());
EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr());
...@@ -230,6 +232,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) { ...@@ -230,6 +232,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) {
EXPECT_TRUE(bool(ew)); EXPECT_TRUE(bool(ew));
EXPECT_EQ(typeid(std::runtime_error), ew.type()); EXPECT_EQ(typeid(std::runtime_error), ew.type());
EXPECT_NE(nullptr, ew.get_exception()); 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_FALSE(ew.has_exception_ptr());
EXPECT_NE(nullptr, ew.to_exception_ptr()); EXPECT_NE(nullptr, ew.to_exception_ptr());
EXPECT_TRUE(ew.has_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr());
...@@ -244,6 +248,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) { ...@@ -244,6 +248,8 @@ TEST(ExceptionWrapper, with_shared_ptr_test) {
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_EQ(exception_wrapper::none(), ew.type());
EXPECT_EQ(nullptr, ew.get_exception()); 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(nullptr, ew.to_exception_ptr());
EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.class_name());
EXPECT_EQ("", ew.what()); EXPECT_EQ("", ew.what());
...@@ -258,6 +264,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) { ...@@ -258,6 +264,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
EXPECT_TRUE(bool(ew)); EXPECT_TRUE(bool(ew));
EXPECT_EQ(typeid(std::runtime_error), ew.type()); EXPECT_EQ(typeid(std::runtime_error), ew.type());
EXPECT_NE(nullptr, ew.get_exception()); 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_TRUE(ew.has_exception_ptr());
EXPECT_EQ(ep, ew.to_exception_ptr()); EXPECT_EQ(ep, ew.to_exception_ptr());
EXPECT_TRUE(ew.has_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr());
...@@ -272,6 +280,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) { ...@@ -272,6 +280,8 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(exception_wrapper::none(), ew.type()); EXPECT_EQ(exception_wrapper::none(), ew.type());
EXPECT_EQ(nullptr, ew.get_exception()); 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(nullptr, ew.to_exception_ptr());
EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.class_name());
EXPECT_EQ("", ew.what()); EXPECT_EQ("", ew.what());
...@@ -285,6 +295,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) { ...@@ -285,6 +295,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) {
auto ew = exception_wrapper(ep, from_eptr<int>(ep)); auto ew = exception_wrapper(ep, from_eptr<int>(ep));
EXPECT_TRUE(bool(ew)); EXPECT_TRUE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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_TRUE(ew.has_exception_ptr());
EXPECT_EQ(ep, ew.to_exception_ptr()); EXPECT_EQ(ep, ew.to_exception_ptr());
EXPECT_TRUE(ew.has_exception_ptr()); EXPECT_TRUE(ew.has_exception_ptr());
...@@ -298,6 +310,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) { ...@@ -298,6 +310,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) {
exception_wrapper(std::move(ew)); exception_wrapper(std::move(ew));
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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(nullptr, ew.to_exception_ptr());
EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr());
EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.class_name());
...@@ -311,6 +325,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) { ...@@ -311,6 +325,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) {
auto ew = exception_wrapper(folly::in_place, 42); auto ew = exception_wrapper(folly::in_place, 42);
EXPECT_TRUE(bool(ew)); EXPECT_TRUE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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_FALSE(ew.has_exception_ptr());
EXPECT_EQ("int", ew.class_name()); EXPECT_EQ("int", ew.class_name());
EXPECT_EQ("int", ew.what()); EXPECT_EQ("int", ew.what());
...@@ -326,6 +342,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) { ...@@ -326,6 +342,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) {
exception_wrapper(std::move(ew)); exception_wrapper(std::move(ew));
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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(nullptr, ew.to_exception_ptr());
EXPECT_FALSE(ew.has_exception_ptr()); EXPECT_FALSE(ew.has_exception_ptr());
EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.class_name());
...@@ -340,6 +358,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) { ...@@ -340,6 +358,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
auto ew = exception_wrapper(ep); // concrete type is erased auto ew = exception_wrapper(ep); // concrete type is erased
EXPECT_TRUE(bool(ew)); EXPECT_TRUE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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(ep, ew.to_exception_ptr());
EXPECT_EQ("<unknown exception>", ew.class_name()); // because concrete type is EXPECT_EQ("<unknown exception>", ew.class_name()); // because concrete type is
// erased // erased
...@@ -352,6 +372,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) { ...@@ -352,6 +372,8 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
exception_wrapper(std::move(ew)); exception_wrapper(std::move(ew));
EXPECT_FALSE(bool(ew)); EXPECT_FALSE(bool(ew));
EXPECT_EQ(nullptr, ew.get_exception()); 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(nullptr, ew.to_exception_ptr());
EXPECT_EQ("", ew.class_name()); EXPECT_EQ("", ew.class_name());
EXPECT_EQ("", ew.what()); EXPECT_EQ("", ew.what());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment