From 0fd541f291a5aea057f350db0b00072938c19c20 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 17 Jan 2024 07:15:50 -0800 Subject: [PATCH] Make format_specs not depend on code unit type --- include/fmt/base.h | 9 ++- include/fmt/chrono.h | 6 +- include/fmt/format-inl.h | 4 +- include/fmt/format.h | 141 +++++++++++++++++++-------------------- include/fmt/printf.h | 37 +++++----- include/fmt/std.h | 16 ++--- include/fmt/xchar.h | 3 +- test/format-test.cc | 4 +- test/scan.h | 16 ++--- 9 files changed, 115 insertions(+), 121 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index de86bed7fb0da..7d75a1bcd604a 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -2037,6 +2037,7 @@ using unsigned_char = typename conditional_t::value, std::make_unsigned, type_identity>::type; +// Character (code unit) type is erased to prevent template bloat. struct fill_t { private: enum { max_size = 4 }; @@ -2106,7 +2107,7 @@ enum class presentation_type : unsigned char { }; // Format specifiers for built-in and string types. -template struct format_specs { +struct format_specs { int width; int precision; presentation_type type; @@ -2160,8 +2161,7 @@ template struct arg_ref { // Format specifiers with width and precision resolved at formatting rather // than parsing time to allow reusing the same parsed specifiers with // different sets of arguments (precompilation of format strings). -template -struct dynamic_format_specs : format_specs { +template struct dynamic_format_specs : format_specs { arg_ref width_ref; arg_ref precision_ref; }; @@ -2636,8 +2636,7 @@ FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) } // Checks char specs and returns true iff the presentation type is char-like. -template -FMT_CONSTEXPR auto check_char_specs(const format_specs& specs) -> bool { +FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool { if (specs.type != presentation_type::none && specs.type != presentation_type::chr && specs.type != presentation_type::debug) { diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index d2552776ab275..f6e5e75563987 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1733,7 +1733,7 @@ auto format_duration_value(OutputIt out, Rep val, int) -> OutputIt { template ::value)> auto format_duration_value(OutputIt out, Rep val, int precision) -> OutputIt { - auto specs = format_specs(); + auto specs = format_specs(); specs.precision = precision; specs.type = precision >= 0 ? presentation_type::fixed : presentation_type::general; @@ -2076,7 +2076,7 @@ template struct formatter { template struct formatter, Char> { private: - format_specs specs_; + format_specs specs_; detail::arg_ref width_ref_; detail::arg_ref precision_ref_; bool localized_ = false; @@ -2218,7 +2218,7 @@ struct formatter, template struct formatter { private: - format_specs specs_; + format_specs specs_; detail::arg_ref width_ref_; protected: diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 05ea41ac513fe..e50ab4a23d28b 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -109,7 +109,7 @@ template FMT_FUNC Char decimal_point_impl(locale_ref) { #endif FMT_FUNC auto write_loc(appender out, loc_value value, - const format_specs<>& specs, locale_ref loc) -> bool { + const format_specs& specs, locale_ref loc) -> bool { #ifndef FMT_STATIC_THOUSANDS_SEPARATOR auto locale = loc.get(); // We cannot use the num_put facet because it may produce output in @@ -138,7 +138,7 @@ template format_facet::format_facet(Locale& loc) { template <> FMT_API FMT_FUNC auto format_facet::do_put( - appender out, loc_value val, const format_specs<>& specs) const -> bool { + appender out, loc_value val, const format_specs& specs) const -> bool { return val.visit( detail::loc_writer<>{out, specs, separator_, grouping_, decimal_point_}); } diff --git a/include/fmt/format.h b/include/fmt/format.h index 6388befb760a5..8a8f93e1f60a9 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -999,7 +999,8 @@ constexpr auto compile_string_to_view(basic_string_view s) } // namespace detail_exported // A generic formatting context with custom output iterator and character -// (code unit) support. +// (code unit) support. Char is the format string code unit type which can be +// different from OutputIt::value_type. template class generic_context { private: OutputIt out_; @@ -1068,7 +1069,7 @@ template class format_facet : public Locale::facet { protected: virtual auto do_put(appender out, loc_value val, - const format_specs<>& specs) const -> bool; + const format_specs& specs) const -> bool; public: static FMT_API typename Locale::id id; @@ -1081,7 +1082,7 @@ template class format_facet : public Locale::facet { grouping_(g.begin(), g.end()), decimal_point_(decimal_point) {} - auto put(appender out, loc_value val, const format_specs<>& specs) const + auto put(appender out, loc_value val, const format_specs& specs) const -> bool { return do_put(out, val, specs); } @@ -1727,7 +1728,7 @@ FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t& fill) // width: output display width in (terminal) column positions. template -FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, +FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, size_t size, size_t width, F&& f) -> OutputIt { static_assert(align == align::left || align == align::right, ""); unsigned spec_width = to_unsigned(specs.width); @@ -1746,14 +1747,14 @@ FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, template -constexpr auto write_padded(OutputIt out, const format_specs& specs, +constexpr auto write_padded(OutputIt out, const format_specs& specs, size_t size, F&& f) -> OutputIt { return write_padded(out, specs, size, size, f); } template FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, - const format_specs& specs) -> OutputIt { + const format_specs& specs = {}) -> OutputIt { return write_padded( out, specs, bytes.size(), [bytes](reserve_iterator it) { const char* data = bytes.data(); @@ -1762,7 +1763,7 @@ FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, } template -auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs) +auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs) -> OutputIt { int num_digits = count_digits<4>(value); auto size = to_unsigned(num_digits) + size_t(2); @@ -1926,7 +1927,7 @@ auto write_escaped_char(OutputIt out, Char v) -> OutputIt { template FMT_CONSTEXPR auto write_char(OutputIt out, Char value, - const format_specs& specs) -> OutputIt { + const format_specs& specs) -> OutputIt { bool is_debug = specs.type == presentation_type::debug; return write_padded(out, specs, 1, [=](reserve_iterator it) { if (is_debug) return write_escaped_char(it, value); @@ -1935,15 +1936,14 @@ FMT_CONSTEXPR auto write_char(OutputIt out, Char value, }); } template -FMT_CONSTEXPR auto write(OutputIt out, Char value, - const format_specs& specs, locale_ref loc = {}) - -> OutputIt { +FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs& specs, + locale_ref loc = {}) -> OutputIt { // char is formatted as unsigned char for consistency across platforms. using unsigned_type = conditional_t::value, unsigned char, unsigned>; return check_char_specs(specs) ? write_char(out, value, specs) - : write(out, static_cast(value), specs, loc); + : write(out, static_cast(value), specs, loc); } // Data for write_int that doesn't depend on output iterator type. It is used to @@ -1953,7 +1953,7 @@ template struct write_int_data { size_t padding; FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, - const format_specs& specs) + const format_specs& specs) : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { if (specs.align == align::numeric) { auto width = to_unsigned(specs.width); @@ -1975,7 +1975,7 @@ template struct write_int_data { template FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, unsigned prefix, - const format_specs& specs, + const format_specs& specs, W write_digits) -> OutputIt { // Slightly faster check for specs.width == 0 && specs.precision == -1. if ((specs.width | (specs.precision + 1)) == 0) { @@ -2068,8 +2068,8 @@ FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { // Writes a decimal integer with digit grouping. template auto write_int(OutputIt out, UInt value, unsigned prefix, - const format_specs& specs, - const digit_grouping& grouping) -> OutputIt { + const format_specs& specs, const digit_grouping& grouping) + -> OutputIt { static_assert(std::is_same, UInt>::value, ""); int num_digits = 0; auto buffer = memory_buffer(); @@ -2117,11 +2117,11 @@ auto write_int(OutputIt out, UInt value, unsigned prefix, } // Writes a localized value. -FMT_API auto write_loc(appender out, loc_value value, - const format_specs<>& specs, locale_ref loc) -> bool; -template -inline auto write_loc(OutputIt, loc_value, const format_specs&, - locale_ref) -> bool { +FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs, + locale_ref loc) -> bool; +template +inline auto write_loc(OutputIt, loc_value, const format_specs&, locale_ref) + -> bool { return false; } @@ -2148,7 +2148,7 @@ FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) template struct loc_writer { basic_appender out; - const format_specs& specs; + const format_specs& specs; std::basic_string sep; std::string grouping; std::basic_string decimal_point; @@ -2169,8 +2169,8 @@ template struct loc_writer { template FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg arg, - const format_specs& specs, - locale_ref) -> OutputIt { + const format_specs& specs, locale_ref) + -> OutputIt { static_assert(std::is_same>::value, ""); auto abs_value = arg.abs_value; auto prefix = arg.prefix; @@ -2221,18 +2221,19 @@ FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg arg, return out; } template -FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline( - OutputIt out, write_int_arg arg, const format_specs& specs, - locale_ref loc) -> OutputIt { +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, + write_int_arg arg, + const format_specs& specs, + locale_ref loc) -> OutputIt { return write_int(out, arg, specs, loc); } -template ::value && !std::is_same::value && - std::is_same>::value)> -FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, - const format_specs& specs, - locale_ref loc) -> OutputIt { + !std::is_same::value)> +FMT_CONSTEXPR FMT_INLINE auto write(basic_appender out, T value, + const format_specs& specs, locale_ref loc) + -> basic_appender { if (specs.localized && write_loc(out, value, specs, loc)) return out; return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs, loc); @@ -2241,10 +2242,11 @@ FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, template ::value && !std::is_same::value && + !std::is_same::value && !std::is_same>::value)> FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, - const format_specs& specs, - locale_ref loc) -> OutputIt { + const format_specs& specs, locale_ref loc) + -> OutputIt { if (specs.localized && write_loc(out, value, specs, loc)) return out; return write_int(out, make_write_int_arg(value, specs.sign), specs, loc); @@ -2292,7 +2294,7 @@ class counting_iterator { template FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, - const format_specs& specs) -> OutputIt { + const format_specs& specs) -> OutputIt { auto data = s.data(); auto size = s.size(); if (specs.precision >= 0 && to_unsigned(specs.precision) < size) @@ -2317,14 +2319,12 @@ FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, template FMT_CONSTEXPR auto write(OutputIt out, basic_string_view> s, - const format_specs& specs, locale_ref) - -> OutputIt { + const format_specs& specs, locale_ref) -> OutputIt { return write(out, s, specs); } template -FMT_CONSTEXPR auto write(OutputIt out, const Char* s, - const format_specs& specs, locale_ref) - -> OutputIt { +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, const format_specs& specs, + locale_ref) -> OutputIt { if (specs.type == presentation_type::pointer) return write_ptr(out, bit_cast(s), &specs); if (!s) report_error("string pointer is null"); @@ -2356,7 +2356,7 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { // DEPRECATED! template FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, - format_specs& specs) -> const Char* { + format_specs& specs) -> const Char* { FMT_ASSERT(begin != end, ""); auto align = align::none; auto p = begin + code_point_length(begin); @@ -2414,8 +2414,8 @@ struct float_specs { bool showpoint : 1; }; -template -FMT_CONSTEXPR auto parse_float_type_spec(const format_specs& specs) +// DEPRECATED! +FMT_CONSTEXPR inline auto parse_float_type_spec(const format_specs& specs) -> float_specs { auto result = float_specs(); result.showpoint = specs.alt; @@ -2451,7 +2451,7 @@ FMT_CONSTEXPR auto parse_float_type_spec(const format_specs& specs) template FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, - format_specs specs, + format_specs specs, const float_specs& fspecs) -> OutputIt { auto str = isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf"); @@ -2573,10 +2573,10 @@ FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, buffer.end(), out); } -template > FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, - const format_specs& specs, + const format_specs& specs, float_specs fspecs, locale_ref loc) -> OutputIt { auto significand = f.significand; @@ -2694,17 +2694,16 @@ template class fallback_digit_grouping { } }; -template +template FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, - const format_specs& specs, - float_specs fspecs, locale_ref loc) - -> OutputIt { + const format_specs& specs, float_specs fspecs, + locale_ref loc) -> OutputIt { if (is_constant_evaluated()) { - return do_write_float>(out, f, specs, fspecs, loc); } else { - return do_write_float(out, f, specs, fspecs, loc); + return do_write_float(out, f, specs, fspecs, loc); } } @@ -3561,9 +3560,8 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, return exp; } template -FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, - format_specs specs, locale_ref loc) - -> OutputIt { +FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, + locale_ref loc) -> OutputIt { float_specs fspecs = parse_float_type_spec(specs); fspecs.sign = specs.sign; if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. @@ -3574,7 +3572,7 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, } if (!detail::isfinite(value)) - return write_nonfinite(out, detail::isnan(value), specs, fspecs); + return write_nonfinite(out, detail::isnan(value), specs, fspecs); if (specs.align == align::numeric && fspecs.sign) { auto it = reserve(out, 1); @@ -3606,23 +3604,23 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, int exp = format_float(convert_float(value), precision, fspecs, buffer); fspecs.precision = precision; auto f = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; - return write_float(out, f, specs, fspecs, loc); + return write_float(out, f, specs, fspecs, loc); } template ::value)> -FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs, +FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs, locale_ref loc = {}) -> OutputIt { if (const_check(!is_supported_floating_point(value))) return out; return specs.localized && write_loc(out, value, specs, loc) ? out - : write_float(out, value, specs, loc); + : write_float(out, value, specs, loc); } template ::value)> FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { - if (is_constant_evaluated()) return write(out, value, format_specs()); + if (is_constant_evaluated()) return write(out, value, format_specs()); if (const_check(!is_supported_floating_point(value))) return out; auto fspecs = float_specs(); @@ -3631,26 +3629,26 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { value = -value; } - constexpr auto specs = format_specs(); + constexpr auto specs = format_specs(); using floaty = conditional_t::value, double, T>; using floaty_uint = typename dragonbox::float_info::carrier_uint; floaty_uint mask = exponent_mask(); if ((bit_cast(value) & mask) == mask) - return write_nonfinite(out, std::isnan(value), specs, fspecs); + return write_nonfinite(out, std::isnan(value), specs, fspecs); auto dec = dragonbox::to_decimal(static_cast(value)); - return write_float(out, dec, specs, fspecs, {}); + return write_float(out, dec, specs, fspecs, {}); } template ::value && !is_fast_float::value)> inline auto write(OutputIt out, T value) -> OutputIt { - return write(out, value, format_specs()); + return write(out, value, format_specs()); } template -auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) +auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) -> OutputIt { FMT_ASSERT(false, ""); return out; @@ -3684,9 +3682,8 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { template ::value)> -FMT_CONSTEXPR auto write(OutputIt out, T value, - const format_specs& specs = {}, locale_ref = {}) - -> OutputIt { +FMT_CONSTEXPR auto write(OutputIt out, T value, const format_specs& specs = {}, + locale_ref = {}) -> OutputIt { return specs.type != presentation_type::none && specs.type != presentation_type::string ? write(out, value ? 1 : 0, specs, {}) @@ -3709,7 +3706,7 @@ FMT_CONSTEXPR20 auto write(OutputIt out, const Char* value) -> OutputIt { template ::value)> -auto write(OutputIt out, const T* value, const format_specs& specs = {}, +auto write(OutputIt out, const T* value, const format_specs& specs = {}, locale_ref = {}) -> OutputIt { return write_ptr(out, bit_cast(value), &specs); } @@ -3764,7 +3761,7 @@ template struct arg_formatter { using context = buffered_context; iterator out; - const format_specs& specs; + const format_specs& specs; locale_ref locale; template @@ -4094,7 +4091,7 @@ template <> struct formatter { specs.width_ref, ctx); detail::handle_dynamic_spec( specs.precision, specs.precision_ref, ctx); - return detail::write_bytes(ctx.out(), b.data_, specs); + return detail::write_bytes(ctx.out(), b.data_, specs); } }; @@ -4184,7 +4181,7 @@ template struct nested_formatter { if (width_ == 0) return write(ctx.out()); auto buf = memory_buffer(); write(appender(buf)); - auto specs = format_specs<>(); + auto specs = format_specs(); specs.width = width_; specs.fill = fill_; specs.align = align_; diff --git a/include/fmt/printf.h b/include/fmt/printf.h index aca56ebb8ac9b..4f0fe9aeca2cc 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -191,12 +191,12 @@ template struct get_cstring { // Checks if an argument is a valid printf width specifier and sets // left alignment if it is negative. -template class printf_width_handler { +class printf_width_handler { private: - format_specs& specs_; + format_specs& specs_; public: - explicit printf_width_handler(format_specs& specs) : specs_(specs) {} + explicit printf_width_handler(format_specs& specs) : specs_(specs) {} template ::value)> auto operator()(T value) -> unsigned { @@ -220,7 +220,7 @@ template class printf_width_handler { // Workaround for a bug with the XL compiler when initializing // printf_arg_formatter's base class. template -auto make_arg_formatter(basic_appender iter, format_specs& s) +auto make_arg_formatter(basic_appender iter, format_specs& s) -> arg_formatter { return {iter, s, locale_ref()}; } @@ -237,11 +237,11 @@ class printf_arg_formatter : public arg_formatter { void write_null_pointer(bool is_string = false) { auto s = this->specs; s.type = presentation_type::none; - write_bytes(this->out, is_string ? "(null)" : "(nil)", s); + write_bytes(this->out, is_string ? "(null)" : "(nil)", s); } public: - printf_arg_formatter(basic_appender iter, format_specs& s, + printf_arg_formatter(basic_appender iter, format_specs& s, context_type& ctx) : base(make_arg_formatter(iter, s)), context_(ctx) {} @@ -255,19 +255,18 @@ class printf_arg_formatter : public arg_formatter { base::operator()(value); return; } - format_specs fmt_specs = this->specs; - if (fmt_specs.type != presentation_type::none && - fmt_specs.type != presentation_type::chr) { + format_specs s = this->specs; + if (s.type != presentation_type::none && s.type != presentation_type::chr) { return (*this)(static_cast(value)); } - fmt_specs.sign = sign::none; - fmt_specs.alt = false; - fmt_specs.fill = ' '; // Ignore '0' flag for char types. + s.sign = sign::none; + s.alt = false; + s.fill = ' '; // Ignore '0' flag for char types. // align::numeric needs to be overwritten here since the '0' flag is // ignored for non-numeric types - if (fmt_specs.align == align::none || fmt_specs.align == align::numeric) - fmt_specs.align = align::right; - write(this->out, static_cast(value), fmt_specs); + if (s.align == align::none || s.align == align::numeric) + s.align = align::right; + write(this->out, static_cast(value), s); } template ::value)> @@ -309,7 +308,7 @@ class printf_arg_formatter : public arg_formatter { }; template -void parse_flags(format_specs& specs, const Char*& it, const Char* end) { +void parse_flags(format_specs& specs, const Char*& it, const Char* end) { for (; it != end; ++it) { switch (*it) { case '-': @@ -334,7 +333,7 @@ void parse_flags(format_specs& specs, const Char*& it, const Char* end) { } template -auto parse_header(const Char*& it, const Char* end, format_specs& specs, +auto parse_header(const Char*& it, const Char* end, format_specs& specs, GetArg get_arg) -> int { int arg_index = -1; Char c = *it; @@ -365,7 +364,7 @@ auto parse_header(const Char*& it, const Char* end, format_specs& specs, } else if (*it == '*') { ++it; specs.width = static_cast( - get_arg(-1).visit(detail::printf_width_handler(specs))); + get_arg(-1).visit(detail::printf_width_handler(specs))); } } return arg_index; @@ -450,7 +449,7 @@ void vprintf(buffer& buf, basic_string_view format, } write(out, basic_string_view(start, to_unsigned(it - 1 - start))); - auto specs = format_specs(); + auto specs = format_specs(); specs.align = align::right; // Parse argument index, flags and width. diff --git a/include/fmt/std.h b/include/fmt/std.h index ff81da1ab9d48..fad32459a6505 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -117,7 +117,7 @@ void write_escaped_path(basic_memory_buffer& quoted, FMT_EXPORT template struct formatter { private: - format_specs specs_; + format_specs specs_; detail::arg_ref width_ref_; bool debug_ = false; char path_type_ = 0; @@ -372,7 +372,7 @@ template struct formatter { FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const -> decltype(ctx.out()) { auto out = ctx.out(); - out = detail::write_bytes(out, ec.category().name(), format_specs()); + out = detail::write_bytes(out, ec.category().name(), format_specs()); out = detail::write(out, Char(':')); out = detail::write(out, ec.value()); return out; @@ -403,10 +403,9 @@ struct formatter< template auto format(const std::exception& ex, Context& ctx) const -> decltype(ctx.out()) { - format_specs spec; auto out = ctx.out(); if (!with_typename_) - return detail::write_bytes(out, string_view(ex.what()), spec); + return detail::write_bytes(out, string_view(ex.what())); #if FMT_USE_TYPEID const std::type_info& ti = typeid(ex); @@ -448,20 +447,21 @@ struct formatter< } else { demangled_name_view = string_view(ti.name()); } - out = detail::write_bytes(out, demangled_name_view, spec); + out = detail::write_bytes(out, demangled_name_view); # elif FMT_MSC_VERSION string_view demangled_name_view(ti.name()); if (demangled_name_view.starts_with("class ")) demangled_name_view.remove_prefix(6); else if (demangled_name_view.starts_with("struct ")) demangled_name_view.remove_prefix(7); - out = detail::write_bytes(out, demangled_name_view, spec); + out = detail::write_bytes(out, demangled_name_view); # else - out = detail::write_bytes(out, string_view(ti.name()), spec); + out = detail::write_bytes(out, string_view(ti.name()) + }); # endif *out++ = ':'; *out++ = ' '; - return detail::write_bytes(out, string_view(ex.what()), spec); + return detail::write_bytes(out, string_view(ex.what())); #endif } }; diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index 57eab89001557..eed501c73cb0e 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -47,8 +47,7 @@ template using format_string_char_t = typename format_string_char::type; inline auto write_loc(basic_appender out, loc_value value, - const format_specs& specs, locale_ref loc) - -> bool { + const format_specs& specs, locale_ref loc) -> bool { #ifndef FMT_STATIC_THOUSANDS_SEPARATOR auto& numpunct = std::use_facet>(loc.get()); diff --git a/test/format-test.cc b/test/format-test.cc index f735ffd3a72dd..14121af4e0acd 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2188,11 +2188,11 @@ class format_facet : public fmt::format_facet { }; auto do_put(fmt::appender out, fmt::loc_value val, - const fmt::format_specs<>&) const -> bool override; + const fmt::format_specs&) const -> bool override; }; auto format_facet::do_put(fmt::appender out, fmt::loc_value val, - const fmt::format_specs<>&) const -> bool { + const fmt::format_specs&) const -> bool { return val.visit(int_formatter{out}); } diff --git a/test/scan.h b/test/scan.h index 67b5d5ba18ca4..43e6a13c632e0 100644 --- a/test/scan.h +++ b/test/scan.h @@ -434,7 +434,7 @@ class scan_context { namespace detail { const char* parse_scan_specs(const char* begin, const char* end, - format_specs<>& specs, scan_type) { + format_specs& specs, scan_type) { while (begin != end) { switch (to_ascii(*begin)) { // TODO: parse more scan format specifiers @@ -506,14 +506,14 @@ auto read_hex(scan_iterator it, T& value) -> scan_iterator { } template ::value)> -auto read(scan_iterator it, T& value, const format_specs<>& specs) +auto read(scan_iterator it, T& value, const format_specs& specs) -> scan_iterator { if (specs.type == presentation_type::hex) return read_hex(it, value); return read(it, value); } template ::value)> -auto read(scan_iterator it, T& value, const format_specs<>& specs = {}) +auto read(scan_iterator it, T& value, const format_specs& specs = {}) -> scan_iterator { bool negative = it != scan_sentinel() && *it == '-'; if (negative) { @@ -528,13 +528,13 @@ auto read(scan_iterator it, T& value, const format_specs<>& specs = {}) return it; } -auto read(scan_iterator it, std::string& value, const format_specs<>& = {}) +auto read(scan_iterator it, std::string& value, const format_specs& = {}) -> scan_iterator { while (it != scan_sentinel() && *it != ' ') value.push_back(*it++); return it; } -auto read(scan_iterator it, string_view& value, const format_specs<>& = {}) +auto read(scan_iterator it, string_view& value, const format_specs& = {}) -> scan_iterator { auto range = to_contiguous(it); // This could also be checked at compile time in scan. @@ -546,7 +546,7 @@ auto read(scan_iterator it, string_view& value, const format_specs<>& = {}) return advance(it, size); } -auto read(scan_iterator it, monostate, const format_specs<>& = {}) +auto read(scan_iterator it, monostate, const format_specs& = {}) -> scan_iterator { return it; } @@ -563,7 +563,7 @@ struct default_arg_scanner { // An argument scanner with format specifiers. struct arg_scanner { scan_iterator it; - const format_specs<>& specs; + const format_specs& specs; template auto operator()(T&& value) -> scan_iterator { return read(it, value, specs); @@ -617,7 +617,7 @@ struct scan_handler { scan_arg arg = scan_ctx_.arg(arg_id); if (arg.scan_custom(begin, parse_ctx_, scan_ctx_)) return parse_ctx_.begin(); - auto specs = format_specs<>(); + auto specs = format_specs(); begin = parse_scan_specs(begin, end, specs, arg.type()); if (begin == end || *begin != '}') on_error("missing '}' in format string"); scan_ctx_.advance_to(arg.visit(arg_scanner{scan_ctx_.begin(), specs}));