From 8f8a1a02d5c5cb967d240feee3ffac00d66f22a2 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 14 Jan 2022 13:08:14 -0800 Subject: [PATCH] Fix handling of formattable types implicitly convertible to pointers --- include/fmt/core.h | 5 +++-- test/core-test.cc | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index f2d21e5c5a..12571ce0da 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -1398,10 +1398,11 @@ template struct arg_mapper { template < typename T, FMT_ENABLE_IF( - std::is_member_pointer::value || + std::is_pointer::value || std::is_member_pointer::value || std::is_function::type>::value || (std::is_convertible::value && - !std::is_convertible::value))> + !std::is_convertible::value && + !has_formatter::value))> FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { return {}; } diff --git a/test/core-test.cc b/test/core-test.cc index b2f2097ea1..c9eea8ffd8 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -737,6 +737,24 @@ struct convertible_to_pointer { operator const int*() const { return nullptr; } }; +struct convertible_to_pointer_formattable { + operator const int*() const { return nullptr; } +}; + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + auto format(convertible_to_pointer_formattable, format_context& ctx) const + -> decltype(ctx.out()) { + auto test = string_view("test"); + return std::copy_n(test.data(), test.size(), ctx.out()); + } +}; +FMT_END_NAMESPACE + enum class test_scoped_enum {}; TEST(core_test, is_formattable) { @@ -770,11 +788,12 @@ TEST(core_test, is_formattable) { #endif static_assert(!fmt::is_formattable::value, ""); + const auto f = convertible_to_pointer_formattable(); + EXPECT_EQ(fmt::format("{}", f), "test"); static_assert(!fmt::is_formattable::value, ""); struct s; - static_assert(!fmt::is_formattable::value, ""); static_assert(!fmt::is_formattable::value, ""); static_assert(!fmt::is_formattable::value, "");