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

Try::tryGetExceptionObject

Summary:
[Folly] `Try::tryGetExceptionObject`.

If the `Try` has a `std::exception` for the non-template overload or a `From` where `is_convertible<From*, Ex*>` 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
parent 3c7ee0d0
......@@ -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<From*, Ex*>`; otherwise,
* returns `nullptr`.
*/
template <class E>
E* tryGetExceptionObject() {
return hasException() ? e_.get_exception<E>() : nullptr;
}
template <class E>
E const* tryGetExceptionObject() const {
return hasException() ? e_.get_exception<E>() : nullptr;
}
/*
* If the Try contains an exception and it is of type Ex, execute func(Ex)
*
......@@ -339,6 +364,31 @@ class Try<void> {
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<From*, Ex*>`; otherwise,
* returns `nullptr`.
*/
template <class E>
E* tryGetExceptionObject() {
return hasException() ? e_.get_exception<E>() : nullptr;
}
template <class E>
E const* tryGetExceptionObject() const {
return hasException() ? e_.get_exception<E>() : nullptr;
}
/*
* If the Try contains an exception and it is of type Ex, execute func(Ex)
*
......
......@@ -14,8 +14,11 @@
* limitations under the License.
*/
#include <folly/Memory.h>
#include <folly/Try.h>
#include <glog/logging.h>
#include <folly/Memory.h>
#include <folly/portability/GTest.h>
using namespace folly;
......@@ -89,3 +92,106 @@ TEST(Try, makeTryWithVoidThrow) {
auto result = makeTryWith(func);
EXPECT_TRUE(result.hasException<std::runtime_error>());
}
template <typename E>
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<std::range_error>(epexn));
auto num = CHECK_NOTNULL(get_exception<int>(epnum));
{
auto t = Try<bool>(true);
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto t = Try<bool>(exception_wrapper(epexn, *exn));
EXPECT_EQ(exn, t.tryGetExceptionObject());
EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto t = Try<bool>(exception_wrapper(epnum, *num));
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(num, t.tryGetExceptionObject<int>());
}
{
auto t = Try<void>();
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto t = Try<void>(exception_wrapper(epexn, *exn));
EXPECT_EQ(exn, t.tryGetExceptionObject());
EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto t = Try<void>(exception_wrapper(epnum, *num));
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(num, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<bool>(true);
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<bool>(exception_wrapper(epexn, *exn));
EXPECT_EQ(exn, t.tryGetExceptionObject());
EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<bool>(exception_wrapper(epnum, *num));
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(num, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<void>();
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<void>(exception_wrapper(epexn, *exn));
EXPECT_EQ(exn, t.tryGetExceptionObject());
EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
}
{
auto const t = Try<void>(exception_wrapper(epnum, *num));
EXPECT_EQ(nullptr, t.tryGetExceptionObject());
EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
EXPECT_EQ(num, t.tryGetExceptionObject<int>());
}
}
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