From a476850036e4431054831fc7e83889afedc77829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20B=C3=B8e?= <94781160+cptFracassa@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:31:32 +0100 Subject: [PATCH] fix: support optional with format_as(T) Formatting a std::optional where T had a custom format_as(T) function failed to compile with clang, due to set_debug_format being hidden by private inheritance. This fix makes the function available through a using clause. --- include/fmt/format.h | 1 + test/std-test.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/fmt/format.h b/include/fmt/format.h index 4104d91fc7cd3..f34c97b11c742 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -4053,6 +4053,7 @@ struct formatter::value>> : private formatter, Char> { using base = formatter, Char>; using base::parse; + using base::set_debug_format; template auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { diff --git a/test/std-test.cc b/test/std-test.cc index 41183dbfa941a..d673ea2ce2aa2 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -90,6 +90,34 @@ TEST(std_test, optional) { #endif } +namespace my_nso { +enum class my_number { + one, + two, +}; +auto format_as(my_number number) { + return number == my_number::one ? "first" : "second"; +} + +class my_class { + public: + int av; + + private: + friend auto format_as(const my_class& elm) { return fmt::to_string(elm.av); } +}; +} // namespace my_nso +TEST(std_test, optional_format_as) { +#ifdef __cpp_lib_optional + EXPECT_EQ(fmt::format("{}", std::optional{}), "none"); + EXPECT_EQ(fmt::format("{}", std::optional{my_nso::my_number::one}), + "optional(\"first\")"); + EXPECT_EQ(fmt::format("{}", std::optional{}), "none"); + EXPECT_EQ(fmt::format("{}", std::optional{my_nso::my_class{7}}), + "optional(\"7\")"); +#endif +} + struct throws_on_move { throws_on_move() = default;