fix: support optional<T> with format_as(T) (#3713)

Formatting a std::optional<T> 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.
This commit is contained in:
Ole Bøe 2023-11-17 00:02:33 +01:00 committed by GitHub
parent 649fe0fc8b
commit 864a8b5f38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 0 deletions

View File

@ -4054,6 +4054,7 @@ struct formatter<T, Char, enable_if_t<detail::has_format_as<T>::value>>
: private formatter<detail::format_as_t<T>, Char> { : private formatter<detail::format_as_t<T>, Char> {
using base = formatter<detail::format_as_t<T>, Char>; using base = formatter<detail::format_as_t<T>, Char>;
using base::parse; using base::parse;
using base::set_debug_format;
template <typename FormatContext> template <typename FormatContext>
auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) {

View File

@ -90,6 +90,36 @@ TEST(std_test, optional) {
#endif #endif
} }
namespace my_nso {
enum class my_number {
one,
two,
};
auto format_as(my_number number) -> fmt::string_view {
return number == my_number::one ? "first" : "second";
}
class my_class {
public:
int av;
private:
friend auto format_as(const my_class& elm) -> std::string {
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<my_nso::my_number>{}), "none");
EXPECT_EQ(fmt::format("{}", std::optional{my_nso::my_number::one}),
"optional(\"first\")");
EXPECT_EQ(fmt::format("{}", std::optional<my_nso::my_class>{}), "none");
EXPECT_EQ(fmt::format("{}", std::optional{my_nso::my_class{7}}),
"optional(\"7\")");
#endif
}
struct throws_on_move { struct throws_on_move {
throws_on_move() = default; throws_on_move() = default;