diff --git a/include/fmt/base.h b/include/fmt/base.h index e4cdd5ec..1bfa4344 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1081,15 +1081,18 @@ enum { long_short = sizeof(long) == sizeof(int) }; using long_type = conditional_t; using ulong_type = conditional_t; -template struct format_as_result { - template ::value || std::is_class::value)> - static auto map(U*) -> remove_cvref_t()))>; - static auto map(...) -> void; +template +using format_as_result = + remove_cvref_t()))>; - using type = decltype(map(static_cast(nullptr))); -}; -template using format_as_t = typename format_as_result::type; +template +struct use_format_as : std::false_type {}; + +// Only map owning types because mapping views can be unsafe. +template +struct use_format_as< + T, bool_constant>::value>> + : std::true_type {}; template constexpr auto has_const_formatter_impl(T*) @@ -1193,10 +1196,8 @@ template struct arg_mapper { return x; } - // Only map owning types because mapping views can be unsafe. - template , - FMT_ENABLE_IF(std::is_arithmetic::value)> - FMT_MAP_API auto map(const T& x) -> decltype(map(U())) { + template ::value)> + FMT_MAP_API auto map(const T& x) -> decltype(map(format_as(x))) { return map(format_as(x)); } @@ -1222,7 +1223,7 @@ template struct arg_mapper { std::is_union::value || std::is_fundamental::value) && !has_to_string_view::value && !is_char::value && !is_named_arg::value && !std::is_integral::value && - !std::is_arithmetic>::value)> + !use_format_as::value)> FMT_MAP_API auto map(T& x) -> decltype(do_map(x)) { return do_map(x); } diff --git a/include/fmt/format.h b/include/fmt/format.h index bd4ae809..25968f26 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3826,10 +3826,6 @@ using fmt::report_error; FMT_API void report_error(format_func func, int error_code, const char* message) noexcept; -template -struct has_format_as - : bool_constant, void>::value> {}; - FMT_BEGIN_EXPORT #ifndef FMT_HEADER_ONLY @@ -3859,13 +3855,13 @@ FMT_CONSTEXPR auto native_formatter::format( } // namespace detail template -struct formatter::value>> - : formatter, Char> { +struct formatter>> + : formatter, Char> { template FMT_CONSTEXPR auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto&& val = format_as(value); // Make an lvalue reference for format. - return formatter, Char>::format(val, ctx); + return formatter, Char>::format(val, ctx); } }; @@ -4303,20 +4299,19 @@ FMT_NODISCARD auto to_string(T value) -> std::string { return {buffer, detail::write(begin, value)}; } +template ::value)> +FMT_NODISCARD auto to_string(const T& value) -> std::string { + return to_string(format_as(value)); +} + template ::value && - !detail::has_format_as::value)> + !detail::use_format_as::value)> FMT_NODISCARD auto to_string(const T& value) -> std::string { auto buffer = memory_buffer(); detail::write(appender(buffer), value); return {buffer.data(), buffer.size()}; } -template ::value && - detail::has_format_as::value)> -FMT_NODISCARD auto to_string(const T& value) -> std::string { - return to_string(format_as(value)); -} - FMT_END_EXPORT FMT_END_NAMESPACE