4084. std::fixed ignores std::uppercase

Section: 28.3.4.3.3.3 [facet.num.put.virtuals] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2024-04-30 Last modified: 2024-09-19

Priority: 3

View other active issues in [facet.num.put.virtuals].

View all other issues in [facet.num.put.virtuals].

View all issues with Tentatively Ready status.

Discussion:

In Table 114 – Floating-point conversions [tab:facet.num.put.fp] we specify that a floating-point value should be printed as if by %f when (flags & floatfield) == fixed. This ignores whether uppercase is also set in flags, meaning there is no way to use the conversion specifier %F that was added to printf in C99.

That's fine for finite values, because 1.23 in fixed format has no exponent character and no hex digits that would need to use uppercase. But %f and %F are not equivalent for non-finite values, because %F prints "NAN" and "INF" (or "INFINITY"). It seems there is no way to print "NAN" or "INF" using std::num_put.

Libstdc++ and MSVC print "inf" for the following code, but libc++ prints "INF" which I think is non-conforming:

    std::cout << std::uppercase << std::fixed << std::numeric_limits<double>::infinity();

The libc++ behaviour seems more useful and less surprising.

[2024-05-08; Reflector poll]

Set priority to 3 after reflector poll. Send to LEWG.

[2024-09-17; LEWG mailing list vote]

Set status to Open after LEWG approved the proposed change.

[2024-09-19; Reflector poll]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

Proposed resolution:

This wording is relative to N4981.

  1. Modify 28.3.4.3.3.3 [facet.num.put.virtuals] as indicated:

    Table 114 – Floating-point conversions [tab:facet.num.put.fp]
    State stdio equivalent
    floatfield == ios_base::fixed && !uppercase %f
    floatfield == ios_base::fixed %F
    floatfield == ios_base::scientific && !uppercase %e
    floatfield == ios_base::scientific %E
    floatfield == (ios_base::fixed | ios_base::scientific)` && !uppercase %a
    floatfield == (ios_base::fixed | ios_base::scientific) %A
    !uppercase %g
    otherwise %G