Commit 085c0a8d authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by facebook-github-bot-0

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
parent e9df6f79
......@@ -223,6 +223,18 @@ class exception_wrapper {
return false;
}
template <class F>
bool with_exception(F&& f) {
using arg_type = typename functor_traits<F>::arg_type_decayed;
return with_exception<arg_type>(std::forward<F>(f));
}
template <class F>
bool with_exception(F&& f) const {
using arg_type = typename functor_traits<F>::arg_type_decayed;
return with_exception<const arg_type>(std::forward<F>(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 <typename F>
struct functor_traits {
template <typename T>
struct impl;
template <typename C, typename R, typename A>
struct impl<R(C::*)(A)> { using arg_type = A; };
template <typename C, typename R, typename A>
struct impl<R(C::*)(A) const> { using arg_type = A; };
using arg_type = typename impl<decltype(&F::operator())>::arg_type;
using arg_type_decayed = typename std::decay<arg_type>::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.
......
......@@ -203,6 +203,34 @@ TEST(ExceptionWrapper, with_exception_test) {
*/
}
TEST(ExceptionWrapper, with_exception_deduction) {
auto ew = make_exception_wrapper<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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;
......
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