Fix ExceptionWrapper::with_exception to support lvalue ref functors
authorYedidya Feldblum <yfeldblum@fb.com>
Thu, 26 Nov 2015 05:48:38 +0000 (21:48 -0800)
committerfacebook-github-bot-0 <folly-bot@fb.com>
Thu, 26 Nov 2015 06:20:20 +0000 (22:20 -0800)
Summary: [Folly] Fix `ExceptionWrapper::with_exception` to support lvalue ref functors.

Ex:

    auto handler = [&](const std::runtime_error& e) { handle_runtime_error(e); };
    exception_wrapper wrap = get_some_exception_wrapper_from_context();
    wrap.with_exception(handler); // broken before this diff, fixed after

Reviewed By: markisaa

Differential Revision: D2698680

fb-gh-sync-id: 4976ba08e3601e22891d00d79a5dae5118887b71

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

index 70eb996bd433a7c906267492aa77471db6dc4c68..f97f1a8ec2544824166b39ddd15f32fe6b418f99 100644 (file)
@@ -330,7 +330,9 @@ private:
     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 functor_decayed = typename std::decay<F>::type;
+    using functor_op = decltype(&functor_decayed::operator());
+    using arg_type = typename impl<functor_op>::arg_type;
     using arg_type_decayed = typename std::decay<arg_type>::type;
   };
 
index 61395df7ca1d53cd965767279ad2d63fb908636a..265c5b02a5997fef53b2bcb31cb6d4ab808fcb88 100644 (file)
@@ -210,14 +210,14 @@ TEST(ExceptionWrapper, with_exception_deduction) {
   EXPECT_FALSE(ew.with_exception([](std::logic_error&) {}));
 }
 
-TEST(ExceptionWrapper, with_exception_deduction_const) {
+TEST(ExceptionWrapper, with_exception_deduction_exn_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) {
+TEST(ExceptionWrapper, with_exception_deduction_wrap_const_exn_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&) {}));
@@ -231,6 +231,18 @@ TEST(ExceptionWrapper, with_exception_deduction_returning) {
   EXPECT_FALSE(ew.with_exception([](std::logic_error&) { return nullptr; }));
 }
 
+namespace {
+template <typename T>
+T& r_to_l(T v) { return std::ref(v); }
+}
+
+TEST(ExceptionWrapper, with_exception_deduction_functor_lvalue) {
+  auto ew = make_exception_wrapper<std::runtime_error>("hi");
+  EXPECT_TRUE(ew.with_exception(r_to_l([](std::runtime_error&) {})));
+  EXPECT_TRUE(ew.with_exception(r_to_l([](std::exception&) {})));
+  EXPECT_FALSE(ew.with_exception(r_to_l([](std::logic_error&) {})));
+}
+
 TEST(ExceptionWrapper, non_std_exception_test) {
   int expected = 17;