From 41977277125299adb7d21e5ec0f62e0367ae37f1 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Mon, 16 Sep 2024 18:52:18 -0700 Subject: [PATCH] Improve handling of unformattable args --- include/fmt/base.h | 37 ++++++++++++++++++------------------- include/fmt/format.h | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index ac53e464..23ef0c50 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1123,8 +1123,14 @@ constexpr auto has_const_formatter() -> bool { return has_const_formatter_impl(static_cast(nullptr)); } -// Maps formatting argument types to a smaller set. Returns void on -// errors to be SFINAE-friendly. +template > +struct formattable + : bool_constant() || + (std::is_constructible>::value && + !std::is_const::value)> {}; + +// Maps formatting argument types to natively supported types or user-defined +// types with formatters. Returns void on errors to be SFINAE-friendly. template struct type_mapper { static auto map(signed char) -> int; static auto map(unsigned char) -> unsigned; @@ -1176,14 +1182,8 @@ template struct type_mapper { template ::value)> static auto map(const T& x) -> decltype(map(format_as(x))); - template > - struct formattable - : bool_constant() || - (std::is_constructible>::value && - !std::is_const::value)> {}; - template >::value)> - static auto map(T&) -> conditional_t::value, T&, void>; + static auto map(T&) -> conditional_t::value, T&, void>; template ::value)> static auto map(const T& named_arg) -> decltype(map(named_arg.value)); @@ -2192,23 +2192,15 @@ template class value { : named_args{args, size} {} private: - template FMT_CONSTEXPR value(const T& x, custom_tag) { + template ::value)> + FMT_CONSTEXPR value(const T& x, custom_tag) { using value_type = remove_cvref_t; - enum { formattable = !std::is_same::value }; - #if defined(__cpp_if_constexpr) - if constexpr (!formattable) type_is_unformattable_for _; - // T may overload operator& e.g. std::vector::reference in libc++. if constexpr (std::is_same*>::value) custom.value = const_cast(&x); #endif - static_assert( - formattable, - "cannot format an argument; to make type T formattable provide a " - "formatter specialization: https://fmt.dev/latest/api.html#udt"); - custom.value = nullptr; if (!is_constant_evaluated()) custom.value = @@ -2216,6 +2208,13 @@ template class value { custom.format = format_custom>; } + template ::value)> + FMT_CONSTEXPR value(const T&, custom_tag) { + // Cannot format an argument; to make type T formattable provide a + // formatter specialization: https://fmt.dev/latest/api.html#udt. + type_is_unformattable_for _; + } + // Formats an argument of a custom type, such as a user-defined class. template static void format_custom(void* arg, parse_context& parse_ctx, diff --git a/include/fmt/format.h b/include/fmt/format.h index e7b0dcd1..58f52990 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -779,7 +779,7 @@ using is_integer = #if FMT_USE_FLOAT128 using float128 = __float128; #else -using float128 = void; +struct float128 {}; #endif template using is_float128 = std::is_same;