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

3644. std::format does not define "integer presentation type"

Section: 28.5.2.2 [format.string.std] Status: New Submitter: Charlie Barto Opened: 2021-11-23 Last modified: 2022-11-01

Priority: 2

View other active issues in [format.string.std].

View all other issues in [format.string.std].

View all issues with New status.

Discussion:

28.5.2.2 [format.string.std] specifies the behavior of several format specifiers in terms of "integer presentation types"; for example 28.5.2.2 [format.string.std]/4 states:

"The sign option is only valid for arithmetic types other than charT and bool or when an integer presentation type is specified".

Unfortunately nowhere does the standard actually define the term "integer presentation type". The closest it comes is in 28.5.2.2 [format.string.std]/19 and [tab:format.type.int], but that explicitly excludes charT and bool. [tab:format.type.char] and [tab:format.type.bool] then refer to [tab:format.type.int].

I can come up with many interpretations for what could happen when 'c' is used with charT or bool, but the following table is what msvc does right now (throws is the same as does not compile after P2216 in all these cases, although not in general for 'c'):

Argument type Specifiers Throws?
bool # Yes
bool #c No
bool :+ Yes
bool +c Yes
bool ^ No
bool ^c No
bool 0 Yes
bool 0c Yes
bool c No
charT # Yes
charT #c Yes
charT + Yes
charT +c Yes
charT ^ No
charT ^c No
charT 0 Yes
charT 0c Yes

As you can see we don't interpret 'c' as an "integer type specifier", except when explicitly specified for bool with #. I think this is because for # the standard states

"This option is valid for arithmetic types other than charT and bool or when an integer presentation type is specified, and not otherwise",

and [tab:format.type.bool] puts 'c' in the same category as all the other "integer type specifiers", whereas [tab:format.type.char] separates it out into the char-specific types. If this issue's proposed resolution is adopted our behavior would become non-conforming (arguably it already is) and "#c" with bools would become invalid.

[2021-11-29; Tim comments]

This issue touches the same wording area as LWG 3586(i) does.

[2022-01-30; Reflector poll]

Set priority to 2 after reflector poll.

[2021-11-29; Jonathan comments]

LWG 3648(i) removed 'c' as a valid presentation type for bool. The last change in the resolution below (and the drafting note) can be dropped.

LWG 3586(i) could be resolved as part of this issue by using "this is the default unless formatting a floating-point type or using an integer presentation type" for '<' and by using "this is the default when formatting a floating-point type or using an integer presentation type" for '>'.

Proposed resolution:

This wording is relative to N4901.

  1. Modify 28.5.2.2 [format.string.std] as indicated:

    -6- The # option causes the alternate form to be used for the conversion. This option is valid for arithmetic types other than charT and bool or when an integer presentation type is specified, and not otherwise. For integral types, the alternate form inserts the base prefix (if any) specified in Table 65 into the output after the sign character (possibly space) if there is one, or before the output of to_chars otherwise. For floating-point types, the alternate form causes the result of the conversion of finite values to always contain a decimal-point character, even if no digits follow it. Normally, a decimal-point character appears in the result of these conversions only if a digit follows it. In addition, for g and G conversions, trailing zeros are not removed from the result.

    […]

    [Drafting note: This modification is a simple cleanup given the other changes further below, to bring the wording for # in line with the wording for the other modifiers, in the interest of preventing confusion.]

    […]

    -16- The type determines how the data should be presented.