<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3644: std::format does not define "integer presentation type"</title>
<meta property="og:title" content="Issue 3644: std::format does not define &quot;integer presentation type&quot;">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3644.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#New">New</a> status.</em></p>
<h3 id="3644"><a href="lwg-active.html#3644">3644</a>. <code>std::format</code> does not define "integer presentation type"</h3>
<p><b>Section:</b> 28.5.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Charlie Barto <b>Opened:</b> 2021-11-23 <b>Last modified:</b> 2022-11-01</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#format.string.std">active issues</a> in [format.string.std].</p>
<p><b>View all other</b> <a href="lwg-index.html#format.string.std">issues</a> in [format.string.std].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
28.5.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a> specifies the behavior of several format specifiers in terms of 
"integer presentation types"; for example 28.5.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a>/4 states: 
</p>
<blockquote><p>
"The sign option is only valid for arithmetic types other than <code>charT</code> and <code>bool</code> or 
when an integer presentation type is specified". 
</p></blockquote>
<p>
Unfortunately nowhere does the standard actually define the term "integer presentation type". The 
closest it comes is in 28.5.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a>/19 and [tab:format.type.int], but that 
explicitly excludes <code>charT</code> and <code>bool</code>. [tab:format.type.char] and [tab:format.type.bool] 
then refer to [tab:format.type.int].
<p/> 
I can come up with many interpretations for what could happen when <code>'c'</code> is used with <code>charT</code> 
or <code>bool</code>, but the following table is what msvc does right now (throws is the same as does not 
compile after <a href="https://wg21.link/P2216" title=" std::format improvements">P2216</a> in all these cases, although not in general for <code>'c'</code>):
</p>
<blockquote>
<table border="1">
<tr style="text-align:center">
<th>Argument type</th>
<th>Specifiers</th>
<th>Throws?</th>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>#</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>#c</code></td>
<td>No</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>:+</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>+c</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>^</code></td>
<td>No</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>^c</code></td>
<td>No</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>0</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>0c</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>c</code></td>
<td>No</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>#</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>#c</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>+</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>+c</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>^</code></td>
<td>No</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>^c</code></td>
<td>No</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>0</code></td>
<td>Yes</td>
</tr>
<tr>
<td><code>charT</code></td>
<td><code>0c</code></td>
<td>Yes</td>
</tr>
</table>
</blockquote>
<p>
As you can see we don't interpret <code>'c'</code> as an "integer type specifier", except when <em>explicitly</em> 
specified for <code>bool</code> with <code>#</code>. I think this is because for <code>#</code> the standard states 
</p>
<blockquote><p>
"This option is valid for arithmetic types other than <code>charT</code> and <code>bool</code> or when an integer 
presentation type is specified, <em><u>and not otherwise</u></em>", 
</p></blockquote>
<p>
and [tab:format.type.bool] puts <code>'c'</code> 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 <code>"#c"</code> with <code>bool</code>s 
would become invalid.
</p>

<p><i>[2021-11-29; Tim comments]</i></p>

<p>
This issue touches the same wording area as LWG <a href="lwg-active.html#3586" title="Formatting character alignment inconsistencies (Status: New)">3586</a><sup><a href="https://cplusplus.github.io/LWG/issue3586" title="Latest snapshot">(i)</a></sup> does.
</p>

<p><i>[2022-01-30; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

<p><i>[2021-11-29; Jonathan comments]</i></p>

<p>
LWG <a href="lwg-defects.html#3648" title="format should not print bool with 'c' (Status: C++23)">3648</a><sup><a href="https://cplusplus.github.io/LWG/issue3648" title="Latest snapshot">(i)</a></sup> removed 'c' as a valid presentation type for <code>bool</code>.
The last change in the resolution below (and the drafting note) can be dropped.
</p>
<p>
LWG <a href="lwg-active.html#3586" title="Formatting character alignment inconsistencies (Status: New)">3586</a><sup><a href="https://cplusplus.github.io/LWG/issue3586" title="Latest snapshot">(i)</a></sup> 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 '&lt;' and by using
"this is the default when formatting a floating-point type or using
an integer presentation type" for '&gt;'.
</p>



<p id="res-3644"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4901" title=" Working Draft, Standard for Programming Language C++">N4901</a>.
</p>

<ol>

<li><p>Modify 28.5.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a> as indicated:</p>

<blockquote>
<p>
-6- The <code>#</code> option causes the <i>alternate</i> form to be used for the conversion. This option is <ins>only</ins> 
valid for arithmetic types other than <code>charT</code> and <code>bool</code> or when an integer presentation type 
is specified<del>, and not otherwise</del>. 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 <code>to_chars</code> 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 <code>g</code> and <code>G</code> conversions, trailing zeros are not removed from the result.
</p>
[&hellip;]
<blockquote class="note">
<p>
[<i>Drafting note:</i> This modification is a simple cleanup given the other changes further below, to bring the 
wording for <code>#</code> in line with the wording for the other modifiers, in the interest of preventing confusion.]
</p>
</blockquote>
[&hellip;]
<p>
-16- The <i>type</i> determines how the data should be presented.
<p/>
<ins>-?- An <i>integer presentation type</i> is one of the following type specifiers in Table 
[tab:format.type.integer_presentation], or none, if none is defined to have the same behavior 
as one of the type specifiers in Table [tab:format.type.integer_presentation].</ins>
</p>

<blockquote>
<table border="1">
<caption><ins>Table ? &mdash; Meaning of <i>type</i> options for integer representations [tab:format.type.integer_presentation]</ins></caption>
<tr style="text-align:center">
<th><ins>Type</ins></th>
<th><ins>Meaning</ins></th>
</tr>
<tr>
<td><ins><code>b</code></ins></td>
<td><ins><code>to_chars(first, last, value, 2);</code> the base prefix is <code>0b</code>.</ins></td>
</tr>
<tr>
<td><ins><code>B</code></ins></td>
<td><ins>The same as <code>b</code>, except that the base prefix is <code>0B</code>.</ins></td>
</tr>
<tr>
<td><ins><code>d</code></ins></td>
<td><ins><code>to_chars(first, last, value)</code>.</ins></td>
</tr>
<tr>
<td><ins><code>o</code></ins></td>
<td><ins><code>to_chars(first, last, value, 8)</code>; the base prefix is <code>0</code> if <code>value</code> is nonzero and is empty otherwise.</ins></td>
</tr>
<tr>
<td><ins><code>x</code></ins></td>
<td><ins><code>to_chars(first, last, value, 16)</code>; the base prefix is <code>0x</code>.</ins></td>
</tr>
<tr>
<td><ins><code>X</code></ins></td>
<td><ins>The same as <code>x</code>, except that it uses uppercase letters for digits above <code>9</code> and 
the base prefix is <code>0X</code>.</ins></td>
</tr>
</table>
</blockquote>

<blockquote class="note">
<p>
[<i>Drafting note:</i> This is the same as [tab:format.type.int] with "none" and <code>'c'</code> removed]
</p>
</blockquote>

<p>
-17- The available string presentation types are specified in Table 64 ([tab:format.type.string]).
</p>
[&hellip;]
<blockquote>
<table border="1">
<caption>Table 65 &mdash; Meaning of <i>type</i> options for integer types [tab:format.type.int]</caption>
<tr style="text-align:center">
<th>Type</th>
<th>Meaning</th>
</tr>
<tr>
<td><code>b</code><ins>, <code>B</code>, <code>d</code>, <code>o</code>, <code>x</code>, <code>X</code></ins></td>
<td><ins>As specified in Table [tab:format.type.integer_presentation]</ins><del><code>to_chars(first, last, value, 2);</code> the base prefix is <code>0b</code></del>.</td>
</tr>
<tr>
<td><del><code>B</code></del></td>
<td><del>The same as <code>b</code>, except that the base prefix is <code>0B</code>.</del></td>
</tr>
<tr>
<td><code>c</code></td>
<td>Copies the character <code>static_cast&lt;charT&gt;(value)</code> to the output. Throws <code>format_error</code> if <code>value</code> is not in the range of representable values for <code>charT</code>.</td>
</tr>
<tr>
<td><del><code>d</code></del></td>
<td><del><code>to_chars(first, last, value)</code>.</del></td>
</tr>
<tr>
<td><del><code>o</code></del></td>
<td><del><code>to_chars(first, last, value, 8)</code>; the base prefix is <code>0</code> if <code>value</code> is nonzero and is empty otherwise.</del></td>
</tr>
<tr>
<td><del><code>x</code></del></td>
<td><del><code>to_chars(first, last, value, 16)</code>; the base prefix is <code>0x</code>.</del></td>
</tr>
<tr>
<td><del><code>X</code></del></td>
<td><del>The same as <code>x</code>, except that it uses uppercase letters for digits above <code>9</code> and 
the base prefix is <code>0X</code>.</del></td>
</tr>
<tr>
<td>none</td>
<td>The same as <code>d</code>.
<del>[<i>Note 8</i>: If the formatting argument type is <code>charT</code> or <code>bool</code>, the default is instead <code>c</code> or <code>s</code>,
respectively. &mdash; <i>end note</i>]</del></td>
</tr>
</table>
</blockquote>
<blockquote>
<table border="1">
<caption>Table 66 &mdash; Meaning of <i>type</i> options for <code>charT</code> [tab:format.type.char]</caption>
<tr style="text-align:center">
<th>Type</th>
<th>Meaning</th>
</tr>
<tr>
<td>none, <code>c</code></td>
<td>Copies the character to the output.</td>
</tr>
<tr>
<td><code>b</code>, <code>B</code>, <code>d</code>, <code>o</code>, <code>x</code>, <code>X</code></td>
<td>As specified in Table <del>[tab:format.type.int]</del><ins>[tab:format.type.integer_presentation]</ins>.</td>
</tr>
</table>
</blockquote>
<blockquote>
<table border="1">
<caption>Table 67 &mdash; Meaning of <i>type</i> options for <code>bool</code> [tab:format.type.bool]</caption>
<tr style="text-align:center">
<th>Type</th>
<th>Meaning</th>
</tr>
<tr>
<td>none, <code>s</code></td>
<td>Copies textual representation, either <code>true</code> or <code>false</code>, to the output.</td>
</tr>
<tr>
<td><code>b</code>, <code>B</code>, <del><code>c</code>,</del> <code>d</code>, <code>o</code>, <code>x</code>, <code>X</code></td>
<td>As specified in Table <del>[tab:format.type.int]</del><ins>[tab:format.type.integer_presentation]</ins> for the value 
<code>static_cast&lt;unsigned char&gt;(value)</code>.</td>
</tr>
<tr>
<td><ins><code>c</code></ins></td>
<td><ins>Copies the character <code>static_cast&lt;unsigned char&gt;(value)</code> to the output.</ins></td>
</tr>
</table>
</blockquote>

<blockquote class="note">
<p>
[<i>Drafting note:</i> allowing the <code>'c'</code> specifier for <code>bool</code> is pretty bizarre behavior, 
but that's very clearly what the standard says now, so I'm preserving it. I would suggest keeping discussion 
of changing that behavior to a separate issue or defect report (the reworking of the tables in this issue makes 
addressing that easier anyway).
<p/>
The inconsistency with respect to using <code>static_cast&lt;unsigned char&gt;</code> here and 
<code>static_cast&lt;charT&gt;</code> in [tab:format.type.int] is pre-existing and should be addressed 
in a separate issue if needed.
]
</p>
</blockquote>

</blockquote>
</li>

</ol>





</body>
</html>
