* Support width and alignment in std::exception formatter
The formatter for std::exception (and std::exception_ptr) previously
accepted only the optional 't' type-name specifier, so standard fill,
align and width specifiers were rejected with "unknown format
specifier". This made it impossible to pad or align exception messages,
e.g. when laying them out in a log column.
Parse the standard fill/align/width specifiers (as the std::filesystem::
path formatter already does) and apply them when writing the message.
Dynamic width ({:{}}) and the 'none'/'unknown exception' cases for
exception_ptr are handled too. Existing behavior ({}, {:t}, nested
exception unwinding) is unchanged.
* Update std.h
fmt::format("{:a}", 0.0) produced 0x0p-1022 where printf's %a gives
0x0p+0, and likewise for -0.0, {:A}, {:#a} and any explicit precision.
basic_fp::assign maps a zero biased exponent to 1 ("subnormals use
biased exponent 1"), which is right for subnormals but not for zero, so
format_hexfloat inherited the minimum subnormal exponent for a value
whose significand carries no information. Reset the exponent there
rather than in assign, which the decimal path shares.
A zero significand can only come from +-0: normals get the implicit bit
added, and a subnormal has a nonzero significand by definition. So the
guard cannot affect anything else, and denorm_min keeps its existing
denormalized form (0x0.0000000000001p-1022, asserted in format_double).
The five new expectations were taken from printf rather than derived,
and all fail without this change.
A named argument that arrives const-qualified was not recognized by
is_named_arg, silently dropping its name. This happens both when a
named argument is passed through an intermediate function returning
const T& (https://github.com/fmtlib/fmt/issues/4866) and in fmt's own
compiled format path, which passes arguments as const T&.
Make is_named_arg and is_static_named_arg see through top-level const so
the name is preserved instead of dropped.
Make basic_ostream_formatter, ostream_formatter and streamed() accessible
to module users via FMT_BEGIN_EXPORT/FMT_BEGIN_EXPORT. Drop now unneeded
FMT_EXPORT for print() and println().
count_digits and do_format_decimal divided the full 128-bit value by a
constant in a loop. Compilers do not strength-reduce 128-bit division, so
each iteration became a slow __udivti3 library call (~27 per number).
Reduce the value to 64-bit chunks by dividing by 10^19 (at most twice) and
reuse the fast 64-bit paths, giving a ~5x speedup on full-range values.
Formatting an integer with ':c' used the magnitude (abs_value) and never
range-checked, so negatives were mangled and out-of-range values silently
truncated. Copy the value as a character and report an error when it is out
of range, treating all character types as unsigned for portability.
The appender and generic-iterator overloads only differed in whether the
integer formatting code was inlined. Merge them into a single overload and
select write_int_noinline vs inline write_int via if constexpr, keeping the
same codegen (out of line for appenders, inlined for compiled formatting)
with no size regression.
Detect when a std::exception also derives from std::nested_exception
(e.g. via std::throw_with_nested) and unwind the whole chain, joining
each level with ": ". The type-name flag ({:t}) is honored at every
level, and the std::exception_ptr formatter inherits this behavior.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use num_bits<UInt>() == 32 instead of sizeof(UInt) == 4 in
do_format_decimal. The magic-number two-digit algorithm requires
exactly 32 value bits, so this is more precise on platforms where
CHAR_BIT != 8 and is consistent with existing num_bits<T>() usage.
Revert the explicit-else workaround from #4822 and instead disable the
"unreachable code" warning for all of base.h. Add an FMT_PRAGMA_MSVC
helper (mirroring FMT_PRAGMA_GCC/CLANG) and wrap the header in a single
warning(push)/disable:4702/pop pair, keeping the original control flow.
if FMT_CONSTEXPR is resolved to constexpr MSC warns about dead code
after 'return' instruction. Explicitly using 'else' in these cases
avoids the warning.
Prevent false positives when the container itself does not have `operator[](size_t)`, but the target type of one of the non-explicit user-defined conversion functions does.
Just a tiny bugfix I spotted: The `f(un)lockfile` wrappers in
`format-inl.h` that wrap Windows's `_(un)lock_file` methods are
defined with a trailing return type derived by using decltype on a
hypothetical call to the underlying functions.
The wrappers don't contain a `return` in their bodies, however, so if
the return type of the underlying functions were to ever change from
`void`, there would be a compile error. This just adds `return` to each.