<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From 8f8a1a02d5c5cb967d240feee3ffac00d66f22a2 Mon Sep 17 00:00:00 2001
From: Victor Zverovich &lt;viz@fb.com&gt;
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 &lt;typename Context&gt; struct arg_mapper {
   template &lt;
       typename T,
       FMT_ENABLE_IF(
-          std::is_member_pointer&lt;T&gt;::value ||
+          std::is_pointer&lt;T&gt;::value || std::is_member_pointer&lt;T&gt;::value ||
           std::is_function&lt;typename std::remove_pointer&lt;T&gt;::type&gt;::value ||
           (std::is_convertible&lt;const T&amp;, const void*&gt;::value &amp;&amp;
-           !std::is_convertible&lt;const T&amp;, const char_type*&gt;::value))&gt;
+           !std::is_convertible&lt;const T&amp;, const char_type*&gt;::value &amp;&amp;
+           !has_formatter&lt;T, Context&gt;::value))&gt;
   FMT_CONSTEXPR auto map(const T&amp;) -&gt; 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 &lt;&gt; struct formatter&lt;convertible_to_pointer_formattable&gt; {
+  auto parse(format_parse_context&amp; ctx) -&gt; decltype(ctx.begin()) {
+    return ctx.begin();
+  }
+
+  auto format(convertible_to_pointer_formattable, format_context&amp; ctx) const
+      -&gt; 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&lt;convertible_to_pointer&gt;::value, "");
+  const auto f = convertible_to_pointer_formattable();
+  EXPECT_EQ(fmt::format("{}", f), "test");
 
   static_assert(!fmt::is_formattable&lt;void (*)()&gt;::value, "");
 
   struct s;
-
   static_assert(!fmt::is_formattable&lt;int(s::*)&gt;::value, "");
   static_assert(!fmt::is_formattable&lt;int (s::*)()&gt;::value, "");
   static_assert(!fmt::is_formattable&lt;test_scoped_enum&gt;::value, "");
</pre></body></html>