<!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="2025-06-16" />
  <title>A Sentinel for Null-Terminated Strings</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">A Sentinel for
Null-Terminated Strings</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3705R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-06-16</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>
      SG-9 Ranges<br>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Eddie Nolan<br>&lt;<a href="mailto:eddiejnolan@gmail.com" class="email">eddiejnolan@gmail.com</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="#motivation" id="toc-motivation"><span class="toc-section-number">1</span> Motivation<span></span></a></li>
<li><a href="#design-alternatives" id="toc-design-alternatives"><span class="toc-section-number">2</span> Design Alternatives<span></span></a>
<ul>
<li><a href="#sentinel-based-design" id="toc-sentinel-based-design"><span class="toc-section-number">2.1</span> Sentinel-based
design<span></span></a>
<ul>
<li><a href="#exposition-only-helper-concept-default-initializable-and-equality-comparable-iter-value" id="toc-exposition-only-helper-concept-default-initializable-and-equality-comparable-iter-value"><span class="toc-section-number">2.1.1</span> Exposition-only helper concept
<code class="sourceCode cpp"><em>default-initializable-and-equality-comparable-iter-value</em></code><span></span></a></li>
<li><a href="#null_sentinel-pass-by-value-design" id="toc-null_sentinel-pass-by-value-design"><span class="toc-section-number">2.1.2</span>
<code class="sourceCode cpp">null_sentinel</code> pass-by-value
design<span></span></a></li>
<li><a href="#null_sentinel-pass-by-reference-design" id="toc-null_sentinel-pass-by-reference-design"><span class="toc-section-number">2.1.3</span>
<code class="sourceCode cpp">null_sentinel</code> pass-by-reference
design<span></span></a></li>
<li><a href="#null_term-cpo" id="toc-null_term-cpo"><span class="toc-section-number">2.1.4</span>
<code class="sourceCode cpp">null_term</code> CPO<span></span></a></li>
</ul></li>
<li><a href="#unchecked_take_before-based-design" id="toc-unchecked_take_before-based-design"><span class="toc-section-number">2.2</span>
<code class="sourceCode cpp">unchecked_take_before</code>-based
design<span></span></a>
<ul>
<li><a href="#exposition-only-helper-concept-default-initializable-iter-value" id="toc-exposition-only-helper-concept-default-initializable-iter-value"><span class="toc-section-number">2.2.1</span> exposition-only helper concept
<code class="sourceCode cpp"><em>default-initializable-iter-value</em></code><span></span></a></li>
<li><a href="#null_term-cpo-1" id="toc-null_term-cpo-1"><span class="toc-section-number">2.2.2</span>
<code class="sourceCode cpp">null_term</code> CPO<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#history" id="toc-history"><span class="toc-section-number">3</span> History<span></span></a>
<ul>
<li><a href="#changelog" id="toc-changelog"><span class="toc-section-number">3.1</span> Changelog<span></span></a>
<ul>
<li><a href="#changes-since-p2728r1" id="toc-changes-since-p2728r1"><span class="toc-section-number">3.1.1</span> Changes since
P2728R1<span></span></a></li>
<li><a href="#changes-since-p2728r3" id="toc-changes-since-p2728r3"><span class="toc-section-number">3.1.2</span> Changes since
P2728R3<span></span></a></li>
<li><a href="#changes-since-p2728r4" id="toc-changes-since-p2728r4"><span class="toc-section-number">3.1.3</span> Changes since
P2728R4<span></span></a></li>
<li><a href="#changes-since-p2728r5" id="toc-changes-since-p2728r5"><span class="toc-section-number">3.1.4</span> Changes since
P2728R5<span></span></a></li>
<li><a href="#changes-since-p2728r6" id="toc-changes-since-p2728r6"><span class="toc-section-number">3.1.5</span> Changes since
P2728R6<span></span></a></li>
<li><a href="#changes-since-p2728r7" id="toc-changes-since-p2728r7"><span class="toc-section-number">3.1.6</span> Changes since
P2728R7<span></span></a></li>
<li><a href="#changes-since-p3705r0" id="toc-changes-since-p3705r0"><span class="toc-section-number">3.1.7</span> Changes since
P3705R0<span></span></a></li>
</ul></li>
<li><a href="#relevant-pollsminutes" id="toc-relevant-pollsminutes"><span class="toc-section-number">3.2</span> Relevant
Polls/Minutes<span></span></a>
<ul>
<li><a href="#sg9-review-of-d2728r4-on-2023-06-12-during-varna-2023" id="toc-sg9-review-of-d2728r4-on-2023-06-12-during-varna-2023"><span class="toc-section-number">3.2.1</span> SG9 review of D2728R4 on
2023-06-12 during Varna 2023<span></span></a></li>
<li><a href="#sg16-review-of-p2728r3-on-2023-05-10-telecon" id="toc-sg16-review-of-p2728r3-on-2023-05-10-telecon"><span class="toc-section-number">3.2.2</span> SG16 review of P2728R3 on
2023-05-10 (Telecon)<span></span></a></li>
</ul></li>
</ul></li>
</ul>
</div>
<h1 data-number="1" id="motivation"><span class="header-section-number">1</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Consider using <code class="sourceCode cpp">std<span class="op">::</span>views<span class="op">::</span>take</code>
to get the first five characters from a string. If we pass a string
literal with five or more characters, it looks okay:</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><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>string<span class="op">{</span>std<span class="op">::</span>from_range, <span class="st">&quot;Brubeck&quot;</span> <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>take<span class="op">(</span><span class="dv">5</span><span class="op">)}</span> <span class="op">==</span> <span class="st">&quot;Brube&quot;</span><span class="op">)</span>; <span class="co">// passes</span></span></code></pre></div>
<p>However, if we pass it a string literal with fewer than five
characters, we get in trouble:</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><span class="co">// static_assert(std::string{std::from_range, &quot;Dave&quot; | std::views::take(5)} == &quot;Dave&quot;); // fails</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">::</span>string_view_literals;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>string<span class="op">{</span>std<span class="op">::</span>from_range, <span class="st">&quot;Dave&quot;</span> <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>take<span class="op">(</span><span class="dv">5</span><span class="op">)}</span> <span class="op">==</span> <span class="st">&quot;Dave</span><span class="sc">\0</span><span class="st">&quot;</span><span class="bu">sv</span><span class="op">)</span>; <span class="co">// passes</span></span></code></pre></div>
<p>The reason the null terminator is included in the output here is
because undecayed string literals are arrays of characters, including
the null terminator, which the ranges library treats like any other
array:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;algorithm&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;array&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;type_traits&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>std<span class="op">::</span>remove_reference_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><span class="st">&quot;foo&quot;</span><span class="op">)&gt;</span>, <span class="kw">const</span> <span class="dt">char</span><span class="op">[</span><span class="dv">4</span><span class="op">]&gt;)</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>equal<span class="op">(</span><span class="st">&quot;foo&quot;</span>, std<span class="op">::</span>array<span class="op">{</span><span class="ch">&#39;f&#39;</span>, <span class="ch">&#39;o&#39;</span>, <span class="ch">&#39;o&#39;</span>, <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">}))</span>;</span></code></pre></div>
<p>A common workaround is to wrap the string literal in <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>.
But this has a performance cost: despite the fact that we only care
about the first five characters, we still need to make a pass through
the entire string to find the null terminator:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string take_five<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> long_string<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string_view <span class="kw">const</span> long_string_view <span class="op">=</span> long_string; <span class="co">// read all of long_string!</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>string<span class="op">{</span>std<span class="op">::</span>from_range, long_string_view <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>take<span class="op">(</span><span class="dv">5</span><span class="op">)}</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This paper introduces
<code class="sourceCode cpp">null_sentinel</code> to solve this problem.
It ends the range when it encounters a null:</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><span class="kw">constexpr</span> std<span class="op">::</span>string take_five<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> long_string<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>subrange <span class="kw">const</span> long_string_range<span class="op">(</span>long_string, std<span class="op">::</span>null_sentinel<span class="op">)</span>; <span class="co">// lazy!</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>string<span class="op">{</span>std<span class="op">::</span>from_range, long_string_range <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>take<span class="op">(</span><span class="dv">5</span><span class="op">)}</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It also introduces a <code class="sourceCode cpp">null_term</code>
CPO for the common case of constructing the a subrange like the one in
the above example:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string take_five<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> long_string<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>string<span class="op">{</span>std<span class="op">::</span>from_range, std<span class="op">::</span>null_term<span class="op">(</span>long_string<span class="op">)</span> <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>take<span class="op">(</span><span class="dv">5</span><span class="op">)}</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The sentinel type matches any iterator position
<code class="sourceCode cpp">it</code> at which
<code class="sourceCode cpp"><span class="op">*</span>it</code> is equal
to a default-constructed object of type <code class="sourceCode cpp">iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span></code>.
This works for null-terminated strings, but can also serve as the
sentinel for any range terminated by a default-constructed value.</p>
<p>For example, <code class="sourceCode cpp">null_term</code> can be
used to iterate <code class="sourceCode cpp">argv</code> and
<code class="sourceCode cpp">environ</code>. The following program
demonstrates this:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;print&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">extern</span> <span class="dt">char</span><span class="op">**</span> environ;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc, <span class="dt">char</span><span class="op">**</span> argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;argv: {}&quot;</span>, std<span class="op">::</span>null_term<span class="op">(</span>argv<span class="op">))</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;environ: {}&quot;</span>, std<span class="op">::</span>null_term<span class="op">(</span>environ<span class="op">))</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Output:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>$ env --ignore-environment FOO=bar BAZ=quux ./test corge</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>argv: [&quot;./test&quot;, &quot;corge&quot;]</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>environ: [&quot;FOO=bar&quot;, &quot;BAZ=quux&quot;]</span></code></pre></div>
<h1 data-number="2" id="design-alternatives"><span class="header-section-number">2</span> Design Alternatives<a href="#design-alternatives" class="self-link"></a></h1>
<p>This paper includes two alternatives for the sentinel: one that
always passes the iterator to the equality operator by reference, and
one that passes by reference for input iterators and by value otherwise.
(Input iterators must be passed by reference here because they are
allowed to be noncopyable.)</p>
<p>The argument for the by-reference design is that it’s simpler. The
argument for the by-value design is that it’s more consistent, since, to
the author’s knowledge, every other parameter in the standard library
that takes an iterator takes it by value; although we still need to take
input iterators by reference here, we allow the common case to be
consistent and treat the edge case as an edge case.</p>
<p>Finally, we could also simply drop
<code class="sourceCode cpp">null_sentinel</code> entirely, only
standardize <code class="sourceCode cpp">null_term</code>, and implement
<code class="sourceCode cpp">null_term</code> in terms of
<code class="sourceCode cpp">unchecked_take_before</code>. Note that at
the time of writing, there is no paper proposing
<code class="sourceCode cpp">unchecked_take_before</code>, so that would
also need to be written if we want to take that direction.</p>
<h2 data-number="2.1" id="sentinel-based-design"><span class="header-section-number">2.1</span> Sentinel-based design<a href="#sentinel-based-design" class="self-link"></a></h2>
<h3 data-number="2.1.1" id="exposition-only-helper-concept-default-initializable-and-equality-comparable-iter-value"><span class="header-section-number">2.1.1</span> Exposition-only helper
concept <code class="sourceCode cpp"><em>default-initializable-and-equality-comparable-iter-value</em></code><a href="#exposition-only-helper-concept-default-initializable-and-equality-comparable-iter-value" class="self-link"></a></h3>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>default-initializable-and-equality-comparable-iter-value</em> <span class="op">=</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    default_initializable<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    equality_comparable_with<span class="op">&lt;</span>iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span>; <span class="co">// <em>exposition only</em></span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="2.1.2" id="null_sentinel-pass-by-value-design"><span class="header-section-number">2.1.2</span>
<code class="sourceCode cpp">null_sentinel</code> pass-by-value design<a href="#null_sentinel-pass-by-value-design" class="self-link"></a></h3>
<h4 data-number="2.1.2.1" id="null-sentinel"><span class="header-section-number">2.1.2.1</span> Null sentinel<a href="#null-sentinel" class="self-link"></a></h4>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> null_sentinel_t <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span><span class="kw">not</span> forward_iterator<span class="op">&lt;</span>I<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I <span class="kw">const</span><span class="op">&amp;</span> it, null_sentinel_t<span class="op">)</span>;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>forward_iterator I<span class="op">&gt;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I it, null_sentinel_t<span class="op">)</span>;</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> null_sentinel_t null_sentinel;</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><span class="op">}</span></span></code></pre></div>
<h4 data-number="2.1.2.2" id="operations"><span class="header-section-number">2.1.2.2</span> Operations<a href="#operations" class="self-link"></a></h4>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span><span class="kw">not</span> forward_iterator<span class="op">&lt;</span>I<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I <span class="kw">const</span><span class="op">&amp;</span> it, null_sentinel_t<span class="op">)</span>;</span></code></pre></div>
<p>Effects:</p>
<p>Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> <span class="op">*</span>it <span class="op">==</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;{}</span>;</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>forward_iterator I<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I it, null_sentinel_t<span class="op">)</span>;</span></code></pre></div>
<p>Effects:</p>
<p>Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> <span class="op">*</span>it <span class="op">==</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;{}</span>;</code>.</p>
<h3 data-number="2.1.3" id="null_sentinel-pass-by-reference-design"><span class="header-section-number">2.1.3</span>
<code class="sourceCode cpp">null_sentinel</code> pass-by-reference
design<a href="#null_sentinel-pass-by-reference-design" class="self-link"></a></h3>
<h4 data-number="2.1.3.1" id="null-sentinel-1"><span class="header-section-number">2.1.3.1</span> Null sentinel<a href="#null-sentinel-1" class="self-link"></a></h4>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> null_sentinel_t <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I <span class="kw">const</span><span class="op">&amp;</span> it, null_sentinel_t<span class="op">)</span>;</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> null_sentinel_t null_sentinel;</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h4 data-number="2.1.3.2" id="operations-1"><span class="header-section-number">2.1.3.2</span> Operations<a href="#operations-1" class="self-link"></a></h4>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <em>default-initializable-and-equality-comparable-iter-value</em><span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>I it, null_sentinel_t<span class="op">)</span>;</span></code></pre></div>
<p>Effects:</p>
<p>Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> <span class="op">*</span>it <span class="op">==</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;{}</span>;</code>.</p>
<h3 data-number="2.1.4" id="null_term-cpo"><span class="header-section-number">2.1.4</span>
<code class="sourceCode cpp">null_term</code> CPO<a href="#null_term-cpo" class="self-link"></a></h3>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <em>unspecified</em> null_term;</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The name <code class="sourceCode cpp">null_term</code> denotes a
customization point object ([customization.point.object]). Given a
subexpression <code class="sourceCode cpp">E</code>, the expression
<code class="sourceCode cpp">null_term<span class="op">(</span>E<span class="op">)</span></code>
is expression-equivalent to <code class="sourceCode cpp">ranges<span class="op">::</span>subrange<span class="op">(</span>E, null_sentinel<span class="op">)</span></code>.</p>
<h2 data-number="2.2" id="unchecked_take_before-based-design"><span class="header-section-number">2.2</span>
<code class="sourceCode cpp">unchecked_take_before</code>-based design<a href="#unchecked_take_before-based-design" class="self-link"></a></h2>
<h3 data-number="2.2.1" id="exposition-only-helper-concept-default-initializable-iter-value"><span class="header-section-number">2.2.1</span> exposition-only helper
concept
<code class="sourceCode cpp"><em>default-initializable-iter-value</em></code><a href="#exposition-only-helper-concept-default-initializable-iter-value" class="self-link"></a></h3>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>default-initializable-iter-value</em> <span class="op">=</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    default_initializable<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span>; <span class="co">// <em>exposition only</em></span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="2.2.2" id="null_term-cpo-1"><span class="header-section-number">2.2.2</span>
<code class="sourceCode cpp">null_term</code> CPO<a href="#null_term-cpo-1" class="self-link"></a></h3>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></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>  <span class="kw">inline</span> <span class="kw">constexpr</span> <em>unspecified</em> null_term;</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><span class="op">}</span></span></code></pre></div>
<p>The name <code class="sourceCode cpp">null_term</code> denotes a
customization point object ([customization.point.object]). Given a
subexpression <code class="sourceCode cpp">E</code>, the expression
<code class="sourceCode cpp">null_term<span class="op">(</span>E<span class="op">)</span></code>
is expression-equivalent to <code class="sourceCode cpp">subrange<span class="op">(</span>E, unreachable_sentinel<span class="op">)</span> <span class="op">|</span> unchecked_take_before<span class="op">(</span>iter_value_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>E<span class="op">)&gt;{})</span></code>.</p>
<p>Constraints:</p>
<p><code class="sourceCode cpp"><em>default-inititializable-iter-value</em><span class="op">&lt;</span>E<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<h1 data-number="3" id="history"><span class="header-section-number">3</span> History<a href="#history" class="self-link"></a></h1>
<h2 data-number="3.1" id="changelog"><span class="header-section-number">3.1</span> Changelog<a href="#changelog" class="self-link"></a></h2>
<p>This proposal was originally written by Zach Laine as part of P2728,
then updated and split out by Eddie Nolan.</p>
<h3 data-number="3.1.1" id="changes-since-p2728r1"><span class="header-section-number">3.1.1</span> Changes since P2728R1<a href="#changes-since-p2728r1" class="self-link"></a></h3>
<ul>
<li>Generalize <code class="sourceCode cpp">null_sentinel_t</code> to a
non-Unicode-specific facility.</li>
</ul>
<h3 data-number="3.1.2" id="changes-since-p2728r3"><span class="header-section-number">3.1.2</span> Changes since P2728R3<a href="#changes-since-p2728r3" class="self-link"></a></h3>
<ul>
<li>Change <code class="sourceCode cpp">null_sentinel_t</code> back to
being Unicode-specific.</li>
</ul>
<h3 data-number="3.1.3" id="changes-since-p2728r4"><span class="header-section-number">3.1.3</span> Changes since P2728R4<a href="#changes-since-p2728r4" class="self-link"></a></h3>
<ul>
<li>Move <code class="sourceCode cpp">null_sentinel_t</code> to
<code class="sourceCode cpp">std</code>, remove its
<code class="sourceCode cpp">base</code> member function, and make it
useful for more than just pointers, based on SG-9 guidance.</li>
</ul>
<h3 data-number="3.1.4" id="changes-since-p2728r5"><span class="header-section-number">3.1.4</span> Changes since P2728R5<a href="#changes-since-p2728r5" class="self-link"></a></h3>
<ul>
<li>Simplify the complicated constraint on the comparison operator for
<code class="sourceCode cpp">null_sentinel_t</code>.</li>
</ul>
<h3 data-number="3.1.5" id="changes-since-p2728r6"><span class="header-section-number">3.1.5</span> Changes since P2728R6<a href="#changes-since-p2728r6" class="self-link"></a></h3>
<ul>
<li>Fix a bug in <code class="sourceCode cpp">null_sentinel_t</code>
causing it not to satisfy
<code class="sourceCode cpp">sentinel_for</code> by changing its <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">==</span></code>
to return
<code class="sourceCode cpp"><span class="dt">bool</span></code>.</li>
<li>Fix a bug in <code class="sourceCode cpp">null_sentinel_t</code>
where it did not support non-copyable input iterators by having <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">==</span></code>
take input iterators by reference.</li>
</ul>
<h3 data-number="3.1.6" id="changes-since-p2728r7"><span class="header-section-number">3.1.6</span> Changes since P2728R7<a href="#changes-since-p2728r7" class="self-link"></a></h3>
<ul>
<li>Move <code class="sourceCode cpp">null_sentinel</code> and
<code class="sourceCode cpp">null_term</code> into P3705</li>
</ul>
<h3 data-number="3.1.7" id="changes-since-p3705r0"><span class="header-section-number">3.1.7</span> Changes since P3705R0<a href="#changes-since-p3705r0" class="self-link"></a></h3>
<ul>
<li>Fix off-by-one in textual description in motivation section</li>
<li>Add example with argv and environ</li>
<li>Add <code class="sourceCode cpp">unchecked_take_before</code> design
alternative</li>
</ul>
<h2 data-number="3.2" id="relevant-pollsminutes"><span class="header-section-number">3.2</span> Relevant Polls/Minutes<a href="#relevant-pollsminutes" class="self-link"></a></h2>
<h3 data-number="3.2.1" id="sg9-review-of-d2728r4-on-2023-06-12-during-varna-2023"><span class="header-section-number">3.2.1</span> SG9 review of D2728R4 on
2023-06-12 during Varna 2023<a href="#sg9-review-of-d2728r4-on-2023-06-12-during-varna-2023" class="self-link"></a></h3>
<ul>
<li><a href="https://wiki.edg.com/bin/view/Wg21varna/P2728#SG9-2023-06-12">Minutes</a></li>
</ul>
<p><strong>POLL:</strong> Move null_sentinel_t to std:: namespace</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td>3</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
</tbody>
</table>
<p><strong># Of Authors:</strong> 1</p>
<p><strong>Author’s Position:</strong> F</p>
<p><strong>Attendance:</strong> 9 (4 abstentions)</p>
<p><strong>Outcome:</strong> Consensus in favor</p>
<p><br /></p>
<p><strong>POLL:</strong> Remove null_sentinel_t::base member function
from the proposal</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>4</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
</tbody>
</table>
<p><strong># Of Authors:</strong> 1</p>
<p><strong>Author’s Position:</strong> F</p>
<p><strong>Attendance:</strong> 8 (3 abstentions)</p>
<p><strong>Outcome:</strong> Consensus in favor</p>
<h3 data-number="3.2.2" id="sg16-review-of-p2728r3-on-2023-05-10-telecon"><span class="header-section-number">3.2.2</span> SG16 review of P2728R3 on
2023-05-10 (Telecon)<a href="#sg16-review-of-p2728r3-on-2023-05-10-telecon" class="self-link"></a></h3>
<ul>
<li><a href="https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#may-10th-2023">Minutes</a></li>
</ul>
<p><strong>POLL:</strong> Separate <code class="sourceCode cpp">std<span class="op">::</span>null_sentinel_t</code>
from P2728 into a separate paper for SG9 and LEWG; SG16 does not need to
see it again.</p>
<table style="width:31%;">
<colgroup>
<col style="width: 6%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 6%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td>1</td>
<td>4</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
<p><strong>Attendance:</strong> 12 (3 abstentions)</p>
<p><strong>Outcome:</strong> No consensus; author’s discretion for how
to continue.</p>
</div>
</div>
</body>
</html>
