<!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-05-17" />
  <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>P3705R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-05-17</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" id="toc-design"><span class="toc-section-number">2</span> 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</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.2</span> null_sentinel pass-by-value
design<span></span></a>
<ul>
<li><a href="#null-sentinel" id="toc-null-sentinel"><span class="toc-section-number">2.2.1</span> Null
sentinel<span></span></a></li>
<li><a href="#operations" id="toc-operations"><span class="toc-section-number">2.2.2</span> Operations<span></span></a></li>
</ul></li>
<li><a href="#null_sentinel-pass-by-reference-design" id="toc-null_sentinel-pass-by-reference-design"><span class="toc-section-number">2.3</span> null_sentinel pass-by-reference
design<span></span></a>
<ul>
<li><a href="#null-sentinel-1" id="toc-null-sentinel-1"><span class="toc-section-number">2.3.1</span> Null
sentinel<span></span></a></li>
<li><a href="#operations-1" id="toc-operations-1"><span class="toc-section-number">2.3.2</span> Operations<span></span></a></li>
</ul></li>
<li><a href="#null_term-cpo" id="toc-null_term-cpo"><span class="toc-section-number">2.4</span> null_term
CPO<span></span></a></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>
</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 four 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 four
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>
<h1 data-number="2" id="design"><span class="header-section-number">2</span> Design<a href="#design" class="self-link"></a></h1>
<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>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>
<h2 data-number="2.1" id="exposition-only-helper-concept-default-initializable-and-equality-comparable-iter-value"><span class="header-section-number">2.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></h2>
<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="kw">namespace</span> std <span class="op">{</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">template</span><span class="op">&lt;</span><span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb7-4"><a href="#cb7-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="cb7-5"><a href="#cb7-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="cb7-6"><a href="#cb7-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="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="2.2" id="null_sentinel-pass-by-value-design"><span class="header-section-number">2.2</span> null_sentinel pass-by-value
design<a href="#null_sentinel-pass-by-value-design" class="self-link"></a></h2>
<h3 data-number="2.2.1" id="null-sentinel"><span class="header-section-number">2.2.1</span> Null sentinel<a href="#null-sentinel" class="self-link"></a></h3>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> null_sentinel_t <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-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="cb8-5"><a href="#cb8-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="cb8-6"><a href="#cb8-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="cb8-7"><a href="#cb8-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="cb8-8"><a href="#cb8-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="cb8-9"><a href="#cb8-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="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-12"><a href="#cb8-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="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="2.2.2" id="operations"><span class="header-section-number">2.2.2</span> Operations<a href="#operations" 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">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-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="cb9-3"><a href="#cb9-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="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">template</span><span class="op">&lt;</span>forward_iterator I<span class="op">&gt;</span></span>
<span id="cb10-2"><a href="#cb10-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="cb10-3"><a href="#cb10-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>
<h2 data-number="2.3" id="null_sentinel-pass-by-reference-design"><span class="header-section-number">2.3</span> null_sentinel pass-by-reference
design<a href="#null_sentinel-pass-by-reference-design" class="self-link"></a></h2>
<h3 data-number="2.3.1" id="null-sentinel-1"><span class="header-section-number">2.3.1</span> Null sentinel<a href="#null-sentinel-1" class="self-link"></a></h3>
<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">namespace</span> std <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> null_sentinel_t <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-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="cb11-5"><a href="#cb11-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="cb11-6"><a href="#cb11-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="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-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="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="2.3.2" id="operations-1"><span class="header-section-number">2.3.2</span> Operations<a href="#operations-1" class="self-link"></a></h3>
<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>input_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>
<h2 data-number="2.4" id="null_term-cpo"><span class="header-section-number">2.4</span> null_term CPO<a href="#null_term-cpo" class="self-link"></a></h2>
<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">inline</span> <span class="kw">constexpr</span> <em>unspecified</em> null_term;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-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>
<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>
<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>
