This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

4084. std::fixed ignores std::uppercase

Section: 28.3.4.3.3.3 [facet.num.put.virtuals] Status: WP Submitter: Jonathan Wakely Opened: 2024-04-30 Last modified: 2024-11-28

Priority: 3

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

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

View all issues with WP 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.

[Wrocław 2024-11-23; Status changed: Voting → WP.]

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