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.
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.
*/
}
+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;