Skip to content

Commit

Permalink
Fix handling of formattable types implicitly convertible to pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Jan 14, 2022
1 parent b02e5af commit 8f8a1a0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
5 changes: 3 additions & 2 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1398,10 +1398,11 @@ template <typename Context> struct arg_mapper {
template <
typename T,
FMT_ENABLE_IF(
std::is_member_pointer<T>::value ||
std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
std::is_function<typename std::remove_pointer<T>::type>::value ||
(std::is_convertible<const T&, const void*>::value &&
!std::is_convertible<const T&, const char_type*>::value))>
!std::is_convertible<const T&, const char_type*>::value &&
!has_formatter<T, Context>::value))>
FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
return {};
}
Expand Down
21 changes: 20 additions & 1 deletion test/core-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<convertible_to_pointer_formattable> {
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) {
Expand Down Expand Up @@ -770,11 +788,12 @@ TEST(core_test, is_formattable) {
#endif

static_assert(!fmt::is_formattable<convertible_to_pointer>::value, "");
const auto f = convertible_to_pointer_formattable();
EXPECT_EQ(fmt::format("{}", f), "test");

static_assert(!fmt::is_formattable<void (*)()>::value, "");

struct s;

static_assert(!fmt::is_formattable<int(s::*)>::value, "");
static_assert(!fmt::is_formattable<int (s::*)()>::value, "");
static_assert(!fmt::is_formattable<test_scoped_enum>::value, "");
Expand Down

0 comments on commit 8f8a1a0

Please sign in to comment.