From 085c0a8da601091ec70d01e3a8d6bdbd8501afa6 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Tue, 24 Nov 2015 18:27:46 -0800 Subject: [PATCH] ExceptionWrapper::with_exception variant, deducing exception type from functor type Summary: [Folly] `ExceptionWrapper::with_exception` variant deducing exception type from functor type. From the `README.md`: // TODO(jsedgwick) infer exception type from the type of the function Reviewed By: Gownta Differential Revision: D2685579 fb-gh-sync-id: 158bcd030019f28b4f392d17167ab0bd67cc1edb --- folly/ExceptionWrapper.h | 24 ++++++++++++++++++++++++ folly/test/ExceptionWrapperTest.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/folly/ExceptionWrapper.h b/folly/ExceptionWrapper.h index bc8c9758..70eb996b 100644 --- a/folly/ExceptionWrapper.h +++ b/folly/ExceptionWrapper.h @@ -223,6 +223,18 @@ class exception_wrapper { return false; } + template + bool with_exception(F&& f) { + using arg_type = typename functor_traits::arg_type_decayed; + return with_exception(std::forward(f)); + } + + template + bool with_exception(F&& f) const { + using arg_type = typename functor_traits::arg_type_decayed; + return with_exception(std::forward(f)); + } + // If this exception wrapper wraps an exception of type Ex, with_exception // will call f with the wrapped exception as an argument and return true, and // will otherwise return false. @@ -310,6 +322,18 @@ protected: friend exception_wrapper make_exception_wrapper(Args&&... args); private: + template + struct functor_traits { + template + struct impl; + template + struct impl { using arg_type = A; }; + template + struct impl { using arg_type = A; }; + using arg_type = typename impl::arg_type; + using arg_type_decayed = typename std::decay::type; + }; + // What makes this useful is that T can be exception_wrapper* or // const exception_wrapper*, and the compiler will use the // instantiation which works with F. diff --git a/folly/test/ExceptionWrapperTest.cpp b/folly/test/ExceptionWrapperTest.cpp index 723dff04..61395df7 100644 --- a/folly/test/ExceptionWrapperTest.cpp +++ b/folly/test/ExceptionWrapperTest.cpp @@ -203,6 +203,34 @@ TEST(ExceptionWrapper, with_exception_test) { */ } +TEST(ExceptionWrapper, with_exception_deduction) { + auto ew = make_exception_wrapper("hi"); + EXPECT_TRUE(ew.with_exception([](std::runtime_error&) {})); + EXPECT_TRUE(ew.with_exception([](std::exception&) {})); + EXPECT_FALSE(ew.with_exception([](std::logic_error&) {})); +} + +TEST(ExceptionWrapper, with_exception_deduction_const) { + auto ew = make_exception_wrapper("hi"); + EXPECT_TRUE(ew.with_exception([](const std::runtime_error&) {})); + EXPECT_TRUE(ew.with_exception([](const std::exception&) {})); + EXPECT_FALSE(ew.with_exception([](const std::logic_error&) {})); +} + +TEST(ExceptionWrapper, with_exception_deduction_const_const) { + const auto cew = make_exception_wrapper("hi"); + EXPECT_TRUE(cew.with_exception([](const std::runtime_error&) {})); + EXPECT_TRUE(cew.with_exception([](const std::exception&) {})); + EXPECT_FALSE(cew.with_exception([](const std::logic_error&) {})); +} + +TEST(ExceptionWrapper, with_exception_deduction_returning) { + auto ew = make_exception_wrapper("hi"); + EXPECT_TRUE(ew.with_exception([](std::runtime_error&) { return 3; })); + EXPECT_TRUE(ew.with_exception([](std::exception&) { return "hello"; })); + EXPECT_FALSE(ew.with_exception([](std::logic_error&) { return nullptr; })); +} + TEST(ExceptionWrapper, non_std_exception_test) { int expected = 17; -- 2.34.1