diff --git a/include/fmt/std.h b/include/fmt/std.h index 41d2b2838b6d7..39fa776244d06 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -8,6 +8,7 @@ #ifndef FMT_STD_H_ #define FMT_STD_H_ +#include #include #include #include @@ -166,6 +167,21 @@ struct formatter< } }; FMT_END_NAMESPACE -#endif + +#endif // __cpp_lib_variant + +FMT_BEGIN_NAMESPACE +template +struct formatter< + T, Char, + typename std::enable_if::value>::type> + : formatter { + template + auto format(const std::exception& ex, FormatContext& ctx) const -> + typename FormatContext::iterator { + return fmt::formatter::format(ex.what(), ctx); + } +}; +FMT_END_NAMESPACE #endif // FMT_STD_H_ diff --git a/test/std-test.cc b/test/std-test.cc index c22b3e38fb39b..51363efff986a 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -6,11 +6,11 @@ // For the license information refer to format.h. #include "fmt/std.h" -#include "fmt/ranges.h" #include #include +#include "fmt/ranges.h" #include "gtest/gtest.h" TEST(std_test, path) { @@ -77,3 +77,34 @@ TEST(std_test, variant) { EXPECT_EQ(fmt::format("{}", v5), "variant(\"yes, this is variant\")"); #endif } + +TEST(std_test, exception) { +#if defined(_MSC_VER) +# if _MSC_VER > 1920 + std::string str("invalid vector subscript"); +# else + std::string str("invalid vector subscript"); +# endif +#elif not defined(NDEBUG) && (defined(__clang__) || defined(__GNUC__)) || defined (__APPLE__) + std::string str("vector::_M_range_check: __n (which is 42) >= this->size() (which is 0)"); +#else + std::string str("vector"); +#endif + std::string escstr = fmt::format("\"{}\"", str); + + try { + std::vector vec; + std::ignore = vec.at(42); + } catch (const std::exception& ex) { + EXPECT_EQ(fmt::format("{}", ex), str); + EXPECT_EQ(fmt::format("{:?}", ex), escstr); + } + + try { + std::vector vec; + std::ignore = vec.at(42); + } catch (const std::out_of_range& ex) { + EXPECT_EQ(fmt::format("{}", ex), str); + EXPECT_EQ(fmt::format("{:?}", ex), escstr); + } +}