<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2023-07-15" />
  <title>Formatter specializations for the standard library</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Formatter specializations
for the standard library</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2930R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-07-15</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Mark de Wever<br>&lt;<a href="mailto:koraq@xs4all.nl" class="email">koraq@xs4all.nl</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation<span></span></a></li>
<li><a href="#scope" id="toc-scope"><span class="toc-section-number">3</span> Scope<span></span></a>
<ul>
<li><a href="#atomic-values" id="toc-atomic-values"><span class="toc-section-number">3.1</span> Atomic
values<span></span></a></li>
<li><a href="#random-engines-and-distributions" id="toc-random-engines-and-distributions"><span class="toc-section-number">3.2</span> Random engines and
distributions<span></span></a></li>
<li><a href="#pointers-and-smart-pointers" id="toc-pointers-and-smart-pointers"><span class="toc-section-number">3.3</span> Pointers and smart
pointers<span></span></a></li>
<li><a href="#utility-types" id="toc-utility-types"><span class="toc-section-number">3.4</span> Utility
types<span></span></a></li>
<li><a href="#filesystempath" id="toc-filesystempath"><span class="toc-section-number">3.5</span>
<code class="sourceCode default">filesystem::path</code><span></span></a></li>
<li><a href="#mdspan" id="toc-mdspan"><span class="toc-section-number">3.6</span>
<code class="sourceCode default">mdspan</code><span></span></a></li>
<li><a href="#flat_map-and-flat_set" id="toc-flat_map-and-flat_set"><span class="toc-section-number">3.7</span>
<code class="sourceCode default">flat_map</code> and
<code class="sourceCode default">flat_set</code><span></span></a></li>
<li><a href="#diagnostics-library" id="toc-diagnostics-library"><span class="toc-section-number">3.8</span> Diagnostics
library<span></span></a></li>
<li><a href="#other-types" id="toc-other-types"><span class="toc-section-number">3.9</span> Other types<span></span></a></li>
<li><a href="#byte" id="toc-byte"><span class="toc-section-number">3.10</span> Byte<span></span></a></li>
<li><a href="#summary" id="toc-summary"><span class="toc-section-number">3.11</span> Summary<span></span></a></li>
</ul></li>
<li><a href="#design-decisions" id="toc-design-decisions"><span class="toc-section-number">4</span> Design decisions<span></span></a>
<ul>
<li><a href="#formats-impact-on-translation-unit-size" id="toc-formats-impact-on-translation-unit-size"><span class="toc-section-number">4.1</span> Format’s impact on translation
unit size<span></span></a></li>
<li><a href="#complex" id="toc-complex"><span class="toc-section-number">4.2</span>
<code class="sourceCode default">Complex</code><span></span></a></li>
<li><a href="#bitset" id="toc-bitset"><span class="toc-section-number">4.3</span>
<code class="sourceCode default">Bitset</code><span></span></a>
<ul>
<li><a href="#bitset-reference" id="toc-bitset-reference"><span class="toc-section-number">4.3.1</span>
<code class="sourceCode default">Bitset</code>
reference<span></span></a></li>
</ul></li>
<li><a href="#sub_match" id="toc-sub_match"><span class="toc-section-number">4.4</span>
<code class="sourceCode default">Sub_match</code><span></span></a></li>
<li><a href="#diagnostics" id="toc-diagnostics"><span class="toc-section-number">4.5</span> Diagnostics<span></span></a>
<ul>
<li><a href="#to-specialize-wchar_t-or-not-to-specialize-wchar_t" id="toc-to-specialize-wchar_t-or-not-to-specialize-wchar_t"><span class="toc-section-number">4.5.1</span> To specialize
<code class="sourceCode default">wchar_t</code> or not to specialize
<code class="sourceCode default">wchar_t</code><span></span></a></li>
<li><a href="#error_code" id="toc-error_code"><span class="toc-section-number">4.5.2</span>
<code class="sourceCode default">Error_code</code><span></span></a></li>
<li><a href="#error_condition" id="toc-error_condition"><span class="toc-section-number">4.5.3</span>
<code class="sourceCode default">Error_condition</code><span></span></a></li>
<li><a href="#error_category" id="toc-error_category"><span class="toc-section-number">4.5.4</span>
<code class="sourceCode default">Error_category</code><span></span></a></li>
</ul></li>
<li><a href="#byte-1" id="toc-byte-1"><span class="toc-section-number">4.6</span> Byte<span></span></a></li>
</ul></li>
<li><a href="#impact-on-the-standard" id="toc-impact-on-the-standard"><span class="toc-section-number">5</span> Impact on the
standard<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">6</span> Implementation
experience<span></span></a></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">7</span> Proposed wording<span></span></a>
<ul>
<li><a href="#feature-test-macro" id="toc-feature-test-macro"><span class="toc-section-number">7.1</span> Feature test
macro<span></span></a></li>
<li><a href="#formats-impact-on-translation-unit-size-1" id="toc-formats-impact-on-translation-unit-size-1"><span class="toc-section-number">7.2</span> Format’s impact on translation
unit size<span></span></a></li>
<li><a href="#formatter-complex" id="toc-formatter-complex"><span class="toc-section-number">7.3</span> Formatter
<code class="sourceCode default">complex</code><span></span></a></li>
<li><a href="#formatters-bitset-and-bitsetreference" id="toc-formatters-bitset-and-bitsetreference"><span class="toc-section-number">7.4</span> Formatters
<code class="sourceCode default">bitset</code> and
<code class="sourceCode default">bitset::reference</code><span></span></a></li>
<li><a href="#formatter-sub_match" id="toc-formatter-sub_match"><span class="toc-section-number">7.5</span> Formatter
<code class="sourceCode default">sub_match</code><span></span></a></li>
<li><a href="#header-system_error" id="toc-header-system_error"><span class="toc-section-number">7.6</span> Header
<code class="sourceCode default">system_error</code><span></span></a></li>
<li><a href="#byte-2" id="toc-byte-2"><span class="toc-section-number">7.7</span> Byte<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>C++20 introduced <code class="sourceCode default">std::format</code>
and in C++23 several improvements were made, for example <span class="citation" data-cites="P2286R8">[<a href="#ref-P2286R8" role="doc-biblioref">P2286R8</a>]</span> and <span class="citation" data-cites="P2693R1">[<a href="#ref-P2693R1" role="doc-biblioref">P2693R1</a>]</span>. Some types in the standard
library are formattable that do not have streaming support,
unfortunately the opposite is also true. Some types can be streamed, but
not formatted. This paper looks at the types that are not formattable
and proposes formatter support for some of these types. Other types will
be out of the scope of this paper, but are identified.</p>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>The addition of <code class="sourceCode default">std::format</code>
and <code class="sourceCode default">std::print</code> are a huge step
forward for formatting and printing objects in C++. Unfortunately, for
some types in the standard library, users still need to use the stream
operators to format the output. A part of these types have been
identified in <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>.
Unfortunately the author of the paper can no longer be reached. (The
author of this paper and others have, without success, reached out to
the author of <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>.) Parts of
the design of the paper are approved by LEWG, but never made it into the
standard.</p>
<p>This paper has a different approach for the formatter specializations
as <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>. That paper was based on the
state of <code class="sourceCode default">&lt;format&gt;</code> in
C++20. In C++23 <code class="sourceCode default">&lt;format&gt;</code>
gained a lot of new features giving better tools to define these
specializations.</p>
<h1 data-number="3" id="scope"><span class="header-section-number">3</span> Scope<a href="#scope" class="self-link"></a></h1>
<p>The proposal <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> has
identified some formatters that are missing. This proposal looks at more
types.</p>
<h2 data-number="3.1" id="atomic-values"><span class="header-section-number">3.1</span> Atomic values<a href="#atomic-values" class="self-link"></a></h2>
<p>These types are not streamable nor formattable. This paper does not
propose to add these types. Users can already format the values by do
this by using</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}&quot;</span>, atomic_value<span class="op">.</span>load<span class="op">())</span>;</span></code></pre></div>
<p>This allows to specify the memory ordering of
<code class="sourceCode default">load()</code>. Adding a formatter for
this type would need to have a way to specify the memory order too. This
adds extra complexity to the standard for little gain. The only benefit
from having it in the library would be that it’s possible to format a
<code class="sourceCode default">vector&lt;atomic&lt;T&gt;&gt;</code>
directly.</p>
<p>Users can already do this by using something like:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array input<span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>atomic<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;{</span><span class="dv">1</span><span class="op">}</span>,</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>atomic<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;{</span><span class="dv">2</span><span class="op">}</span>,</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>atomic<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;{</span><span class="dv">3</span><span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}&quot;</span>,</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    input <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span><span class="op">&amp;</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> i<span class="op">.</span>load<span class="op">()</span>; <span class="op">}))</span>;</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="3.2" id="random-engines-and-distributions"><span class="header-section-number">3.2</span> Random engines and
distributions<a href="#random-engines-and-distributions" class="self-link"></a></h2>
<p>These types are streamable to store and load their internal state.
This is a set of decimal numbers, so it could be formatted as a range of
integrals. However the intention is recreating a random engine or
distribution with a previous state. It’s not intended to display the
state. The author sees little benefit from making these types
formattable so the paper does not propose to make these types
formattable.</p>
<h2 data-number="3.3" id="pointers-and-smart-pointers"><span class="header-section-number">3.3</span> Pointers and smart pointers<a href="#pointers-and-smart-pointers" class="self-link"></a></h2>
<p>Currently only <code class="sourceCode default">void</code> pointers
and <code class="sourceCode default">nullptr</code>s can be formatted.
It might be useful to format other pointers and smart pointers as well.
<span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> proposed this, but LEWG
requested the smart pointers to be removed. Formatting pointers sounds
useful. However there are several design decision to be taken. The
author feels this would better be addressed in a separate paper.</p>
<h2 data-number="3.4" id="utility-types"><span class="header-section-number">3.4</span> Utility types<a href="#utility-types" class="self-link"></a></h2>
<p>There are several utility types:
<code class="sourceCode default">optional</code>,
<code class="sourceCode default">variant</code>,
<code class="sourceCode default">any</code>, and
<code class="sourceCode default">expected</code> that would be nice to
format. <span class="citation" data-cites="P2286R8">[<a href="#ref-P2286R8" role="doc-biblioref">P2286R8</a>]</span> introduced
formatting for <code class="sourceCode default">tuple</code> and
<code class="sourceCode default">pair</code>, but didn’t offer a way to
specify the formatting of the underlying types. Earlier versions of the
paper proposed a solution, but there were issues with that approach.
Later revisions removed this part of the proposal. These utility types
would have the same issue. The author feels it would be better to solve
this issue before adding more formatters with the same issue.</p>
<h2 data-number="3.5" id="filesystempath"><span class="header-section-number">3.5</span>
<code class="sourceCode default">filesystem::path</code><a href="#filesystempath" class="self-link"></a></h2>
<p>This was proposed in <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> and Victor
Zverovich recently proposed <span class="citation" data-cites="P2845R0">[<a href="#ref-P2845R0" role="doc-biblioref">P2845R0</a>]</span>.</p>
<h2 data-number="3.6" id="mdspan"><span class="header-section-number">3.6</span>
<code class="sourceCode default">mdspan</code><a href="#mdspan" class="self-link"></a></h2>
<p>This type has no formatting support. It would useful to be able to
format this type. However determining the best approach how to format
this type has several interesting non-trivial design choices. Especially
for <code class="sourceCode default">mdspan</code>s with more than two
dimensions. It seems better to do this in a dedicated paper. Adding a
formatter for <code class="sourceCode default">mdarray</code> (<span class="citation" data-cites="P1684R5">[<a href="#ref-P1684R5" role="doc-biblioref">P1684R5</a>]</span> not in the WP yet) has been
requested by LEWG. That formatter can be used for
<code class="sourceCode default">mdspan</code> too.</p>
<h2 data-number="3.7" id="flat_map-and-flat_set"><span class="header-section-number">3.7</span>
<code class="sourceCode default">flat_map</code> and
<code class="sourceCode default">flat_set</code><a href="#flat_map-and-flat_set" class="self-link"></a></h2>
<p>There is no need to do anything for these container adaptors. These
types are handled by <span class="citation" data-cites="P2585R0">[<a href="#ref-P2585R0" role="doc-biblioref">P2585R0</a>]</span> and are
formatted the same way are their “non-flat” equivalents.</p>
<h2 data-number="3.8" id="diagnostics-library"><span class="header-section-number">3.8</span> Diagnostics library<a href="#diagnostics-library" class="self-link"></a></h2>
<p>In the diagnostics library
<code class="sourceCode default">error_code</code> is streamable but not
formattable. The similar type
<code class="sourceCode default">error_condition</code> is neither
streamable nor formattable. The stream operator of
<code class="sourceCode default">error_code</code> uses the value of the
<code class="sourceCode default">error_category</code> which is not
streamable. <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> proposes
formatting of <code class="sourceCode default">error_code</code>.</p>
<p>It seems useful to make all these types formattable, especially the
difference between <code class="sourceCode default">error_code</code>
and <code class="sourceCode default">error_condition</code> looks odd.
The author has not been able to find the historic reason for this
discrepancy.</p>
<h2 data-number="3.9" id="other-types"><span class="header-section-number">3.9</span> Other types<a href="#other-types" class="self-link"></a></h2>
<p>There are some other types proposed in <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> which have not been
incorporated in the standard library:</p>
<ul>
<li><code class="sourceCode default">bitset</code></li>
<li><code class="sourceCode default">complex</code></li>
<li><code class="sourceCode default">sub_match</code></li>
</ul>
<p>LEWG was happy to add formatters for these types so this proposal
adds them too.</p>
<h2 data-number="3.10" id="byte"><span class="header-section-number">3.10</span> Byte<a href="#byte" class="self-link"></a></h2>
<p>There are no proposals to add this type. Before <span class="citation" data-cites="P2286R8">[<a href="#ref-P2286R8" role="doc-biblioref">P2286R8</a>]</span> a
<code class="sourceCode default">byte</code> formatter would only be be
able to format one element. After <span class="citation" data-cites="P2286R8">[<a href="#ref-P2286R8" role="doc-biblioref">P2286R8</a>]</span> it is possible to format ranges
of elements. Since <code class="sourceCode default">byte</code> is
intended to be used to give a byte-oriented access to a memory range
this seems very useful to format. This makes it easy to print data
received in buffers. For example for logging or debugging data
received.</p>
<h2 data-number="3.11" id="summary"><span class="header-section-number">3.11</span> Summary<a href="#summary" class="self-link"></a></h2>
<p>There are several standard library types that are interesting to be
formattable, that are not in the current standard. This paper proposes
formatters for the following types:</p>
<ul>
<li><code class="sourceCode default">bitset</code></li>
<li><code class="sourceCode default">byte</code></li>
<li><code class="sourceCode default">complex</code></li>
<li><code class="sourceCode default">error_category</code></li>
<li><code class="sourceCode default">error_code</code></li>
<li><code class="sourceCode default">error_condition</code></li>
<li><code class="sourceCode default">sub_match</code></li>
</ul>
<p>This paper does not propose formatters for the following types:</p>
<ul>
<li>(smart) pointers</li>
<li>utility types (<code class="sourceCode default">optional</code>,
<code class="sourceCode default">variant</code>,
<code class="sourceCode default">any</code>, and
<code class="sourceCode default">expected</code>)</li>
<li>filesystem path</li>
<li><code class="sourceCode default">mdspan</code> (and
<code class="sourceCode default">mdarray</code>)</li>
</ul>
<h1 data-number="4" id="design-decisions"><span class="header-section-number">4</span> Design decisions<a href="#design-decisions" class="self-link"></a></h1>
<p>The proposal <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> is quite
old, since that time the formatting library has improved and other
formatter specializations have been added. For example, the paper <span class="citation" data-cites="P2286R8">[<a href="#ref-P2286R8" role="doc-biblioref">P2286R8</a>]</span> solved some of the same
problems <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> solves for
<code class="sourceCode default">complex</code>. So it’s better to
follow the design already in the Standard instead of the original
design. This improves the consistency of the formatter
specializations.</p>
<p>From an implementers point of view some of the design choices are not
optimal. Forcing public inheriting from <code class="sourceCode default">formatter&lt;basic_string&lt;charT&gt;, charT&gt;</code>
is not always optimal. For example, when a
<code class="sourceCode default">sub_match</code> has a
<code class="sourceCode default">contigious_iterator</code> there is no
reason to copy the matched result into a
<code class="sourceCode default">basic_string</code>, using
<code class="sourceCode default">basic_string_view</code> would avoid
the copy. The paper <span class="citation" data-cites="P2693R1">[<a href="#ref-P2693R1" role="doc-biblioref">P2693R1</a>]</span> which
proposed a part of <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> went used a
different direction; only specifying what should happen without forcing
design choices on implementers. This paper will follow the same
approach; giving implementers the freedom to use the best option for
their implementation.</p>
<h2 data-number="4.1" id="formats-impact-on-translation-unit-size"><span class="header-section-number">4.1</span> Format’s impact on translation
unit size<a href="#formats-impact-on-translation-unit-size" class="self-link"></a></h2>
<p>Per <span>22.14.6.3
<a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a></span>/2</p>
<div class="bq">
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>  Each header that declares the template formatter provides the following</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  enabled specializations:</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  …</span></code></pre></div>
</div>
<p>This requires every header that specializes a formatter to make the
listed specializations available. This seemed fine when formatters were
used in a limited number of headers, however since its initial inception
formatters have been added to more headers in the standard library. This
proposal adds more formatter specializations, causing more headers to be
affected.</p>
<p>The libc++ standard library uses granularized headers to reduce the
size of translation units. This formatter requirement requires libc++ to
add extra includes in its implementation. Instead this paper proposes to
only require these specializations to be available when the header
<code class="sourceCode default">format</code> is included. This header
defines the format functions that use these specializations.</p>
<p>The size increase of headers due to the inclusion of format has an
impact on users. For example, one of the people working on Chromium
mentioned the following in a <a href="https://reviews.llvm.org/D149543#4455780">Phabricator</a>
review</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>In Chromium we noticed that this almost doubled the preprocessed size of</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>&lt;vector&gt;, from ca 1.6 MB to 3.2 MB. Since it&#39;s a widely included header, that</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>results in ca 8 GB (2.5%) of extra code to compile during a full build.</span></code></pre></div>
<p>This was due to implementing the
<code class="sourceCode default">vector&lt;bool&gt;::reference</code>
formatter specialization. This added several new includes to the vector
header in libc++, like
<code class="sourceCode default">&lt;string&gt;</code>,
<code class="sourceCode default">&lt;string_view&gt;</code>, and
<code class="sourceCode default">&lt;locale&gt;</code>.</p>
<p>Another motivation for this change is to avoid possible circular
dependencies in headers. For example the
<code class="sourceCode default">&lt;vector&gt;</code> header has a
formatter specialization. Using
<code class="sourceCode default">vector</code> in
<code class="sourceCode default">&lt;format&gt;</code> causes a circular
dependency. This circular dependency has caused an issue in libc++.</p>
<p>Note when using modules the inclusion size less relevant, but at the
moment of writing module support for the standard library is not wildly
available on all platforms.</p>
<p>Does LEWG want to address this or should this be an LWG issue
instead?</p>
<p>Does LEWG feel the translation unit size is something that should be
addressed by LEWG?</p>
<h2 data-number="4.2" id="complex"><span class="header-section-number">4.2</span>
<code class="sourceCode default">Complex</code><a href="#complex" class="self-link"></a></h2>
<p>Both <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> and <span class="citation" data-cites="P2197R0">[<a href="#ref-P2197R0" role="doc-biblioref">P2197R0</a>]</span> have proposed this feature
before. This implementation ideas align with <span class="citation" data-cites="P2197R0">[<a href="#ref-P2197R0" role="doc-biblioref">P2197R0</a>]</span>.</p>
<p>The output format has two options:</p>
<ul>
<li>A stream-like output that is similar to the output of
<code class="sourceCode default">operator&lt;&lt;</code>. This format
still allows changing the output format of the floating-point values
using the appropriate options of the <em>complex-format-spec</em>.</li>
<li>A range-like output that matches more with the format used in <span class="citation" data-cites="P2197R0">[<a href="#ref-P2197R0" role="doc-biblioref">P2197R0</a>]</span>.</li>
</ul>
<p>The output is based on the range based formatters and uses the
following <code class="sourceCode default">format-spec</code>:</p>
<blockquote>
<div class="line-block"><em>complex-format-spec</em>:<br />
    <em>range-fill-and-align</em><sub>opt</sub>
<em>width</em><sub>opt</sub> <em>n</em><sub>opt</sub>
<em>complex-type</em><sub>opt</sub>
<em>complex-underlying-spec</em><sub>opt</sub><br />
<em>complex-type</em>:<br />
     <code class="sourceCode default">S</code><br />
     <code class="sourceCode default">r</code><br />
<em>complex-underlying-spec</em>:<br />
      : <em>format-spec</em></div>
</blockquote>
<p>The <em>format-spec</em> of <em>complex-underlying-spec</em> is
applied to both the real and the imaginary part of the complex number.
This allows users to have control on how these values are formatted.
When the <em>complex-type</em> is
<code class="sourceCode default">r</code> there are some special
cases:</p>
<ul>
<li><p>Since the sign is the separator between the real and imaginary
part, the imaginary part should always have a sign. Otherwise it will be
hard to determine where the real part ends and the imaginary part
begins. Therefore the sign option for the imaginary defaults to
<code class="sourceCode default">+</code> and the option
<code class="sourceCode default">-</code> is ignored. This still allows
to use the <code class="sourceCode default">sign</code> option.</p></li>
<li><p>If the value is not infinity or NaN the value is suffixed with
“i”, otherwise the value is suffixed with ” i”. The differences is just
for readability purposes. The suffix is part of the formatted value and
counts to its width.</p></li>
</ul>
<p>The <em>complex-type</em> behaves like:</p>
<ul>
<li><code class="sourceCode default">S</code> uses the output format
similar to the <code class="sourceCode default">operator&lt;&lt;</code>
output.</li>
<li>The <em>complex-type</em> <code class="sourceCode default">r</code>
uses the range based output format.</li>
</ul>
<p>When no <em>complex-type</em> the range based output format is
used.</p>
<p>These letters are not used in the current <em>std-format-spec</em>
and alternative would be to use
<code class="sourceCode default">o</code> or
<code class="sourceCode default">s</code> for the stream-like output.
The option <code class="sourceCode default">S</code> will also be used
for the <code class="sourceCode default">error_condition</code>
formatter where <code class="sourceCode default">o</code> (octal) and
<code class="sourceCode default">s</code> (string) have a different
meaning. For consistency the proposal uses
<code class="sourceCode default">S</code> for all stream-like output
formats.</p>
<p>Some examples of the output for formatting
<code class="sourceCode default">complex</code> values</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Value</strong>
</div></th>
<th><div style="text-align:center">
<strong>Format</strong>
</div></th>
<th><div style="text-align:center">
<strong>Output</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>complex{0, 0}</td>
<td>{}</td>
<td>(0+0i)</td>
</tr>
<tr class="even">
<td>complex{3, 4}</td>
<td>{}</td>
<td>(3+4i)</td>
</tr>
<tr class="odd">
<td>complex{-3, 4}</td>
<td>{}</td>
<td>(-3+4i)</td>
</tr>
<tr class="even">
<td>complex{3, -4}</td>
<td>{}</td>
<td>(3-4i)</td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>complex{nan, nan}</td>
<td>{}</td>
<td>(nan+nan i)</td>
</tr>
<tr class="odd">
<td>complex{-nan, -nan}</td>
<td>{}</td>
<td>(nan-nan i)</td>
</tr>
<tr class="even">
<td>complex{inf, inf}</td>
<td>{}</td>
<td>(inf+inf i)</td>
</tr>
<tr class="odd">
<td>complex{-inf, -inf}</td>
<td>{}</td>
<td>(-inf-inf i)</td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>complex{0, 0}</td>
<td>{:r}</td>
<td>(0+0i)</td>
</tr>
<tr class="even">
<td>complex{0, 0}</td>
<td>{:nr}</td>
<td>0+0i</td>
</tr>
<tr class="odd">
<td>complex{0, 0}</td>
<td>{:S}</td>
<td>(0,0)</td>
</tr>
<tr class="even">
<td>complex{0, 0}</td>
<td>{:nS}</td>
<td>0,0</td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>complex{0, 0}</td>
<td>{::#}</td>
<td>(0.+0.i)</td>
</tr>
<tr class="odd">
<td>complex{1.345, 1.3}</td>
<td>{:#^18}</td>
<td>###(1.345+1.3i)###</td>
</tr>
<tr class="even">
<td>complex{1.345, 1.3}</td>
<td>{::08}</td>
<td>(0001.345+0001.3i)</td>
</tr>
<tr class="odd">
<td>complex{1.345, 1.3}</td>
<td>{::+08}</td>
<td>(+001.345+0001.3i)</td>
</tr>
<tr class="even">
<td>complex{1.345, 1.3}</td>
<td>{::E}</td>
<td>(1.345E+00+1.3E+00i)</td>
</tr>
<tr class="odd">
<td>complex{1.345, 1.3}</td>
<td>{::.6E}</td>
<td>(1.345000E+00+1.300000E+00i)</td>
</tr>
</tbody>
</table>
<p>There are some open questions:</p>
<ul>
<li>Should the <code class="sourceCode default">i</code> suffix be
considered as part of the width of the imaginary value? Currently it is,
it could also be considered not to be and instead part of the total
width of the output, which also happens for the brackets.</li>
<li>Are there items of the wish list of <span class="citation" data-cites="P2197R0">[<a href="#ref-P2197R0" role="doc-biblioref">P2197R0</a>]</span> that should be implemented? The
author feels we should not implement a different symbol for the
imaginary unit at this time. Currently it’s not possible to define the
brackets or separator for range based formatters in the
<em>format_spec</em>. The author has ideas how this can be done, but
feels this should be a separate paper.</li>
</ul>
<h2 data-number="4.3" id="bitset"><span class="header-section-number">4.3</span>
<code class="sourceCode default">Bitset</code><a href="#bitset" class="self-link"></a></h2>
<p>This type’s formatting deviates from <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>, the original proposal’s output
isn’t bad, but it’s very limited. Next to
<code class="sourceCode default">to_string</code> the
<code class="sourceCode default">bitset</code> the members
<code class="sourceCode default">to_ulong</code> and
<code class="sourceCode default">to_ullong</code>, which allow an
integral value. Another way to look at a
<code class="sourceCode default">bitset</code> is a range of bits.
Proposed are the following output formats:</p>
<ul>
<li><p>As a <code class="sourceCode default">string</code>. This uses
the <code class="sourceCode default">bitset</code>’s
<code class="sourceCode default">to_string()</code> member function. The
contents are a representatation of the value and not a specific string.
This means the output can’t be truncated with a precision option, nor
does it have the debug option.</p></li>
<li><p>As an <code class="sourceCode default">integral</code>. Since the
value is not a real arithmetic value the value is always considered to
be a positive value. Implemenenations can use the member functions
<code class="sourceCode default">to_ulong()</code> or
<code class="sourceCode default">to_ullong()</code> to extract the
value. Implementations are not allowed to throw
<code class="sourceCode default">overflow_error</code> when the value
fits in an <code class="sourceCode default">unsigned long long</code>.
The usage of <code class="sourceCode default">to_ulong()</code> is
intended to be allowed as optimization when it is known the value will
fit in an <code class="sourceCode default">unsigned long</code>, for
example when the using a
<code class="sourceCode default">bitset&lt;8&gt;</code>.</p>
<p>When the value does not fit in an
<code class="sourceCode default">unsigned long long</code>, it is
implementation defined whether an implementation throws
<code class="sourceCode default">overflow_error</code> or outputs the
correct value. Implementations are allowed to change this behaviour
depending on the display type. For example, throw an
<code class="sourceCode default">overflow_error</code> for the decimal
display type, but write values for the binary display type. The reason
for this choice is that writing the arbitrary long output for bases 2,
8, and 16 is easier to implement than for base 10. Since the value is a
set of bits, the base 10 value is likely less interesting. Note that the
<code class="sourceCode default">string</code> or range of
<code class="sourceCode default">bool</code> make is possible to always
get all bits, regardless of the number of bits in the
<code class="sourceCode default">bitset</code>. The provided
implementation has an example where a binary display type never
throws.</p></li>
<li><p>As a range of <code class="sourceCode default">bool</code>
values, where the underlying
<code class="sourceCode default">bool</code> can be configured like the
normal <code class="sourceCode default">bool</code> value.</p></li>
</ul>
<p>The formatter will use the following
<code class="sourceCode default">format-spec</code>:</p>
<blockquote>
<div class="line-block"><em>bitset-format-spec</em>:<br />
    <em>range-fill-and-align</em><sub>opt</sub> <em>#</em><sub>opt</sub>
<em>0</em><sub>opt</sub> <em>width</em><sub>opt</sub>
<em>L</em><sub>opt</sub> <em>n</em><sub>opt</sub>
<em>bitset-type</em><sub>opt</sub>
<em>bitset-underlying-spec</em><sub>opt</sub><br />
<em>bitset-type</em>: one of<br />
     <code class="sourceCode default">b</code>
<code class="sourceCode default">B</code>
<code class="sourceCode default">d</code>
<code class="sourceCode default">o</code>
<code class="sourceCode default">x</code>
<code class="sourceCode default">X</code>
<code class="sourceCode default">r</code>
<code class="sourceCode default">s</code><br />
<em>bitset-underlying-spec</em>:<br />
      : <em>format-spec</em></div>
</blockquote>
<p>Most fields match the behaviour of the <em>std-format-spec</em>
(<span>22.14.2.2
<a href="https://wg21.link/format.string.std">[format.string.std]</a></span>)
or the <em>range-format-spec</em> (<span>22.14.7.2
<a href="https://wg21.link/format.range.formatter">[format.range.formatter]</a></span>).</p>
<p>The <em>n</em> option is only valid when the <em>bitset-type</em>
option is <code class="sourceCode default">r</code>.</p>
<p>The <code class="sourceCode default">r</code> option of
<em>bitset-type</em> selects the range-based output. This implies the
underlying bits are outputted in the same way as the
<code class="sourceCode default">bool</code> formatter.</p>
<p>The <em>bitset-underlying-spec</em> is only valid when the output is
range-based.</p>
<p>The <em>format-spec</em> of the <em>bitset-underlying-spec</em>
matches the <em>std-format-spec</em> of the
<code class="sourceCode default">bool</code> type.</p>
<p>Some examples of the output for formatting
<code class="sourceCode default">bitset</code> values</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Value</strong>
</div></th>
<th><div style="text-align:center">
<strong>Format</strong>
</div></th>
<th><div style="text-align:center">
<strong>Output</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{}</td>
<td>0101</td>
</tr>
<tr class="even">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:s}</td>
<td>0101</td>
</tr>
<tr class="odd">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:b}</td>
<td>101</td>
</tr>
<tr class="even">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:#B}</td>
<td>0B101</td>
</tr>
<tr class="odd">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:r}</td>
<td>[false, true, false, true]</td>
</tr>
<tr class="even">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:r:b}</td>
<td>[0, 1, 0, 1]</td>
</tr>
<tr class="odd">
<td>bitset&lt;4&gt;{0x5}</td>
<td>{:nr:b}</td>
<td>0, 1, 0, 1</td>
</tr>
</tbody>
</table>
<h3 data-number="4.3.1" id="bitset-reference"><span class="header-section-number">4.3.1</span>
<code class="sourceCode default">Bitset</code> reference<a href="#bitset-reference" class="self-link"></a></h3>
<p>Like <code class="sourceCode default">vector&lt;bool&gt;</code> the
returned type of the non-<code class="sourceCode default">const</code>
member <code class="sourceCode default">operator[](size_t)</code> of a
<code class="sourceCode default">bitset</code> is a proxy. The formatter
for this proxy is modeled after the proxy of
<code class="sourceCode default">vector&lt;bool&gt;</code>.</p>
<p>(Note that the provided libc++ implementation tests for a
<code class="sourceCode default">bitset&lt;N&gt;::const_reference</code>-like
type too. This is due libc++ returning a non-conforming proxy from the
<code class="sourceCode default">const</code> member
<code class="sourceCode default">operator[](size_t)</code> in some ABI
versions. These tests also work on confirming implementations returning
a <code class="sourceCode default">bool</code>.)</p>
<p>The <em>format-spec</em> for this type is identical to the
<em>std-format-spec</em> of a boolean.</p>
<h2 data-number="4.4" id="sub_match"><span class="header-section-number">4.4</span>
<code class="sourceCode default">Sub_match</code><a href="#sub_match" class="self-link"></a></h2>
<p>This type’s formatting matches <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>, but the wording takes a
different approach. It’s likely
<code class="sourceCode default">sub_match</code> uses a
<code class="sourceCode default">contiguous_iterator</code>, forcing the
range to be copied to a <code class="sourceCode default">string</code>
and then copied to the output adds unneeded overhead. The wording gives
implementations options to pick other types. For example a
<code class="sourceCode default">basic_string_view</code> for a
<code class="sourceCode default">contiguous_iterator</code> and a
<code class="sourceCode default">basic_string</code> for a
non-<code class="sourceCode default">contiguous_iterator</code>.</p>
<p>The <em>format-spec</em> for this type is identical to the
<em>std-format-spec</em> of a string type.</p>
<h2 data-number="4.5" id="diagnostics"><span class="header-section-number">4.5</span> Diagnostics<a href="#diagnostics" class="self-link"></a></h2>
<h3 data-number="4.5.1" id="to-specialize-wchar_t-or-not-to-specialize-wchar_t"><span class="header-section-number">4.5.1</span> To specialize
<code class="sourceCode default">wchar_t</code> or not to specialize
<code class="sourceCode default">wchar_t</code><a href="#to-specialize-wchar_t-or-not-to-specialize-wchar_t" class="self-link"></a></h3>
<p>All these formatters may use
<code class="sourceCode default">error_category::name()</code>. This
function returns a <code class="sourceCode default">string</code> and
has no option to return a
<code class="sourceCode default">wstring</code>. The same holds true for
the <code class="sourceCode default">message</code> member function of
<code class="sourceCode default">error_code</code> and
<code class="sourceCode default">error_condition</code>.</p>
<p>A design consideration is whether or not to allow
<code class="sourceCode default">wchar_t</code> formatter
specializations for the diagnostics. In <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span> the formatter specialization
had the following effect:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>  basic_ostringstream<span class="op">&lt;</span>charT<span class="op">&gt;</span> o;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  o<span class="op">.</span>imbue<span class="op">(</span>locale<span class="op">::</span>classic<span class="op">())</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  o <span class="op">&lt;&lt;</span> ec;</span></code></pre></div>
<p>If <code class="sourceCode default">charT</code> is a
<code class="sourceCode default">wchar_t</code> it widens the
<code class="sourceCode default">char</code> input to
<code class="sourceCode default">wchar_t</code>.</p>
<p>The formatter specialization for
<code class="sourceCode default">stacktrace_entry</code> in <span class="citation" data-cites="P2693R1">[<a href="#ref-P2693R1" role="doc-biblioref">P2693R1</a>]</span> took a different design
approach, it doesn’t support
<code class="sourceCode default">wchar_t</code>. At the moment Zach
Laine is working on improving Unicode support in C++. The paper <span class="citation" data-cites="P2728R3">[<a href="#ref-P2728R3" role="doc-biblioref">P2728R3</a>]</span> specifies a
<code class="sourceCode default">utf_view</code> specialization</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>  These should be added to the list of “the debug-enabled string type</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  specializations” in [format.formatter.spec]. This allows utf_view to</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  be used in std::format() and std::print(). The intention is that the</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  formatter will transcode to UTF-8 if the formatter’s charT is char, or</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  to UTF-16 if the formatter’s charT is wchar_t – if transcoding is</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  necessary at all.</span></code></pre></div>
<p>Here the conversion from <code class="sourceCode default">char</code>
to <code class="sourceCode default">wchar_t</code> will be done using
Unicode transcoding. For consistency, there should only be one way of
transcoding in the format library. (There is already some transcoding in
the library with <em>STATICALLY-WIDEN</em>, which is done by the
compiler.) The C++26 cycle has just started. The author prefers to
disallow <code class="sourceCode default">wchar_t</code> specializations
for now. Once <span class="citation" data-cites="P2728R3">[<a href="#ref-P2728R3" role="doc-biblioref">P2728R3</a>]</span> is approved
the author can write a small paper adding
<code class="sourceCode default">wchar_t</code> support using Unicode
transcoding.</p>
<h3 data-number="4.5.2" id="error_code"><span class="header-section-number">4.5.2</span>
<code class="sourceCode default">Error_code</code><a href="#error_code" class="self-link"></a></h3>
<p>This type’s formatting deviates from <span class="citation" data-cites="P1636R2">[<a href="#ref-P1636R2" role="doc-biblioref">P1636R2</a>]</span>. The original proposal’s output
feels limited. It’s based on the output of
<code class="sourceCode default">operator&lt;&lt;</code>. Customizing
the output of <code class="sourceCode default">operator&lt;&lt;</code>
for “custom” types is non-trivial, but formatters don’t have this
limitation. Instead of limiting the output of the formatter, let’s
embrace it. Some of the limitations are that it’s not possible to write
the error’s message which may contain useful information.</p>
<p>It could be argued that the decimal output may not be portable across
platforms. For example EOVERFLOW has the value
<code class="sourceCode default">75</code> on Linux and
<code class="sourceCode default">132</code> on Windows. However this
value is currently already used in
<code class="sourceCode default">operator&lt;&lt;</code>, so this
proposal follows the direction in this regard.</p>
<p>The formatter will use the following
<code class="sourceCode default">format-spec</code>:</p>
<blockquote>
<div class="line-block"><em>error-code-format-spec</em>:<br />
    <em>fill-and-align</em><sub>opt</sub> <em>#</em><sub>opt</sub>
<em>0</em><sub>opt</sub> <em>width</em><sub>opt</sub>
<em>L</em><sub>opt</sub> <em>error-code-type</em><sub>opt</sub><br />
<em>error-code-type</em>:<br />
    <em>error-code-type-value</em><br />
    <em>error-code-type-message</em><br />
    <em>error-code-type-ostream</em><br />
<em>error-code-type-value</em>: one of<br />
     <code class="sourceCode default">b</code>
<code class="sourceCode default">B</code>
<code class="sourceCode default">d</code>
<code class="sourceCode default">o</code>
<code class="sourceCode default">x</code>
<code class="sourceCode default">X</code><br />
<em>error-code-type-message</em>:<br />
     <code class="sourceCode default">s</code><br />
<em>error-code-type-ostream</em>:<br />
     <code class="sourceCode default">S</code></div>
</blockquote>
<p>Most fields match the behaviour of the <em>std-format-spec</em>
(<span>22.14.2.2
<a href="https://wg21.link/format.string.std">[format.string.std]</a></span>).</p>
<p>When <em>error-code-type</em> is a <em>error-code-type-value</em> the
value is formatted as an <code class="sourceCode default">int</code>
obtained by calling the <code class="sourceCode default">value()</code>
member function.</p>
<p>When <em>error-code-type</em> is a <em>error-code-type-message</em>
the value is formatted as a
<code class="sourceCode default">string</code> obtained by calling the
<code class="sourceCode default">message()</code> member function.</p>
<p>When <em>error-code-type</em> is a <em>error-code-type-ostream</em>
the value is formatted is the same way the output of
<code class="sourceCode default">operator&lt;&lt;</code>. When this
display type is used only the <em>fill-and-align</em> and <em>width</em>
option may be present.</p>
<p>When the <em>error-code-type</em> is omitted it is formatted as-if
the <em>error-code-type-ostream</em> has been specified.</p>
<p>Formatting the <code class="sourceCode default">make_error_code(errc::value_too_large);</code>
may give the following results:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Format</strong>
</div></th>
<th><div style="text-align:center">
<strong>Output</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>{}</td>
<td>Value too large for defined data type</td>
</tr>
<tr class="even">
<td>{:s}</td>
<td>Value too large for defined data type</td>
</tr>
<tr class="odd">
<td>{:d}</td>
<td>75</td>
</tr>
<tr class="even">
<td>{:S}</td>
<td>generic:75</td>
</tr>
</tbody>
</table>
<h3 data-number="4.5.3" id="error_condition"><span class="header-section-number">4.5.3</span>
<code class="sourceCode default">Error_condition</code><a href="#error_condition" class="self-link"></a></h3>
<p>This type is similar to
<code class="sourceCode default">error_code</code>, but it has no
<code class="sourceCode default">operator&lt;&lt;</code>. It’s unclear
to the author what the historic reason for the difference is. This
proposal proposes to add an
<code class="sourceCode default">error_condition</code> formatter. This
formatter behaves the same as the
<code class="sourceCode default">error_code</code> formatter.</p>
<h3 data-number="4.5.4" id="error_category"><span class="header-section-number">4.5.4</span>
<code class="sourceCode default">Error_category</code><a href="#error_category" class="self-link"></a></h3>
<p>This formatter behaves the same as a formatter for a string type
taking its value from the <code class="sourceCode default">name()</code>
member function. Since these messages typical are short and truncating
them may loose information the formatter specialization will not allow
the precision option that is available for string types.</p>
<p>Formatting the
<code class="sourceCode default">generic_category();</code> gives the
following results:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Format</strong>
</div></th>
<th><div style="text-align:center">
<strong>Output</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>{}</td>
<td>generic</td>
</tr>
<tr class="even">
<td>{:s}</td>
<td>generic</td>
</tr>
<tr class="odd">
<td>{:.42}</td>
<td>// ill-formed, precision not allowed</td>
</tr>
</tbody>
</table>
<h2 data-number="4.6" id="byte-1"><span class="header-section-number">4.6</span> Byte<a href="#byte-1" class="self-link"></a></h2>
<p>There are no previous proposals for this type. The type is intended
to be used as a memory buffer containing bytes. With the presence of
range-based formatting it seems useful to be able to format this memory
buffer.</p>
<p>This type is defined in
<code class="sourceCode default">cstddef</code>. It feels wrong to add a
<code class="sourceCode default">formatter</code> to a c header. Instead
this formatter specialization will be available in the
<code class="sourceCode default">&lt;format&gt;</code> header.</p>
<p>Since the type is small it makes sense to directly store the byte in
the <code class="sourceCode default">basic_format_arg</code> exposition
only value variant. However this change may be problematic for
implementers due to following requirement</p>
<p><span>22.14.8.3
<a href="https://wg21.link/format.args">[format.args]</a></span>/1</p>
<div class="bq">
<div class="sourceCode" id="cb7"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>  An instance of basic_format_args provides access to formatting arguments.</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  Implementations should optimize the representation of basic_format_args for a</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  small number of formatting arguments.</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  [Note 1: For example, by storing indices of type alternatives separately</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  from values and packing the former. — end note]</span></code></pre></div>
</div>
<p>Implementations have different methods for packing their types. Two
of the implementations have added additional types to this
“<code class="sourceCode default">variant</code>”:</p>
<ul>
<li>libc++ 128 bit integral types</li>
<li>libstdc++ 128 bit integral types and extended floating-point
types</li>
<li>MSVC STL has no extensions</li>
</ul>
<p>Instead of requiring implementers to add it to the variant it is
unspecified whether the value is stored directly in the handle or in the
variant. This difference is observable when users call
<code class="sourceCode default">visit_format_arg</code>. Searching for
this string on GitHub only finds usage of this function in {fmt}, LLVM,
GCC, MSVC STL and the LWG issue repositories (or forks of them). So the
function unlikely to be used in the wild. (Note <span class="citation" data-cites="P2637R2">[<a href="#ref-P2637R2" role="doc-biblioref">P2637R2</a>]</span> deprecated this function and
added a <code class="sourceCode default">visit&lt;R&gt;</code> member
function to <code class="sourceCode default">basic_format_arg</code> as
its replacement.)</p>
<p>Not specifying this means it’s unspecified whether the
<code class="sourceCode default">visit</code> functions can use this
value Requiring it to be always visitibale basically requires storing in
the value in the “<code class="sourceCode default">variant</code>”.</p>
<p>The formatter itself behaves like the formatter for
<code class="sourceCode default">int</code> except that it does not
allow the character display type. When formatting a
<code class="sourceCode default">byte</code> as a
<code class="sourceCode default">char</code> half of the values can not
be represented in a <code class="sourceCode default">char</code> if
<code class="sourceCode default">char</code> has a
<code class="sourceCode default">signed char</code> as underlying type.
For <code class="sourceCode default">wchar_t</code> all values can be
represented. When a value can’t be represented as a
<code class="sourceCode default">char</code> the formatter has to throw
an exception (<a href="https://wg21.link/tab:format.type.int">[tab:format.type.int]</a>).
So instead of adding a possible unusable format option, don’t add it at
all. If users want to output a range of
<code class="sourceCode default">byte</code>s as
<code class="sourceCode default">char</code>s they have the option to
use a <code class="sourceCode default">std::views::transform</code> and
convert the <code class="sourceCode default">byte</code> to a
<code class="sourceCode default">char</code> and then the
<code class="sourceCode default">char</code> formatter will be used.</p>
<p>Since the type is always unsigned it might be worth considering to
disallow a <em>sign</em> option. However the sign option can be used for
unsigned integrals. Therefore the sign is allowed here too.</p>
<p>Some examples of the output for formatting
<code class="sourceCode default">byte</code> values</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Value</strong>
</div></th>
<th></th>
<th><div style="text-align:center">
<strong>Format</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>byte{0}</td>
<td>{}</td>
<td>0</td>
</tr>
<tr class="even">
<td>byte{42}</td>
<td>{:x}</td>
<td>2a</td>
</tr>
<tr class="odd">
<td>byte{255}</td>
<td>{:#X}</td>
<td>0X2A</td>
</tr>
<tr class="even">
<td>byte{2}</td>
<td>{:b}</td>
<td>10</td>
</tr>
<tr class="odd">
<td>byte{2}</td>
<td>{:c}</td>
<td>// ill-formed, char output not allowed</td>
</tr>
</tbody>
</table>
<h1 data-number="5" id="impact-on-the-standard"><span class="header-section-number">5</span> Impact on the standard<a href="#impact-on-the-standard" class="self-link"></a></h1>
<p>The proposal is a library only extension.</p>
<h1 data-number="6" id="implementation-experience"><span class="header-section-number">6</span> Implementation experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>A libc++ <a href="https://github.com/mordante/llvm-project/tree/formatting_library">reference
implementation</a> is available. The formatter
<code class="sourceCode default">byte</code> has not been implemented.
The author would like to get approval for the design direction before
writing this formatter.</p>
<h1 data-number="7" id="proposed-wording"><span class="header-section-number">7</span> Proposed wording<a href="#proposed-wording" class="self-link"></a></h1>
<p>The wording is not entirely complete and needs polishing before LWG
starts reviewing. For the same reason as the implementation, the
formatter <code class="sourceCode default">byte</code> has not wording.
The wording is based on <span class="citation" data-cites="N4944">[<a href="#ref-N4944" role="doc-biblioref">N4944</a>]</span>.</p>
<h2 data-number="7.1" id="feature-test-macro"><span class="header-section-number">7.1</span> Feature test macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>Update the macro
<code class="sourceCode default">__cpp_lib_formatters</code> to the date
of adoption and make it available in the following additional headers
<code class="sourceCode default">&lt;bitset&gt;</code>,
<code class="sourceCode default">&lt;complex&gt;</code>,
<code class="sourceCode default">&lt;regex&gt;</code>,
<code class="sourceCode default">&lt;system_error&gt;</code>,
<code class="sourceCode default">&lt;format&gt;</code>.</p>
<h2 data-number="7.2" id="formats-impact-on-translation-unit-size-1"><span class="header-section-number">7.2</span> Format’s impact on translation
unit size<a href="#formats-impact-on-translation-unit-size-1" class="self-link"></a></h2>
<p><span>22.14.6.3
<a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a></span>/2</p>
<div class="bq">
<div>
<div class="sourceCode" id="cb8"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="st">- Each header that declares the template formatter provides the following enabled specializations:</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ This header provides the following enabled specializations:</span></span></code></pre></div>
</div>
</div>
<h2 data-number="7.3" id="formatter-complex"><span class="header-section-number">7.3</span> Formatter
<code class="sourceCode default">complex</code><a href="#formatter-complex" class="self-link"></a></h2>
<p>Add to <span>28.4.2
<a href="https://wg21.link/complex.syn">[complex.syn]</a></span></p>
<div class="bq">
<div>
<div class="sourceCode" id="cb9"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>   template&lt;class T&gt; complex&lt;T&gt; tan  (const complex&lt;T&gt;&amp;);</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>   template&lt;class T&gt; complex&lt;T&gt; tanh (const complex&lt;T&gt;&amp;);</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="va">+  // [complex.format], complex formatting</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;class T, class charT&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="va">+  struct formatter&lt;complex&lt;T&gt;, charT&gt;;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>   // [complex.literals], complex literals</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>   inline namespace literals {</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>   inline namespace complex_literals {</span></code></pre></div>
</div>
</div>
<p>Add a new section 26.4.? Formatting [complex.format]:</p>
<div class="bq">
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb10"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>namespace std {</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  template&lt;class T, class charT&gt;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  class formatter&lt;complex&lt;T&gt;, charT {</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    formatter&lt;T, charT&gt; underlying_;                                          // exposition only</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; separator_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;&quot;);        // exposition only</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; opening-bracket_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;(&quot;); // exposition only</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; closing-bracket_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;)&quot;); // exposition only</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>  public:</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    constexpr void set_separator(basic_string_view&lt;charT&gt; sep) noexcept;</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    constexpr void set_brackets(basic_string_view&lt;charT&gt; opening,</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>                                basic_string_view&lt;charT&gt; closing) noexcept;</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    template&lt;class ParseContext&gt;</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>      constexpr typename ParseContext::iterator</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>        parse(ParseContext&amp; ctx);</span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    template&lt;class FormatContext&gt;</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>      typename FormatContext::iterator</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>        format(complex&lt;T&gt; value, FormatContext&amp; ctx) const;</span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">template&lt;class T, class charT&gt; class formatter&lt;complex&lt;T&gt;, charT&gt;;</code></p>
<p><code class="sourceCode default">formatter&lt;complex&lt;T&gt;, charT&gt;</code>
interprets <em>format-spec</em> as a <em>complex-format-spec</em>. The
syntax of format specifications is as follows:</p>
<blockquote>
<div class="line-block"><em>complex-format-spec</em>:<br />
    <em>range-fill-and-align</em><sub>opt</sub>
<em>width</em><sub>opt</sub> <em>n</em><sub>opt</sub>
<em>complex-type</em><sub>opt</sub>
<em>complex-underlying-spec</em><sub>opt</sub><br />
<em>complex-type</em>:<br />
     <code class="sourceCode default">S</code><br />
     <code class="sourceCode default">r</code><br />
<em>complex-underlying-spec</em>:<br />
      : <em>format-spec</em></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>range-fill-and-align</em> is interpreted the same way as a described
in <span>22.14.7.2
<a href="https://wg21.link/format.range.formatter">[format.range.formatter]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>width</em> is interpreted the same way as a described in
<span>22.14.2
<a href="https://wg21.link/format.string">[format.string]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>n</em> is interpreted the same way as a described in <span>22.14.7.2
<a href="https://wg21.link/format.range.formatter">[format.range.formatter]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
the <em>complex-type</em> specifier changes the way a complex is
formatted, with certain options only valid with certain argument types.
The meaning of the various type options is as specified in Table xx.</p>
<p>Table xx: Meaning of complex-type
options [tab:complex.format.type]</p>
<table>
<colgroup>
<col style="width: 11%" />
<col style="width: 88%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Option</strong>
</div></th>
<th><div style="text-align:center">
<strong>Meaning</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode default">S</code></td>
<td>The output is compatible with the ostream output. Indicates the
separator should be STATICALLY-WIDEN(“,”).</td>
</tr>
<tr class="even">
<td><code class="sourceCode default">r</code></td>
<td>The output is a range of the real and imaginary part.</td>
</tr>
<tr class="odd">
<td>none</td>
<td>The same as <code class="sourceCode default">r</code>.</td>
</tr>
</tbody>
</table>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The <em>format-spec</em> in a <em>complex-underlying-spec</em>, if any,
is interpreted as the <em>std-format-spec</em> for a floating-point type
as described in <span>22.14.2
<a href="https://wg21.link/format.string">[format.string]</a></span>.</p>
<p><code class="sourceCode default">constexpr void set_separator(basic_string_view&lt;charT&gt; sep) noexcept;</code></p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Effects</em>: Equivalent to:
<code class="sourceCode default">separator_ = sep;</code></p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>constexpr void set_brackets(basic_string_view&lt;charT&gt; opening,</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>                            basic_string_view&lt;charT&gt; closing) noexcept;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>  opening-bracket_ = opening;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  closing-bracket_ = closing;</span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>template&lt;class ParseContext&gt;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  constexpr typename ParseContext::iterator</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    parse(ParseContext&amp; ctx);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Effects</em>: Parses the format specifier as a
<em>complex-format-spec</em> and stores the parsed specifiers in
<code class="sourceCode default">*this</code>. The values of
<code class="sourceCode default">opening-bracket_</code>,
<code class="sourceCode default">closing-bracket_</code>, and
<code class="sourceCode default">separator_</code> are modified if and
only if required by the <em>complex-type</em> or the <em>n</em> option,
if present. The function
<code class="sourceCode default">underlying_.parse()</code> is called
with the <em>format-spec</em> of <em>complex-underlying-spec</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Returns</em>: An iterator past the end of the
<em>complex-format-spec</em>.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>template&lt;class FormatContext&gt;</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  typename FormatContext::iterator</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    format(complex&lt;T&gt; value, FormatContext&amp; ctx) const;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Effects</em>: Writes the following into
<code class="sourceCode default">ctx.out()</code>, adjusted according to
the <em>complex-format-spec</em>:</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.1)</a></span> -
<code class="sourceCode default">opening-bracket_</code>,</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.2)</a></span> -
<code class="sourceCode default">value.real()</code> via
<code class="sourceCode default">underlying_</code>,</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.3)</a></span> -
<code class="sourceCode default">separator_</code>,</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.5)</a></span> -
<code class="sourceCode default">value.imag()</code> via
<code class="sourceCode default">underlying_</code>. If
<em>complex-type</em> is not <code class="sourceCode default">S</code>
and <code class="sourceCode default">underlying_.parse()</code> was
called without a <em>sign</em> option or a <em>sign</em> option
<code class="sourceCode default">-</code>, adjust the ouput as-if
<code class="sourceCode default">underlying_.parse()</code> was called
with <em>sign</em> option <code class="sourceCode default">+</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.5)</a></span> -
if <em>complex-type</em> is not
<code class="sourceCode default">S</code>, if
<code class="sourceCode default">value.imag()</code> is not infinity or
NaN, write
`<code class="sourceCode default">STATICALLY-WIDEN(&quot; i&quot;)</code>
else write
<code class="sourceCode default">STATICALLY-WIDEN(&quot; i&quot;)</code>,
and</p>
<p><span class="marginalizedparent"><a class="marginalized">(11.6)</a></span> -
<code class="sourceCode default">closing-bracket_</code>.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>[ Example xx:</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>string s0 = format(&quot;{}&quot;, complex{0.0, 0.0});         // s0 has value: (0+0i)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>string s1 = format(&quot;{::-}&quot;, complex{0.0, 0.0});      // s1 has value: (0+0i)</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>string s2 = format(&quot;{:: }&quot;, complex{0.0, 0.0});      // s2 has value: ( 0 0i)</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>string s3 = format(&quot;{::+}&quot;, complex{0.0, 0.0});      // s3 has value: (+0+0i)</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>string s4 = format(&quot;{:S:}&quot;, complex{0.0, 0.0});      // s4 has value: (0,0)</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>double inf = numeric_limits&lt;double&gt;::infinity();</span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>double nan = numeric_limits&lt;double&gt;::quiet_NaN();</span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>string s5 = format(&quot;{::}&quot;, complex{inf, nan});       // s5 has value: (inf+nan i)</span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>string s6 = format(&quot;{:S:}&quot;, complex{inf, nan});      // s6 has value: (inf,nan)</span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>-- end example]</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Returns</em>: An iterator past the end of the output range.</p>
</div>
</div>
<h2 data-number="7.4" id="formatters-bitset-and-bitsetreference"><span class="header-section-number">7.4</span> Formatters
<code class="sourceCode default">bitset</code> and
<code class="sourceCode default">bitset::reference</code><a href="#formatters-bitset-and-bitsetreference" class="self-link"></a></h2>
<p>Add to <span>22.9.1
<a href="https://wg21.link/bitset.syn">[bitset.syn]</a></span></p>
<div class="bq">
<div>
<div class="sourceCode" id="cb16"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>   template&lt;class charT, class traits, size_t N&gt;</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>     basic_ostream&lt;charT, traits&gt;&amp;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>       operator&lt;&lt;(basic_ostream&lt;charT, traits&gt;&amp; os, const bitset&lt;N&gt;&amp; x);</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="va">+  // [bitset.format], formatter specialization for bitset</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;size_t N, class charT&gt; struct formatter&lt;bitset&lt;N&gt;, charT&gt;;</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;class T&gt;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="va">+    constexpr bool is-bitset-reference = see below;          // exposition only</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;class T, class charT&gt; requires is-bitset-reference&lt;T&gt;</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="va">+    struct formatter&lt;T, charT&gt;;</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a> }</span></code></pre></div>
</div>
</div>
<div class="bq">
<div>
<div class="sourceCode" id="cb17"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a> [3]{.pnum} The functions described in [template.bitset]{.sref} can report three kinds of errors, each associated with a distinct exception:</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> [3.1]{.pnum} an _invalid-argument_ error is associated with exceptions of type `invalid_argument` ([invalid.argument]{.sref});</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a> [3.2]{.pnum} an _out-of-range_ error is associated with exceptions of type out_of_range ([out.of.range]{.sref});</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a> [3.3]{.pnum} an _overflow_ error is associated with exceptions of type overflow_error ([overflow.error]{.sref}).</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="va">+template&lt;class T&gt;</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="va">+  constexpr bool is-bitset-reference = see below;</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ [4]{.pnum} The expression is-bitset-reference&lt;T&gt; is true if T denotes the type `template&lt;size_t N&gt; bitset&lt;N&gt;::reference`.</span></span></code></pre></div>
</div>
</div>
<p>Add a new section 22.9.? Formatting [bitset.format]:</p>
<div class="bq">
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb18"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>namespace std {</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>  template&lt;size_t N, class charT = char&gt;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>  class formatter&lt;bitset&lt;N&gt;, charT {</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; separator_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;&quot;);        // exposition only</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; opening-bracket_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;(&quot;); // exposition only</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    basic_string_view&lt;charT&gt; closing-bracket_ = STATICALLY-WIDEN&lt;charT&gt;(&quot;)&quot;); // exposition only</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    charT zero_ = CharT(&#39;0&#39;);                                                 // exposition only</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    charT one_ = CharT(&#39;1&#39;);                                                  // exposition only</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>  public:</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    constexpr void set_separator(basic_string_view&lt;charT&gt; sep) noexcept;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>    constexpr void set_brackets(basic_string_view&lt;charT&gt; opening,</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>                                basic_string_view&lt;charT&gt; closing) noexcept;</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>    constexpr void set_zero_one(charT zero, charT one) noexcept;</span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>    template&lt;class ParseContext&gt;</span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>      constexpr typename ParseContext::iterator</span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>        parse(ParseContext&amp; ctx);</span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>    template&lt;class FormatContext&gt;</span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>      typename FormatContext::iterator</span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>        format(bitset&lt;N&gt; value, FormatContext&amp; ctx) const;</span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">template&lt;size_t N, class charT&gt; class formatter&lt;bitset&lt;N&gt;, charT&gt;;</code></p>
<p><code class="sourceCode default">formatter&lt;bitset&lt;N&gt;, charT&gt;</code>
interprets <em>format-spec</em> as a <em>bitset-format-spec</em>. The
syntax of format specifications is as follows:</p>
<blockquote>
<div class="line-block"><em>bitset-format-spec</em>:<br />
    <em>range-fill-and-align</em><sub>opt</sub> <em>#</em><sub>opt</sub>
<em>0</em><sub>opt</sub> <em>width</em><sub>opt</sub>
<em>L</em><sub>opt</sub> <em>n</em><sub>opt</sub>
<em>bitset-type</em><sub>opt</sub>
<em>bitset-underlying-spec</em><sub>opt</sub><br />
<em>bitset-type</em>: one of<br />
     <code class="sourceCode default">b</code>
<code class="sourceCode default">B</code>
<code class="sourceCode default">d</code>
<code class="sourceCode default">o</code>
<code class="sourceCode default">x</code>
<code class="sourceCode default">X</code>
<code class="sourceCode default">r</code>
<code class="sourceCode default">s</code><br />
<em>bitset-underlying-spec</em>:<br />
      : <em>format-spec</em></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>range-fill-and-align</em>, is interpreted the same way as a
described in <span>22.14.7.2
<a href="https://wg21.link/format.range.formatter">[format.range.formatter]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>#</em>, <em>0</em>, <em>width</em>, and <em>L</em> are interpreted
the same way as a described in <span>22.14.2
<a href="https://wg21.link/format.string">[format.string]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>n</em> is interpreted the same way as a described in <span>22.14.7.2
<a href="https://wg21.link/format.range.formatter">[format.range.formatter]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
the <em>bitset-type</em> specifier changes the way a
<code class="sourceCode default">bitset</code> is formatted, with
certain options only valid with certain argument types. The meaning of
the various type options is as specified in Table xx.</p>
<p>Table xx: Meaning of bitset-type options [tab:bitset.format.type]</p>
<table>
<colgroup>
<col style="width: 14%" />
<col style="width: 85%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Option</strong>
</div></th>
<th><div style="text-align:center">
<strong>Meaning</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode default">b</code>,
<code class="sourceCode default">B</code>,
<code class="sourceCode default">d</code>,
<code class="sourceCode default">o</code>,
<code class="sourceCode default">x</code>,
<code class="sourceCode default">X</code></td>
<td><p>Is formatted as if formatting the output of
<code class="sourceCode default">bitset&lt;N&gt;::to_ullong()</code>. If
the value can not be represented in an
<code class="sourceCode default">unsigned long long</code> it is
implementation defined whether the value is formatted as an integral or
an <code class="sourceCode default">overflow_error</code> is thrown.</p>
<p>Implementations may use different behavior for the different
options.</p>
<p><span class="note"><span>[ <em>Note:</em> </span>This allows to
generate output for the <code class="sourceCode default">b</code> option
and throwing for the <code class="sourceCode default">d</code>
option.<span> — <em>end note</em> ]</span></span></p></td>
</tr>
<tr class="even">
<td><code class="sourceCode default">r</code></td>
<td>The output is formatted as a range of boolean values.</td>
</tr>
<tr class="odd">
<td><code class="sourceCode default">s</code></td>
<td>Is formatted as if formatting the output of <code class="sourceCode default">bitset&lt;N&gt;::to_string(zero_, one_)</code>.</td>
</tr>
<tr class="even">
<td>none</td>
<td>The same <code class="sourceCode default">s</code>.</td>
</tr>
</tbody>
</table>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The <em>format-spec</em> in a <em>bitset-underlying-spec</em>, if any,
is interpreted as the <em>std-format-spec</em> for a
<code class="sourceCode default">bool</code> type as described in
<span>22.14.2
<a href="https://wg21.link/format.string">[format.string]</a></span>.
The <em>bitset-underlying-spec</em> is only valid when the
<em>bitset-type</em> option is
<code class="sourceCode default">r</code>.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt;</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  constexpr bool is-bitset-reference = see below;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
The variable template is-bitset-reference<T> is true if T denotes the
type <code class="sourceCode default">bitset&lt;N&gt;::reference</code>
for some value of <code class="sourceCode default">N</code> and
<code class="sourceCode default">bitset&lt;N&gt;</code> is not a
program-defined specialization.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T, class charT&gt; requires is-bitset-reference&lt;T&gt;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  struct formatter&lt;T, charT&gt; {</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>  private:</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    formatter&lt;bool, charT&gt; underlying_;     // exposition only</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  public:</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    template &lt;class ParseContext&gt;</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>      constexpr typename ParseContext::iterator</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>        parse(ParseContext&amp; ctx);</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    template &lt;class FormatContext&gt;</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>      typename FormatContext::iterator</span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>        format(const T&amp; ref, FormatContext&amp; ctx) const;</span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>  };</span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>template &lt;class ParseContext&gt;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  constexpr typename ParseContext::iterator</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    parse(ParseContext&amp; ctx);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
Effects: Equivalent to return underlying_.parse(ctx);</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>template &lt;class FormatContext&gt;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  typename FormatContext::iterator</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    format(const T&amp; ref, FormatContext&amp; ctx) const;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
Effects: Equivalent to return underlying_.format(ref, ctx);</p>
</div>
</div>
<h2 data-number="7.5" id="formatter-sub_match"><span class="header-section-number">7.5</span> Formatter
<code class="sourceCode default">sub_match</code><a href="#formatter-sub_match" class="self-link"></a></h2>
<p>Add to <span>32.3
<a href="https://wg21.link/re.syn">[re.syn]</a></span></p>
<div class="bq">
<div>
<div class="sourceCode" id="cb23"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>   template&lt;class charT, class ST, class BiIter&gt;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>     basic_ostream&lt;charT, ST&gt;&amp;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>       operator&lt;&lt;(basic_ostream&lt;charT, ST&gt;&amp; os, const sub_match&lt;BiIter&gt;&amp; m);</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="va">+  // [re.submatch.format], formatting</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;class BiIter, class charT&gt;</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="va">+  struct formatter&lt;sub_match&lt;BiIter&gt;, charT&gt;;</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>   // [re.results], class template match_results</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>   template&lt;class BidirectionalIterator,</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>            class Allocator = allocator&lt;sub_match&lt;BidirectionalIterator&gt;&gt;&gt;</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>     class match_results;</span></code></pre></div>
</div>
</div>
<p>Add a new section 38.8.? Formatting [re.submatch.format]:</p>
<div class="bq">
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">formatter&lt;sub_match&lt;BiIter&gt;, charT&gt;</code>
is a <em>debug-enabled</em> string type specialization (<span>22.14.6.3
<a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a></span>).</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The formatter outputs the result of the
<code class="sourceCode default">sub_match</code>’s
<code class="sourceCode default">str()</code>.</p>
</div>
</div>
<h2 data-number="7.6" id="header-system_error"><span class="header-section-number">7.6</span> Header
<code class="sourceCode default">system_error</code><a href="#header-system_error" class="self-link"></a></h2>
<p>Add to <span>19.5.2
<a href="https://wg21.link/system.error.syn">[system.error.syn]</a></span></p>
<div class="bq">
<div>
<div class="sourceCode" id="cb24"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>   // [syserr.compare], comparison operator functions</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>   bool operator==(const error_code&amp; lhs, const error_code&amp; rhs) noexcept;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>   bool operator==(const error_code&amp; lhs, const error_condition&amp; rhs) noexcept;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>   bool operator==(const error_condition&amp; lhs, const error_condition&amp; rhs) noexcept;</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>   strong_ordering operator&lt;=&gt;(const error_code&amp; lhs, const error_code&amp; rhs) noexcept;</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>   strong_ordering operator&lt;=&gt;(const error_condition&amp; lhs, const error_condition&amp; rhs) noexcept;</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="va">+  // [syserr.format], formatter support</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;&gt; struct formatter&lt;error_category&gt;;</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;&gt; struct formatter&lt;error_code&gt;;</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="va">+  template&lt;&gt; struct formatter&lt;error_condition&gt;;</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>   // [syserr.hash], hash support</span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>   template&lt;class T&gt; struct hash;</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>   template&lt;&gt; struct hash&lt;error_code&gt;;</span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>   template&lt;&gt; struct hash&lt;error_condition&gt;;</span></code></pre></div>
</div>
</div>
<p>Add a new section 19.5.? Formatting [syserr.format]:</p>
<div class="bq">
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
For each of <code class="sourceCode default">error_code</code> and
<code class="sourceCode default">error_condition</code>, the library
provides the following formatter specialization where
<code class="sourceCode default">error-code</code> is the name of the
template.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>template&lt;&gt; struct formatter&lt;error-code&gt;;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">formatter&lt;error-code&gt;</code>
interprets <em>format-spec</em> as a <em>error-code-format-spec</em>.
The syntax of format specifications is as follows:</p>
<blockquote>
<div class="line-block"><em>error-code-format-spec</em>:<br />
    <em>fill-and-align</em><sub>opt</sub> <em>#</em><sub>opt</sub>
<em>0</em><sub>opt</sub> <em>width</em><sub>opt</sub>
<em>L</em><sub>opt</sub> <em>error-code-type</em><sub>opt</sub><br />
<em>error-code-type</em>:<br />
    <em>error-code-type-value</em><br />
    <em>error-code-type-message</em><br />
    <em>error-code-type-ostream</em><br />
<em>error-code-type-value</em>: one of<br />
     <code class="sourceCode default">b</code>
<code class="sourceCode default">B</code>
<code class="sourceCode default">d</code>
<code class="sourceCode default">o</code>
<code class="sourceCode default">x</code>
<code class="sourceCode default">X</code><br />
<em>error-code-type-message</em>:<br />
     <code class="sourceCode default">s</code><br />
<em>error-code-type-ostream</em>:<br />
     <code class="sourceCode default">S</code></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>fill-and-align</em>, <em>#</em>, <em>0</em>, <em>width</em>, and
<em>L</em> are interpreted the same way as a described in <span>22.14.2
<a href="https://wg21.link/format.string">[format.string]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
When <em>error-code-type</em> is a <em>error-code-type-value</em> the
value is formatted as an <code class="sourceCode default">int</code>
obtained by calling the <code class="sourceCode default">value()</code>
member function.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
When <em>error-code-type</em> is a <em>error-code-type-message</em> the
value is formatted as a <code class="sourceCode default">string</code>
obtained by calling the
<code class="sourceCode default">message()</code> member function.</p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
When <em>error-code-type</em> is a <em>error-code-type-ostream</em> the
value is formatted is the same way the output of
<code class="sourceCode default">operator&lt;&lt;</code>. When this
display type is used only the <em>fill-and-align</em> and <em>width</em>
option may be present.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
When the <em>error-code-type</em> is omitted it is formatted as-if the
<em>error-code-type-ostream</em> has been specified.</p>
</div>
</div>
<h2 data-number="7.7" id="byte-2"><span class="header-section-number">7.7</span> Byte<a href="#byte-2" class="self-link"></a></h2>
<p>TODO after the generic design is approved.</p>
<h1 data-number="8" id="bibliography"><span class="header-section-number">8</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-N4944" class="csl-entry" role="doc-biblioentry">
[N4944] Thomas Köppe. 2023-03-22. Working Draft, Standard for
Programming Language C++. <a href="https://wg21.link/n4944"><div class="csl-block">https://wg21.link/n4944</div></a>
</div>
<div id="ref-P1636R2" class="csl-entry" role="doc-biblioentry">
[P1636R2] Lars Gullik Bjønnes. 2019-10-06. Formatters for library types.
<a href="https://wg21.link/p1636r2"><div class="csl-block">https://wg21.link/p1636r2</div></a>
</div>
<div id="ref-P1684R5" class="csl-entry" role="doc-biblioentry">
[P1684R5] Christian Trott, D. S. Hollman,Mark Hoemmen,Daniel
Sunderland,Damien Lebrun-Grandie. 2023-05-19. mdarray: An Owning
Multidimensional Array Analog of mdspan. <a href="https://wg21.link/p1684r5"><div class="csl-block">https://wg21.link/p1684r5</div></a>
</div>
<div id="ref-P2197R0" class="csl-entry" role="doc-biblioentry">
[P2197R0] Michael Tesch, Victor Zverovich. 2020-08-22. Formatting for
std::complex. <a href="https://wg21.link/p2197r0"><div class="csl-block">https://wg21.link/p2197r0</div></a>
</div>
<div id="ref-P2286R8" class="csl-entry" role="doc-biblioentry">
[P2286R8] Barry Revzin. 2022-05-16. Formatting Ranges. <a href="https://wg21.link/p2286r8"><div class="csl-block">https://wg21.link/p2286r8</div></a>
</div>
<div id="ref-P2585R0" class="csl-entry" role="doc-biblioentry">
[P2585R0] Barry Revzin. 2022-05-15. Improving default container
formatting. <a href="https://wg21.link/p2585r0"><div class="csl-block">https://wg21.link/p2585r0</div></a>
</div>
<div id="ref-P2637R2" class="csl-entry" role="doc-biblioentry">
[P2637R2] Barry Revzin. 2023-05-16. Member visit. <a href="https://wg21.link/p2637r2"><div class="csl-block">https://wg21.link/p2637r2</div></a>
</div>
<div id="ref-P2693R1" class="csl-entry" role="doc-biblioentry">
[P2693R1] Corentin Jabot, Victor Zverovich. 2023-02-09. Formatting
thread::id and stacktrace. <a href="https://wg21.link/p2693r1"><div class="csl-block">https://wg21.link/p2693r1</div></a>
</div>
<div id="ref-P2728R3" class="csl-entry" role="doc-biblioentry">
[P2728R3] Zach Laine. 2023-05-10. Unicode in the Library, Part 1: UTF
Transcoding. <a href="https://wg21.link/p2728r3"><div class="csl-block">https://wg21.link/p2728r3</div></a>
</div>
<div id="ref-P2845R0" class="csl-entry" role="doc-biblioentry">
[P2845R0] Victor Zverovich. 2023-05-07. Formatting of
std::filesystem::path. <a href="https://wg21.link/p2845r0"><div class="csl-block">https://wg21.link/p2845r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
