diff --git a/include/fmt/std.h b/include/fmt/std.h index f7d8d4956a6a..d606508bcbf4 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -649,6 +649,25 @@ struct formatter< } }; +template <> struct formatter : formatter { + template + auto format(const std::exception_ptr& ex_ptr, FormatContext& ctx) const + -> decltype(ctx.out()) { + if (!ex_ptr) { + return detail::write(ctx.out(), string_view("nullptr")); + } + + try { + std::rethrow_exception(ex_ptr); + } catch (const std::exception& e) { + // Reuses the base formatter::format behavior perfectly + return formatter::format(e, ctx); + } catch (...) { + return detail::write(ctx.out(), string_view("unknown exception")); + } + } +}; + template struct formatter, Char> : formatter { static_assert(N <= 64, "unsupported _BitInt"); diff --git a/test/std-test.cc b/test/std-test.cc index f6fc12847282..b308fe383d70 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -404,6 +404,26 @@ TEST(std_test, exception) { #endif } +TEST(std_test, exception_ptr) { + std::exception_ptr p1 = nullptr; + std::exception_ptr p2; + + try { + using namespace my_ns1::my_ns2; + throw my_exception("My Exception"); + } catch (...) { + p2 = std::current_exception(); + } + + EXPECT_EQ(fmt::format("{}", p1), "nullptr"); + EXPECT_EQ(fmt::format("{}", p2), "My Exception"); + +#if FMT_USE_RTTI + EXPECT_EQ(fmt::format("{:t}", p2), + "my_ns1::my_ns2::my_exception: My Exception"); +#endif +} + #if FMT_USE_RTTI TEST(std_test, type_info) { EXPECT_EQ(fmt::format("{}", typeid(std::runtime_error)),