Only use format_as if no formatter is available

This commit is contained in:
timsong-cpp 2022-03-18 12:58:57 -05:00
parent ac0d9d5fe2
commit 88fe83765b
2 changed files with 23 additions and 1 deletions

View File

@ -1423,7 +1423,9 @@ template <typename Context> struct arg_mapper {
}
template <typename T, typename U = decltype(format_as(T())),
FMT_ENABLE_IF(std::is_enum<T>::value&& std::is_integral<U>::value)>
FMT_ENABLE_IF(std::is_enum<T>::value && std::is_integral<U>::value &&
!has_formatter<T, Context>::value &&
!has_fallback_formatter<T, char_type>::value)>
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
-> decltype(std::declval<arg_mapper>().map(U())) {
return map(format_as(val));

View File

@ -761,11 +761,28 @@ namespace test {
enum class formattable_scoped_enum {};
auto format_as(formattable_scoped_enum) -> int { return 42; }
enum class formattable_formatter_scoped_enum {};
auto format_as(formattable_formatter_scoped_enum) -> int { return 24; }
struct convertible_to_enum {
operator formattable_scoped_enum() const { return {}; }
};
} // namespace test
FMT_BEGIN_NAMESPACE
template <> struct formatter<::test::formattable_formatter_scoped_enum> {
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
auto format(::test::formattable_formatter_scoped_enum, format_context& ctx) const
-> decltype(ctx.out()) {
auto name = string_view("formattable_formatter_scoped_enum");
return std::copy_n(name.data(), name.size(), ctx.out());
}
};
FMT_END_NAMESPACE
TEST(core_test, is_formattable) {
#if 0
// This should be enabled once corresponding map overloads are gone.
@ -820,6 +837,9 @@ TEST(core_test, format_to) {
TEST(core_test, format_as) {
EXPECT_EQ(fmt::format("{}", test::formattable_scoped_enum()), "42");
EXPECT_EQ(fmt::format("{}", test::formattable_formatter_scoped_enum()), "formattable_formatter_scoped_enum");
const test::formattable_formatter_scoped_enum x{};
EXPECT_EQ(fmt::format("{}", x), "formattable_formatter_scoped_enum");
}
struct convertible_to_int {