diff --git a/include/spdlog/fmt/bundled/base.h b/include/spdlog/fmt/bundled/base.h index 9eeeb2ce..b886317d 100644 --- a/include/spdlog/fmt/bundled/base.h +++ b/include/spdlog/fmt/bundled/base.h @@ -21,7 +21,7 @@ #endif // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 110103 +#define FMT_VERSION 110104 // Detect compiler versions. #if defined(__clang__) && !defined(__ibmxl__) @@ -294,8 +294,8 @@ #endif #define FMT_APPLY_VARIADIC(expr) \ - using ignore = int[]; \ - (void)ignore { 0, (expr, 0)... } + using unused = int[]; \ + (void)unused { 0, (expr, 0)... } // Enable minimal optimizations for more compact code in debug mode. FMT_PRAGMA_GCC(push_options) @@ -537,7 +537,7 @@ template class basic_string_view { FMT_ALWAYS_INLINE #endif FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) { -#if FMT_HAS_BUILTIN(__buitin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION +#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION if (std::is_same::value) { size_ = __builtin_strlen(detail::narrow(s)); return; @@ -740,7 +740,7 @@ class basic_specs { }; unsigned data_ = 1 << fill_size_shift; - static_assert(sizeof(data_) * CHAR_BIT >= 18, ""); + static_assert(sizeof(basic_specs::data_) * CHAR_BIT >= 18, ""); // Character (code unit) type is erased to prevent template bloat. char fill_data_[max_fill_size] = {' '}; @@ -2263,15 +2263,15 @@ template <> struct is_output_iterator : std::true_type {}; template struct is_output_iterator< It, T, - void_t&>()++ = std::declval())>> - : std::true_type {}; + enable_if_t&>()++), + T>::value>> : std::true_type {}; #ifndef FMT_USE_LOCALE # define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1) #endif // A type-erased reference to an std::locale to avoid a heavy include. -struct locale_ref { +class locale_ref { #if FMT_USE_LOCALE private: const void* locale_; // A type-erased pointer to std::locale. @@ -2283,6 +2283,7 @@ struct locale_ref { inline explicit operator bool() const noexcept { return locale_ != nullptr; } #endif // FMT_USE_LOCALE + public: template auto get() const -> Locale; }; @@ -2729,9 +2730,9 @@ template struct fstring { std::is_same::value)> FMT_ALWAYS_INLINE fstring(const S&) : str(S()) { FMT_CONSTEXPR auto sv = string_view(S()); - FMT_CONSTEXPR int ignore = + FMT_CONSTEXPR int unused = (parse_format_string(sv, checker(sv, arg_pack())), 0); - detail::ignore_unused(ignore); + detail::ignore_unused(unused); } fstring(runtime_format_string<> fmt) : str(fmt.str) {} diff --git a/include/spdlog/fmt/bundled/compile.h b/include/spdlog/fmt/bundled/compile.h index 68b451c7..08d9427f 100644 --- a/include/spdlog/fmt/bundled/compile.h +++ b/include/spdlog/fmt/bundled/compile.h @@ -19,11 +19,11 @@ FMT_BEGIN_NAMESPACE // A compile-time string which is compiled into fast formatting code. FMT_EXPORT class compiled_string {}; -namespace detail { - template struct is_compiled_string : std::is_base_of {}; +namespace detail { + /** * Converts a string literal `s` into a format string that will be parsed at * compile time and converted into efficient formatting code. Requires C++17 @@ -41,16 +41,6 @@ struct is_compiled_string : std::is_base_of {}; # define FMT_COMPILE(s) FMT_STRING(s) #endif -#if FMT_USE_NONTYPE_TEMPLATE_ARGS -template Str> -struct udl_compiled_string : compiled_string { - using char_type = Char; - constexpr explicit operator basic_string_view() const { - return {Str.data, N - 1}; - } -}; -#endif - template auto first(const T& value, const Tail&...) -> const T& { return value; @@ -425,7 +415,7 @@ constexpr auto compile_format_string(S fmt) { } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> constexpr auto compile(S fmt) { constexpr auto str = basic_string_view(fmt); if constexpr (str.size() == 0) { @@ -461,7 +451,7 @@ constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> FMT_INLINE std::basic_string format(const S&, Args&&... args) { if constexpr (std::is_same::value) { @@ -488,7 +478,7 @@ FMT_INLINE std::basic_string format(const S&, } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { constexpr auto compiled = detail::compile(S()); if constexpr (std::is_same, @@ -503,7 +493,7 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { #endif template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) -> format_to_n_result { using traits = detail::fixed_buffer_traits; @@ -513,7 +503,7 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) -> size_t { auto buf = detail::counting_buffer<>(); @@ -522,7 +512,7 @@ FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> void print(std::FILE* f, const S& fmt, const Args&... args) { auto buf = memory_buffer(); fmt::format_to(appender(buf), fmt, args...); @@ -530,7 +520,7 @@ void print(std::FILE* f, const S& fmt, const Args&... args) { } template ::value)> + FMT_ENABLE_IF(is_compiled_string::value)> void print(const S& fmt, const Args&... args) { print(stdout, fmt, args...); } @@ -538,9 +528,7 @@ void print(const S& fmt, const Args&... args) { #if FMT_USE_NONTYPE_TEMPLATE_ARGS inline namespace literals { template constexpr auto operator""_cf() { - using char_t = remove_cvref_t; - return detail::udl_compiled_string(); + return FMT_COMPILE(Str.data); } } // namespace literals #endif diff --git a/include/spdlog/fmt/bundled/format.h b/include/spdlog/fmt/bundled/format.h index 4466b4f4..287e7163 100644 --- a/include/spdlog/fmt/bundled/format.h +++ b/include/spdlog/fmt/bundled/format.h @@ -2332,7 +2332,7 @@ template > FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, const format_specs& specs, sign s, - locale_ref loc) -> OutputIt { + int exp_upper, locale_ref loc) -> OutputIt { auto significand = f.significand; int significand_size = get_significand_size(f); const Char zero = static_cast('0'); @@ -2348,7 +2348,7 @@ FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, if (specs.type() == presentation_type::fixed) return false; // Use the fixed notation if the exponent is in [exp_lower, exp_upper), // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. - const int exp_lower = -4, exp_upper = 16; + const int exp_lower = -4; return output_exp < exp_lower || output_exp >= (specs.precision > 0 ? specs.precision : exp_upper); }; @@ -2451,12 +2451,13 @@ template class fallback_digit_grouping { template FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, const format_specs& specs, sign s, - locale_ref loc) -> OutputIt { + int exp_upper, locale_ref loc) -> OutputIt { if (is_constant_evaluated()) { return do_write_float>(out, f, specs, s, loc); + fallback_digit_grouping>(out, f, specs, s, + exp_upper, loc); } else { - return do_write_float(out, f, specs, s, loc); + return do_write_float(out, f, specs, s, exp_upper, loc); } } @@ -3288,6 +3289,14 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, return exp; } +// Numbers with exponents greater or equal to the returned value will use +// the exponential notation. +template constexpr auto exp_upper() -> int { + return std::numeric_limits::digits10 != 0 + ? min_of(16, std::numeric_limits::digits10 + 1) + : 16; +} + template FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, locale_ref loc) -> OutputIt { @@ -3303,6 +3312,7 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, if (specs.width != 0) --specs.width; } + constexpr int exp_upper = detail::exp_upper(); int precision = specs.precision; if (precision < 0) { if (specs.type() != presentation_type::none) { @@ -3311,7 +3321,7 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, // Use Dragonbox for the shortest format. using floaty = conditional_t= sizeof(double), double, float>; auto dec = dragonbox::to_decimal(static_cast(value)); - return write_float(out, dec, specs, s, loc); + return write_float(out, dec, specs, s, exp_upper, loc); } } @@ -3339,7 +3349,7 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, specs.precision = precision; auto f = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; - return write_float(out, f, specs, s, loc); + return write_float(out, f, specs, s, exp_upper, loc); } template OutputIt { return write_nonfinite(out, std::isnan(value), specs, s); auto dec = dragonbox::to_decimal(static_cast(value)); - return write_float(out, dec, specs, s, {}); + return write_float(out, dec, specs, s, exp_upper(), {}); } template