<!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="2022-05-09" />
  <title>A view of 0 or 1 elements: `views::maybe`</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.hanging-indent{margin-left: 1.5em; text-indent: -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; }
      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 view of 0 or 1 elements: <code class="sourceCode default">views::maybe</code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1255R7</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2022-05-09</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>
      SG9, LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Steve Downey<br>&lt;<a href="mailto:sdowney2@bloomberg.net" class="email">sdowney2@bloomberg.net</a>, <a href="mailto:sdowney@gmail.com" class="email">sdowney@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<p>Abstract: This paper proposes <code class="sourceCode default">views::maybe</code> a range adaptor that produces a view with cardinality 0 or 1 which adapts copyable object types, values, and nullable types such as <code class="sourceCode default">std::optional</code> and pointer to object types.</p>
<h1 data-number="1" id="changes"><span class="header-section-number">1</span> Changes<a href="#changes" class="self-link"></a></h1>
<h2 data-number="1.1" id="changes-since-r6"><span class="header-section-number">1.1</span> Changes since R6<a href="#changes-since-r6" class="self-link"></a></h2>
<ul>
<li>Extend to all object types in order to support list comprehension</li>
<li>Track working draft changes for Ranges</li>
<li>Add discussion of <em>borrowed_range</em></li>
<li>Add an example where pipelines use references.</li>
<li>Add support for proxy references (explore std::pointer_traits, etc).</li>
<li>Make std::views::maybe model std::ranges::borrowed_range if it’s not holding the object by value.</li>
<li>Add a const propagation section discussing options, existing precedent and proposing the option that the author suggests.</li>
</ul>
<h2 data-number="1.2" id="changes-since-r5"><span class="header-section-number">1.2</span> Changes since R5<a href="#changes-since-r5" class="self-link"></a></h2>
<ul>
<li>Fix reversed before/after table entry</li>
<li>Update to match C++20 style <span class="citation" data-cites="N4849">[<a href="#ref-N4849" role="doc-biblioref">N4849</a>]</span> and changes in Ranges since <span class="citation" data-cites="P0896R3">[<a href="#ref-P0896R3" role="doc-biblioref">P0896R3</a>]</span></li>
<li>size is now size_t, like other ranges are also</li>
<li>add synopsis for adding to <code class="sourceCode default">&lt;ranges&gt;</code> header</li>
<li>Wording clean up, formatting, typesetting</li>
<li>Add implementation notes and references</li>
</ul>
<h2 data-number="1.3" id="changes-since-r4"><span class="header-section-number">1.3</span> Changes since R4<a href="#changes-since-r4" class="self-link"></a></h2>
<ul>
<li>Use std::unwrap_reference</li>
<li>Remove conditional <code class="sourceCode default">noexcept</code>ness</li>
<li>Adopted the great concept renaming</li>
</ul>
<h2 data-number="1.4" id="changes-since-r3"><span class="header-section-number">1.4</span> Changes since R3<a href="#changes-since-r3" class="self-link"></a></h2>
<ul>
<li>Always Capture</li>
<li>Support reference_wrapper</li>
</ul>
<h2 data-number="1.5" id="changes-since-r2"><span class="header-section-number">1.5</span> Changes since R2<a href="#changes-since-r2" class="self-link"></a></h2>
<ul>
<li>Reflects current code as reviewed</li>
<li>Nullable concept specification</li>
</ul>
<p>Remove Readable as part of the specification, use the useful requirements from Readable</p>
<ul>
<li>Wording for views::maybe as proposed-</li>
<li>Appendix A: wording for a view_maybe that always captures</li>
</ul>
<h2 data-number="1.6" id="changes-since-r1"><span class="header-section-number">1.6</span> Changes since R1<a href="#changes-since-r1" class="self-link"></a></h2>
<ul>
<li><p>Refer to views::all Behavior of capture vs refer is similar to how views::all works over the expression it is given</p></li>
<li><p>Use wording ‘range adaptor object’ Match current working paper language</p></li>
</ul>
<h2 data-number="1.7" id="changes-since-r0"><span class="header-section-number">1.7</span> Changes since R0<a href="#changes-since-r0" class="self-link"></a></h2>
<ul>
<li>Remove customization point objects</li>
</ul>
<p>Removed views::maybe_has_value and views::maybe_value, instead requiring that the nullable type be dereferenceable and contextually convertible to bool.</p>
<ul>
<li>Concept <code class="sourceCode default">Nullable</code>, for exposition</li>
</ul>
<p>Concept Nullable, which is Readable and contextually convertible to bool</p>
<ul>
<li>Capture rvalues by decay copy</li>
</ul>
<p>Hold a copy when constructing a view over a nullable rvalue.</p>
<ul>
<li>Remove maybe_view as a specified type</li>
</ul>
<p>Introduced two exposition types, one safely holding a copy, the other referring to the nullable</p>
<h1 data-number="2" id="before-after-table"><span class="header-section-number">2</span> Before / After Table<a href="#before-after-table" class="self-link"></a></h1>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a>{</span>
<span id="cb1-2"><a href="#cb1-2"></a>    <span class="kw">auto</span>&amp;&amp; opt = possible_value();</span>
<span id="cb1-3"><a href="#cb1-3"></a>    <span class="cf">if</span> (opt) {</span>
<span id="cb1-4"><a href="#cb1-4"></a>        <span class="co">// a few dozen lines ...</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>        use(*opt); <span class="co">// is *opt OK ?</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>    }</span>
<span id="cb1-7"><a href="#cb1-7"></a>}</span></code></pre></div></td>
<td><div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="cf">for</span> (<span class="kw">auto</span>&amp;&amp; opt : views::maybe(possible_value())) {</span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a>    <span class="co">// a few dozen lines ...</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    use(opt); <span class="co">// opt is OK</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>}</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb3"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="bu">std::</span>optional o{<span class="dv">7</span>};</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="cf">if</span> (o) {</span>
<span id="cb3-3"><a href="#cb3-3"></a>    *o = <span class="dv">9</span>;</span>
<span id="cb3-4"><a href="#cb3-4"></a>    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;o=&quot;</span> &lt;&lt; *o &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb3-5"><a href="#cb3-5"></a>}</span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;o=&quot;</span> &lt;&lt; *o &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb4"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="bu">std::</span>optional o{<span class="dv">7</span>};</span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="cf">for</span> (<span class="kw">auto</span>&amp;&amp; i : views::maybe(<span class="bu">std::</span>ref(o))) {</span>
<span id="cb4-3"><a href="#cb4-3"></a>    i = <span class="dv">9</span>;</span>
<span id="cb4-4"><a href="#cb4-4"></a>    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb4-5"><a href="#cb4-5"></a>}</span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;o=&quot;</span> &lt;&lt; *o &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><div class="sourceCode" id="cb5"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="bu">std::</span>vector&lt;<span class="dt">int</span>&gt; v{<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>, <span class="dv">9</span>, <span class="dv">1</span>};</span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">auto</span> test = [](<span class="dt">int</span> i) -&gt; <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt; {</span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="cf">switch</span> (i) {</span>
<span id="cb5-4"><a href="#cb5-4"></a>      <span class="cf">case</span> <span class="dv">1</span>:</span>
<span id="cb5-5"><a href="#cb5-5"></a>      <span class="cf">case</span> <span class="dv">3</span>:</span>
<span id="cb5-6"><a href="#cb5-6"></a>      <span class="cf">case</span> <span class="dv">7</span>:</span>
<span id="cb5-7"><a href="#cb5-7"></a>      <span class="cf">case</span> <span class="dv">9</span>:</span>
<span id="cb5-8"><a href="#cb5-8"></a>    <span class="cf">return</span> i;</span>
<span id="cb5-9"><a href="#cb5-9"></a>      <span class="cf">default</span>:</span>
<span id="cb5-10"><a href="#cb5-10"></a>    <span class="cf">return</span> {};</span>
<span id="cb5-11"><a href="#cb5-11"></a>    }</span>
<span id="cb5-12"><a href="#cb5-12"></a>};</span>
<span id="cb5-13"><a href="#cb5-13"></a></span>
<span id="cb5-14"><a href="#cb5-14"></a><span class="kw">auto</span>&amp;&amp; r = v |</span>
<span id="cb5-15"><a href="#cb5-15"></a>    ranges::views::transform(test) |</span>
<span id="cb5-16"><a href="#cb5-16"></a>    ranges::views::filter([](<span class="kw">auto</span> x){<span class="cf">return</span> <span class="dt">bool</span>(x);}) |</span>
<span id="cb5-17"><a href="#cb5-17"></a>    ranges::views::transform([](<span class="kw">auto</span> x){<span class="cf">return</span> *x;}) |</span>
<span id="cb5-18"><a href="#cb5-18"></a>    ranges::views::transform(</span>
<span id="cb5-19"><a href="#cb5-19"></a>        [](<span class="dt">int</span> i) {</span>
<span id="cb5-20"><a href="#cb5-20"></a>            <span class="bu">std::</span>cout &lt;&lt; i;</span>
<span id="cb5-21"><a href="#cb5-21"></a>            <span class="cf">return</span> i;</span>
<span id="cb5-22"><a href="#cb5-22"></a>        });</span></code></pre></div></td>
<td><div class="sourceCode" id="cb6"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="bu">std::</span>vector&lt;<span class="dt">int</span>&gt; v{<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>, <span class="dv">9</span>, <span class="dv">1</span>};</span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="kw">auto</span> test = [](<span class="dt">int</span> i) -&gt; <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt; {</span>
<span id="cb6-3"><a href="#cb6-3"></a>    <span class="cf">switch</span> (i) {</span>
<span id="cb6-4"><a href="#cb6-4"></a>      <span class="cf">case</span> <span class="dv">1</span>:</span>
<span id="cb6-5"><a href="#cb6-5"></a>      <span class="cf">case</span> <span class="dv">3</span>:</span>
<span id="cb6-6"><a href="#cb6-6"></a>      <span class="cf">case</span> <span class="dv">7</span>:</span>
<span id="cb6-7"><a href="#cb6-7"></a>      <span class="cf">case</span> <span class="dv">9</span>:</span>
<span id="cb6-8"><a href="#cb6-8"></a>    <span class="cf">return</span> i;</span>
<span id="cb6-9"><a href="#cb6-9"></a>      <span class="cf">default</span>:</span>
<span id="cb6-10"><a href="#cb6-10"></a>    <span class="cf">return</span> {};</span>
<span id="cb6-11"><a href="#cb6-11"></a>    }</span>
<span id="cb6-12"><a href="#cb6-12"></a>};</span>
<span id="cb6-13"><a href="#cb6-13"></a></span>
<span id="cb6-14"><a href="#cb6-14"></a><span class="kw">auto</span>&amp;&amp; r = v |</span>
<span id="cb6-15"><a href="#cb6-15"></a>    ranges::views::transform(test) |</span>
<span id="cb6-16"><a href="#cb6-16"></a>    ranges::views::transform(views::maybe) |</span>
<span id="cb6-17"><a href="#cb6-17"></a>    ranges::views::join |</span>
<span id="cb6-18"><a href="#cb6-18"></a>    ranges::views::transform(</span>
<span id="cb6-19"><a href="#cb6-19"></a>        [](<span class="dt">int</span> i) {</span>
<span id="cb6-20"><a href="#cb6-20"></a>            <span class="bu">std::</span>cout &lt;&lt; i;</span>
<span id="cb6-21"><a href="#cb6-21"></a>            <span class="cf">return</span> i;</span>
<span id="cb6-22"><a href="#cb6-22"></a>        });</span></code></pre></div></td>
</tr>
</tbody>
</table>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>In writing range transformation it is useful to be able to lift a value into a view that is either empty or contains the value. For types that are <code class="sourceCode default">nullable</code>, constructing an empty view for disengaged values and providing a view to the underlying value is useful as well. The adapter <code class="sourceCode default">views::single</code> fills a similar purpose for non-nullable values, lifting a single value into a view, and <code class="sourceCode default">views::empty</code> provides a range of no values of a given type. The type <code class="sourceCode default">views::maybe</code> can be used to unify <code class="sourceCode default">single</code> and <code class="sourceCode default">empty</code> into a single type for further processing. This is in particuluar useful when translating list comprehensions.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt;&gt; v{</span>
<span id="cb7-2"><a href="#cb7-2"></a>  <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt;{<span class="dv">42</span>},</span>
<span id="cb7-3"><a href="#cb7-3"></a>  <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt;{},</span>
<span id="cb7-4"><a href="#cb7-4"></a>  <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt;{<span class="dv">6</span> * <span class="dv">9</span>}};</span>
<span id="cb7-5"><a href="#cb7-5"></a></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="kw">auto</span> r = views::join(views::transform(v, views::maybe));</span>
<span id="cb7-7"><a href="#cb7-7"></a></span>
<span id="cb7-8"><a href="#cb7-8"></a><span class="cf">for</span> (<span class="kw">auto</span> i : r) {</span>
<span id="cb7-9"><a href="#cb7-9"></a>    <span class="bu">std::</span>cout &lt;&lt; i; <span class="co">// prints 42 and 54</span></span>
<span id="cb7-10"><a href="#cb7-10"></a>}</span></code></pre></div>
<p>In addition to range transformation pipelines, <code class="sourceCode default">views::maybe</code> can be used in range based for loops, allowing the nullable value to not be dereferenced within the body. This is of small value in small examples in contrast to testing the nullable in an if statement, but with longer bodies the dereference is often far away from the test. Often the first line in the body of the <code class="sourceCode default">if</code> is naming the dereferenced nullable, and lifting the dereference into the for loop eliminates some boilerplate code, the same way that range based for loops do.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a>{</span>
<span id="cb8-2"><a href="#cb8-2"></a>    <span class="kw">auto</span>&amp;&amp; opt = possible_value();</span>
<span id="cb8-3"><a href="#cb8-3"></a>    <span class="cf">if</span> (opt) {</span>
<span id="cb8-4"><a href="#cb8-4"></a>        <span class="co">// a few dozen lines ...</span></span>
<span id="cb8-5"><a href="#cb8-5"></a>        use(*opt); <span class="co">// is *opt OK ?</span></span>
<span id="cb8-6"><a href="#cb8-6"></a>    }</span>
<span id="cb8-7"><a href="#cb8-7"></a>}</span>
<span id="cb8-8"><a href="#cb8-8"></a></span>
<span id="cb8-9"><a href="#cb8-9"></a><span class="cf">for</span> (<span class="kw">auto</span>&amp;&amp; opt : views::maybe(possible_value())) {</span>
<span id="cb8-10"><a href="#cb8-10"></a>    <span class="co">// a few dozen lines ...</span></span>
<span id="cb8-11"><a href="#cb8-11"></a>    use(opt); <span class="co">// opt is OK</span></span>
<span id="cb8-12"><a href="#cb8-12"></a>}</span></code></pre></div>
<p>The view can be on a <code class="sourceCode default">std::reference_wrapper</code>, allowing the underlying nullable to be modified:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="bu">std::</span>optional o{<span class="dv">7</span>};</span>
<span id="cb9-2"><a href="#cb9-2"></a><span class="cf">for</span> (<span class="kw">auto</span>&amp;&amp; i : views::maybe(<span class="bu">std::</span>ref(o))) {</span>
<span id="cb9-3"><a href="#cb9-3"></a>    i = <span class="dv">9</span>;</span>
<span id="cb9-4"><a href="#cb9-4"></a>    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb9-5"><a href="#cb9-5"></a>}</span>
<span id="cb9-6"><a href="#cb9-6"></a><span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;o=&quot;</span> &lt;&lt; *o &lt;&lt; <span class="st">&quot; prints 9</span><span class="sc">\n</span><span class="st">&quot;</span>;</span></code></pre></div>
<p>Of course, if the nullable is empty, there is nothing in the view to modify.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">auto</span> oe = <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt;{};</span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="cf">for</span> (<span class="dt">int</span> i : views::maybe(<span class="bu">std::</span>ref(oe)))</span>
<span id="cb10-3"><a href="#cb10-3"></a>    <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>; <span class="co">// does not print</span></span></code></pre></div>
<p>Converting an optional type into a view can make APIs that return optional types, such a lookup operations, easier to work with in range pipelines.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="bu">std::</span>unordered_set&lt;<span class="dt">int</span>&gt; set{<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">7</span>, <span class="dv">9</span>};</span>
<span id="cb11-2"><a href="#cb11-2"></a></span>
<span id="cb11-3"><a href="#cb11-3"></a><span class="kw">auto</span> flt = [=](<span class="dt">int</span> i) -&gt; <span class="bu">std::</span>optional&lt;<span class="dt">int</span>&gt; {</span>
<span id="cb11-4"><a href="#cb11-4"></a>    <span class="cf">if</span> (set.contains(i))</span>
<span id="cb11-5"><a href="#cb11-5"></a>        <span class="cf">return</span> i;</span>
<span id="cb11-6"><a href="#cb11-6"></a>    <span class="cf">else</span></span>
<span id="cb11-7"><a href="#cb11-7"></a>        <span class="cf">return</span> {};</span>
<span id="cb11-8"><a href="#cb11-8"></a>};</span>
<span id="cb11-9"><a href="#cb11-9"></a></span>
<span id="cb11-10"><a href="#cb11-10"></a><span class="cf">for</span> (<span class="kw">auto</span> i : ranges::iota_view{<span class="dv">1</span>, <span class="dv">10</span>} | ranges::views::transform(flt)) {</span>
<span id="cb11-11"><a href="#cb11-11"></a>    <span class="cf">for</span> (<span class="kw">auto</span> j : views::maybe(i)) {</span>
<span id="cb11-12"><a href="#cb11-12"></a>        <span class="cf">for</span> (<span class="kw">auto</span> k : ranges::iota_view(<span class="dv">0</span>, j))</span>
<span id="cb11-13"><a href="#cb11-13"></a>            <span class="bu">std::</span>cout &lt;&lt; <span class="ch">&#39;</span><span class="sc">\a</span><span class="ch">&#39;</span>;</span>
<span id="cb11-14"><a href="#cb11-14"></a>        <span class="bu">std::</span>cout &lt;&lt; <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb11-15"><a href="#cb11-15"></a>    }</span>
<span id="cb11-16"><a href="#cb11-16"></a>}</span>
<span id="cb11-17"><a href="#cb11-17"></a></span>
<span id="cb11-18"><a href="#cb11-18"></a><span class="co">// Produce 1 ring, 3 rings, 7 rings, and 9 rings</span></span></code></pre></div>
<h1 data-number="4" id="lazy-monadic-pythagorean-triples"><span class="header-section-number">4</span> Lazy monadic pythagorean triples<a href="#lazy-monadic-pythagorean-triples" class="self-link"></a></h1>
<p>Eric Niebler’s pythagorean triple example, using current C++ and proposed views::maybe.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a></span>
<span id="cb12-2"><a href="#cb12-2"></a><span class="co">// &quot;and_then&quot; creates a new view by applying a</span></span>
<span id="cb12-3"><a href="#cb12-3"></a><span class="co">// transformation to each element in an input</span></span>
<span id="cb12-4"><a href="#cb12-4"></a><span class="co">// range, and flattening the resulting range of</span></span>
<span id="cb12-5"><a href="#cb12-5"></a><span class="co">// ranges. A.k.a. bind</span></span>
<span id="cb12-6"><a href="#cb12-6"></a><span class="co">// (This uses one syntax for constrained lambdas</span></span>
<span id="cb12-7"><a href="#cb12-7"></a><span class="co">// in C++20.)</span></span>
<span id="cb12-8"><a href="#cb12-8"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> and_then = [](<span class="kw">auto</span>&amp;&amp; r, <span class="kw">auto</span> fun) {</span>
<span id="cb12-9"><a href="#cb12-9"></a>    <span class="cf">return</span> <span class="kw">decltype</span>(r)(r) | <span class="bu">std::</span>ranges<span class="bu">::</span>views<span class="bu">::</span>transform(<span class="bu">std::</span>move(fun)) |</span>
<span id="cb12-10"><a href="#cb12-10"></a>           <span class="bu">std::</span>ranges<span class="bu">::</span>views<span class="bu">::</span>join;</span>
<span id="cb12-11"><a href="#cb12-11"></a>};</span>
<span id="cb12-12"><a href="#cb12-12"></a></span>
<span id="cb12-13"><a href="#cb12-13"></a><span class="co">// &quot;yield_if&quot; takes a bool and a value and</span></span>
<span id="cb12-14"><a href="#cb12-14"></a><span class="co">// returns a view of zero or one elements.</span></span>
<span id="cb12-15"><a href="#cb12-15"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> yield_if = [](<span class="dt">bool</span> b, <span class="kw">auto</span> x) {</span>
<span id="cb12-16"><a href="#cb12-16"></a>    <span class="cf">return</span> b ? maybe_view{<span class="bu">std::</span>move(x)}</span>
<span id="cb12-17"><a href="#cb12-17"></a>             : maybe_view&lt;<span class="kw">decltype</span>(x)&gt;{};</span>
<span id="cb12-18"><a href="#cb12-18"></a>};</span>
<span id="cb12-19"><a href="#cb12-19"></a></span>
<span id="cb12-20"><a href="#cb12-20"></a><span class="dt">void</span> print_triples() {</span>
<span id="cb12-21"><a href="#cb12-21"></a>    <span class="kw">using</span> <span class="bu">std::</span>ranges<span class="bu">::</span>views<span class="bu">::</span>iota;</span>
<span id="cb12-22"><a href="#cb12-22"></a>    <span class="kw">auto</span> triples = and_then(iota(<span class="dv">1</span>), [](<span class="dt">int</span> z) {</span>
<span id="cb12-23"><a href="#cb12-23"></a>        <span class="cf">return</span> and_then(iota(<span class="dv">1</span>, z + <span class="dv">1</span>), [=](<span class="dt">int</span> x) {</span>
<span id="cb12-24"><a href="#cb12-24"></a>            <span class="cf">return</span> and_then(iota(x, z + <span class="dv">1</span>), [=](<span class="dt">int</span> y) {</span>
<span id="cb12-25"><a href="#cb12-25"></a>                <span class="cf">return</span> yield_if(x * x + y * y == z * z,</span>
<span id="cb12-26"><a href="#cb12-26"></a>                                <span class="bu">std::</span>make_tuple(x, y, z));</span>
<span id="cb12-27"><a href="#cb12-27"></a>            });</span>
<span id="cb12-28"><a href="#cb12-28"></a>        });</span>
<span id="cb12-29"><a href="#cb12-29"></a>    });</span>
<span id="cb12-30"><a href="#cb12-30"></a></span>
<span id="cb12-31"><a href="#cb12-31"></a>    <span class="co">// Display the first 10 triples</span></span>
<span id="cb12-32"><a href="#cb12-32"></a>    <span class="cf">for</span> (<span class="kw">auto</span> triple : triples | <span class="bu">std::</span>ranges<span class="bu">::</span>views<span class="bu">::</span>take(<span class="dv">10</span>)) {</span>
<span id="cb12-33"><a href="#cb12-33"></a>        <span class="bu">std::</span>cout &lt;&lt; <span class="ch">&#39;(&#39;</span> &lt;&lt; <span class="bu">std::</span>get&lt;<span class="dv">0</span>&gt;(triple) &lt;&lt; <span class="ch">&#39;,&#39;</span> &lt;&lt; <span class="bu">std::</span>get&lt;<span class="dv">1</span>&gt;(triple)</span>
<span id="cb12-34"><a href="#cb12-34"></a>                  &lt;&lt; <span class="ch">&#39;,&#39;</span> &lt;&lt; <span class="bu">std::</span>get&lt;<span class="dv">2</span>&gt;(triple) &lt;&lt; <span class="ch">&#39;)&#39;</span> &lt;&lt; <span class="ch">&#39;</span><span class="sc">\n</span><span class="ch">&#39;</span>;</span>
<span id="cb12-35"><a href="#cb12-35"></a>    }</span>
<span id="cb12-36"><a href="#cb12-36"></a>}</span></code></pre></div>
<p>The implementation of yield_if is essentially the type unification of <code class="sourceCode default">single</code> and <code class="sourceCode default">empty</code> into <code class="sourceCode default">maybe</code>, returning an empty on false, and a range containing one value on true.</p>
<h1 data-number="5" id="proposal"><span class="header-section-number">5</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>Add a range adaptor object <code class="sourceCode default">views::maybe</code>, returning a view over an object, capturing by value. Dor <code class="sourceCode default">nullable</code> objects, provide a zero size range for objects which are disengaged. A <em><code class="sourceCode default">nullable</code></em> object is one that is both contextually convertible to bool and for which the type produced by dereferencing is an equality preserving object. Non void pointers, <code class="sourceCode default">std::optional</code>, and the proposed <code class="sourceCode default">expected</code> <span class="citation" data-cites="P0323R9">[<a href="#ref-P0323R9" role="doc-biblioref">P0323R9</a>]</span> types all models <em><code class="sourceCode default">nullable</code></em>. Function pointers do not, as functions are not objects. Iterators do not generally model <em><code class="sourceCode default">nullable</code></em>, as they are not required to be contextually convertible to bool.</p>
<h1 data-number="6" id="design"><span class="header-section-number">6</span> Design<a href="#design" class="self-link"></a></h1>
<p>The basis of the design is to hybridize <code class="sourceCode default">views::single</code> and <code class="sourceCode default">views::empty</code>. If the view is over a value that is not <code class="sourceCode default">nullable</code> it is like a single view if constructed with a value, or is of size zero otherwise. For <code class="sourceCode default">nullable</code> types, if the underlying object claims to hold a value, as determined by checking if the object when converted to bool is true, <code class="sourceCode default">begin</code> and <code class="sourceCode default">end</code> of the view are equivalent to the address of the held value within the underlying object and one past the underlying object. If the underlying object does not have a value, <code class="sourceCode default">begin</code> and <code class="sourceCode default">end</code> return <code class="sourceCode default">nullptr</code>.</p>
<h1 data-number="7" id="borrowed-range"><span class="header-section-number">7</span> Borrowed Range<a href="#borrowed-range" class="self-link"></a></h1>
<p>A <code class="sourceCode default">borrowed_range</code> is one whose iterators cannot be invalidated by ending the lifetime of the range. For views::maybe, the iterators are T*, where T is essentially the type of the dereferenced nullable. For raw pointers and <code class="sourceCode default">reference_wrapper</code> over nullable types, the iterator for <code class="sourceCode default">maybe_view</code> points directly to the underlying object, and thus matches the semantics of <code class="sourceCode default">borrowed_range</code>. This means that <code class="sourceCode default">maybe_view</code> is conditionally borrowed. A <code class="sourceCode default">maybe_view&lt;shared_ptr&gt;</code>, however, is not a borrowed range, as it participates in ownership of the shared_ptr and might invalidate the iterators if upon the end of its lifetime it is the last owner.</p>
<p>An example of code that is enabled by borrowed ranges, if unlikely code:</p>
<pre class="c+++"><code>num = 42;
int k = *std::ranges::find(views::maybe(&amp;num), num);</code></pre>
<p>Providing the facility is not a signficant cost, and conveys the semantics correctly, even if the simple examples are not hugely motivating. Particularly as there is no real implementation impact, other than providing template variable specializations for <code class="sourceCode default">enable_borrowed_range</code>.</p>
<h1 data-number="8" id="list-comprehension-desugaring"><span class="header-section-number">8</span> List Comprehension Desugaring<a href="#list-comprehension-desugaring" class="self-link"></a></h1>
<p>The case for having maybe_view available is seen in desugaring list comprehensions, where they naturally show up in guard clauses.</p>
<p>Looking at Haskell for a <a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/monad_comprehensions.html">formal lowering of comprehensions</a>:</p>
<p>We write <code class="sourceCode default">Desugar[ e | Q]</code> to mean the desugaring of the comprehension <code class="sourceCode default">[ e | Q]</code></p>
<p>Expressions: <code class="sourceCode default">e</code></p>
<p>Lists of qualifiers: <code class="sourceCode default">Q</code>,<code class="sourceCode default">R</code>,<code class="sourceCode default">S</code></p>
<p>– Basic forms</p>
<p><code class="sourceCode default">Desugar[ e | ]</code> = <code class="sourceCode default">return e</code></p>
<p><code class="sourceCode default">Desugar[ e | p &lt;- e, Q ]</code> = <code class="sourceCode default">e &gt;&gt;= \p -&gt; Desugar[ e | Q ]</code></p>
<p><code class="sourceCode default">Desugar[ e | e, Q ]</code> = <code class="sourceCode default">guard e &gt;&gt; \p -&gt; Desugar[ e | Q ]</code></p>
<p>Where:</p>
<p><code class="sourceCode default">&gt;&gt;=</code> is the normal bind operator</p>
<p><code class="sourceCode default">(&gt;&gt;=) :: m a -&gt; (a -&gt; m b) -&gt; m b</code></p>
<p>equivalent to</p>
<p><code class="sourceCode default">\x -&gt; join (fmap f x)</code></p>
<p>See the <code class="sourceCode default">abd_then</code> function above.</p>
<p><code class="sourceCode default">&gt;&gt;</code> is a bind that sequences but discards the left side</p>
<p><code class="sourceCode default">(&gt;&gt;) :: m a -&gt; m b -&gt; m b</code></p>
<p>defined as</p>
<p><code class="sourceCode default">k &gt;&gt; f =     k &gt;&gt;= (\_ -&gt; f)</code></p>
<p><code class="sourceCode default">guard</code> has the type <code class="sourceCode default">guard :: Alternative f =&gt; Bool -&gt; f ()</code> and is defined as</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1"></a>guard <span class="dt">True</span>  <span class="ot">=</span> <span class="fu">return</span> ()</span>
<span id="cb14-2"><a href="#cb14-2"></a>guard <span class="dt">False</span> <span class="ot">=</span> empty</span></code></pre></div>
<p>See the <code class="sourceCode default">yield_if</code> above.</p>
<p><code class="sourceCode default">return</code> is a constructor for a monad over T, lifting a value into the monad. <code class="sourceCode default">return :: Monad m =&gt; t -&gt; m t</code></p>
<p>The pythagorean triple example above is a typical hand desugaring of a list comprehension.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1"></a> [(x,y,z) | z &lt;- [1..x], y &lt;- [1..z], x &lt;- [1..y], x*x + y*y== z*z]</span></code></pre></div>
<p>The <code class="sourceCode default">guard</code> function functions as a filter. It’s usually possible to rewrite the guard and join into a filter function, but fusing the guard conditions may not be straightforward.</p>
<h1 data-number="9" id="implementation"><span class="header-section-number">9</span> Implementation<a href="#implementation" class="self-link"></a></h1>
<p>A publically available implementation at <a href="https://github.com/steve-downey/view_maybe" class="uri">https://github.com/steve-downey/view_maybe</a> based on the Ranges implementation in libstdc++ . There are no particular implementation difficulties or tricks. The declarations are essentially what is quoted in the Wording section and the implementations are described as <em>Effects</em>.</p>
<p><a href="https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGe1wAyeAyYAHI%2BAEaYxCDSAA6oCoRODB7evnoJSY4CQSHhLFEx0naYDilCBEzEBGk%2Bfly2mPY5DJXVBHlhkdGxtlU1dRmNCgOdwd2FvZIAlLaoXsTI7BzmAMzByN5YANQma24IBARxCiAA9OfETADuAHTAhAheEV5KS7KMBHdoLOejmAAbpgALToVA3EIAT3OgLwmBuAH0WEwoVFziiAcR/ktYfCkSi0Zg8QjkaioncEPtsCYNABBWkMswbBhbLy7fZuYEOEjUxmM0boEAgVBxVpiTnBAjUnZZJIReiIwFiLyYCAzfZWemA1B4dA7N5qqU7AgatZauk6vU7KL8YiYDTq/kAdgtO3de1djI9OyYXiI5gAbEGdqKCHs1gARWWJeWK5XeNVmt0evBUHYQMMzPb0n0mL25n0ey6%2BnZUBE7cEAL0YO1oEwUOzuze9RfdhogACos5qdiW8I3u2KdgB5ADSEYAYq33fnIzPPfP6XP%2BdrdfqmFQCNFHdmXRa7Rm/QGzMHT6HhyAdnCEWcQISohA5XgFZglSqkzM98uC3SfSWmDLCtq1resQkbZs7gXDse3NPtzgvcMB1HMcXSXBlnXQxkrX1W0SEwLh1RzDCLUFYUwxSMRQ3zCxnRXc1GTTDNUG/EiF27CNowATk1BcyJQBZw05Tk9jMMxUH2ecxIjNwRI44SDlEsxZWIKVGx4gBWNwGHMMxeJ/dD%2BLQf0ZJE3SJKjXTTMU%2BSDjM6S4lUwR1JMLSdLE/SMKwtdrU3bdiEI1iaIFAghRFMVKNoajXTozDPMPCBjwk08QzwHYrxvG47wfNV%2BPtKhMy/ILfx9NLJJ2HiGMLd0jME6y3CUvBJKshSGrKuzFKsxy1Iq1ztN0zyV3pWqTNapSLKk5Sxts2TOocpyCBctyBqqrzV0tdcbUwO1MDMJ0f1I0LhW5IhiElQQZUBGizFIHY1lu6Qdg027A1u51boADlurjbq4eiLSSk1MFGTi9g0qwNMjCBjTwbMQRlfiKIECUDilGVguqnYFBuQhkAQDNYc9FMfVEJQdi4EAF3dUnMDuynMeppgyedem/yLGmKtZn17QIRYGB2JrVrbLAqD9WgCC5j0eb5on/oXIa1tWxkkqDENiFBwFPVkzHriMYHjvxO8CF1hQ7RYCBt1GPdnW1tn3V14B9ZATK7xocXoggVyIahwHVA1V1peIfmIlQTwID93jMOt23ucMR27xd4VjcMU2SHNr3XJ9/1UB2COA8wXmg52TtVEjyNo4XB2ncTkBk4YVPiHThmPQzyHocEAXreJtsPRGoSOrazye6LQP%2BcF7u8yj%2BKSCPbPVfPNKr2ILu5eXAz1pw30t2iPaNQOkKwpO3lUYutZsGva7bvunZHuenZXp2d6di%2BirftXulAct/vo1bqGYbhhGR1wriloOdaUZ9ZaY2xrjfG0MV7Nw5hTKmOwOZrEliTJmtMWbII5lxdBOxR4CyHkWEWYsJaVwLjLYKcUhYtziuvJW9IVYpXPOrcqmt8wxylnHauhsk4mzNhbYGpotaVx4QnPhtcBFpwgDXHKFcdbiINreYU2hdT804WIvWEiVFSJToI5Bs5waZ3bkheBdth5YyAcZfus1B60MsQQyhRdx6GMXMmRkCVmFnkDALdKBCV40ItHODgcxaCcA0rwPwHAtCkFQJwWSlhrBYwWEsWm6weCkAljE0JcwECYCYFgGI6pSAAGsQAaQ0PoTgkgomaF4PEjgvAzhVOyVoOYcBYAwEQAJFgcQ6DRHIJQX4/T6AxGAAoZgpwECoAIHwOg/kzgQAiPU0gERgjVChJwTJvw2CCBHAwWgWycmkCwCiIw4gTn4HtOUYEZwTmYFUGUf0KxYlSmaKs%2BsERrjEChB4LA2zeDGzwCwQFcwqAGAmQANXxCOOIjBAUyEECIMQ7ApBIvkEoNQqzdCNAMEYFA1hrD6BfGcWAzA2AoBYMgUYtAbrAhiMbLwDBSlfjiRFAQ9yQQgkFJJUwSTLBmA0DsEEI41jNOaGUVoLgGDuE8PUfwsqugFCKJkRIyQBBDAaKQLIGqGDKp6DEEYkrygCHaIMeVwwmgtAqGMA1UwjX9A6FqvQowOj2tVVwOYChUnLD0MbTAKweBhIiXUk5jTVAfUDCCQMkgdjAGQMgDMTKWXZggIkqwlhbq4EIDPDJt0PB9IGWw5kXqgX1LZeUyp1SOC1NIKC6t0TYmNOaSAVpFbSCdJ6YJOI/ohkQEwPgU6eo9D8GRaIcQ6Kx2YpUOoE5uLSA3GuHEMFNbImkCbQ0zgI5/S9vDKgdMkbo2xvjYm5NxBmWsozIW0Z0RRJrDLVkiteSClFMoCG2tvAG1VM3XEzgrb205MrRUqp4SODio3asltT6gMfrMGG5t/6YPtLmAypIzhJBAA%3D">Compiler Explorer Link to Before/After Examples</a></p>
<h1 data-number="10" id="wording"><span class="header-section-number">10</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="10.1" id="synopsis"><span class="header-section-number">10.1</span> Synopsis<a href="#synopsis" class="self-link"></a></h2>
<p>Modify 26.2 Header <ranges> synopsis</p>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb2"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1"></a>  // <a href="https://wg21.link/range.maybe">[range.maybe]</a>, maybe view</span>
<span id="cb2-2"><a href="#cb2-2"></a>  template&lt;copy_constructible T&gt;</span>
<span id="cb2-3"><a href="#cb2-3"></a>    requires <em>see below</em></span>
<span id="cb2-4"><a href="#cb2-4"></a>  class maybe_view;</span>
<span id="cb2-5"><a href="#cb2-5"></a></span>
<span id="cb2-6"><a href="#cb2-6"></a>  template &lt;typename T&gt;</span>
<span id="cb2-7"><a href="#cb2-7"></a>  constexpr inline bool enable_borrowed_range&lt;maybe_view&lt;T*&gt;&gt; = true;</span>
<span id="cb2-8"><a href="#cb2-8"></a></span>
<span id="cb2-9"><a href="#cb2-9"></a>  template &lt;typename T&gt;</span>
<span id="cb2-10"><a href="#cb2-10"></a>  constexpr inline bool enable_borrowed_range&lt;maybe_view&lt;reference_wrapper&lt;T&gt;&gt;&gt; = true;</span>
<span id="cb2-11"><a href="#cb2-11"></a></span>
<span id="cb2-12"><a href="#cb2-12"></a>  namespace views { inline constexpr <em>unspecified</em> maybe = <em>unspecified</em>; }</span></code></pre></div>

</div>
<h2 data-number="10.2" id="maybe-view-range.maybe"><span class="header-section-number">10.2</span> Maybe View <a href="https://wg21.link/range.maybe">[range.maybe]</a><a href="#maybe-view-range.maybe" class="self-link"></a></h2>
<h3 data-number="10.2.1" id="overview"><span class="header-section-number">10.2.1</span> Overview<a href="#overview" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> <code class="sourceCode default">maybe_view</code> produces a <code class="sourceCode default">view</code> over a <em><code class="sourceCode default">nullable</code></em> that is either empty if the <em><code class="sourceCode default">nullable</code></em> is empty, or provides access to the contents of the <em><code class="sourceCode default">nullable</code></em> object.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> The name <code class="sourceCode default">views::maybe</code> denotes a customization point object ([customization.point.object]). For some subexpression <code class="sourceCode default">E</code>, the expression <code class="sourceCode default">views::maybe(E)</code> is expression-equivalent to:</p>
<ul>
<li><code class="sourceCode default">maybe_view{E}</code>, the <code class="sourceCode default">view</code> specified below, if the expression is well formed, where <code class="sourceCode default">decay-copy(E)</code> is moved into the <code class="sourceCode default">maybe_view</code></li>
<li>otherwise <code class="sourceCode default">views::maybe(E)</code> is ill-formed.</li>
</ul>
<p>[Note: Whenever <code class="sourceCode default">views::maybe(E)</code> is a valid expression, it is a prvalue whose type models <code class="sourceCode default">view</code>. — end note ]</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> [ <em>Example:</em></p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a>  optional o<span class="op">{</span><span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb3-2"><a href="#cb3-2"></a>  maybe_view m<span class="op">{</span>o<span class="op">}</span>;</span>
<span id="cb3-3"><a href="#cb3-3"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">:</span> m<span class="op">)</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>    cout <span class="op">&lt;&lt;</span> i;        <span class="co">// prints 4</span></span></code></pre></div>
<p>— <em>end example</em> ]</p>
<h3 data-number="10.2.2" id="concept-nullable"><span class="header-section-number">10.2.2</span> Concept <em><code class="sourceCode default">nullable</code></em><a href="#concept-nullable" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> Types that:</p>
<ul>
<li>are contextually convertible to <code class="sourceCode default">bool</code></li>
<li>are dereferenceable</li>
<li>have const references which are dereferenceable</li>
<li>the <code class="sourceCode default">iter_reference_t</code> of the type and the <code class="sourceCode default">iter_reference_t</code> of the const type, will :
<ul>
<li>satisfy <code class="sourceCode default">is_lvalue_reference</code></li>
<li>satisfy <code class="sourceCode default">is_object</code> when the reference is removed</li>
<li>for const pointers to the referred to types, satisfy <code class="sourceCode default">convertible_to</code></li>
</ul></li>
<li>or are a <code class="sourceCode default">reference_wrapper</code> around a type that satifies <em><code class="sourceCode default">nullable</code></em></li>
</ul>
<p>model the exposition only <em><code class="sourceCode default">nullable</code></em> concept</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> Given a value <code class="sourceCode default">i</code> of type <code class="sourceCode default">I</code>, <code class="sourceCode default">I</code> models <em><code class="sourceCode default">nullable</code></em> only if the expression <code class="sourceCode default">*i</code> is equality-preserving. [ Note: The expression <code class="sourceCode default">*i</code> is required to be valid via the exposition-only <em><code class="sourceCode default">nullable</code></em> concept). — end note ]</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> For convienence, the exposition-only <code class="sourceCode default"><em>is-reference-wrapper-v</em></code> is used below.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="co">// For Exposition</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>    <span class="kw">struct</span> is_reference_wrapper <span class="op">:</span> false_type <span class="op">{}</span>;</span>
<span id="cb4-4"><a href="#cb4-4"></a></span>
<span id="cb4-5"><a href="#cb4-5"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb4-6"><a href="#cb4-6"></a>    <span class="kw">struct</span> is_reference_wrapper<span class="op">&lt;</span>reference_wrapper<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">:</span> true_type <span class="op">{}</span>;</span>
<span id="cb4-7"><a href="#cb4-7"></a></span>
<span id="cb4-8"><a href="#cb4-8"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb4-9"><a href="#cb4-9"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_reference_wrapper_v</span>
<span id="cb4-10"><a href="#cb4-10"></a>        <span class="op">=</span> is_reference_wrapper<span class="op">&lt;</span>T<span class="op">&gt;::</span>value;</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="co">// For Exposition</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Ref, <span class="kw">class</span> ConstRef<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="kw">concept</span> readable_references <span class="op">=</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>    is_lvalue_reference_v<span class="op">&lt;</span>Ref<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>    is_object_v<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>Ref<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>    is_lvalue_reference_v<span class="op">&lt;</span>ConstRef<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-7"><a href="#cb5-7"></a>    is_object_v<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>ConstRef<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-8"><a href="#cb5-8"></a>    convertible_to<span class="op">&lt;</span>add_pointer_t<span class="op">&lt;</span>ConstRef<span class="op">&gt;</span>,</span>
<span id="cb5-9"><a href="#cb5-9"></a>                   <span class="kw">const</span> remove_reference_t<span class="op">&lt;</span>Ref<span class="op">&gt;*&gt;</span>;</span>
<span id="cb5-10"><a href="#cb5-10"></a></span>
<span id="cb5-11"><a href="#cb5-11"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb5-12"><a href="#cb5-12"></a><span class="kw">concept</span> nullable <span class="op">=</span></span>
<span id="cb5-13"><a href="#cb5-13"></a>    is_object_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-14"><a href="#cb5-14"></a>    <span class="kw">requires</span><span class="op">(</span>T<span class="op">&amp;</span> t, <span class="kw">const</span> T<span class="op">&amp;</span> ct<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-15"><a href="#cb5-15"></a>        <span class="dt">bool</span><span class="op">(</span>ct<span class="op">)</span>; <span class="co">// Contextually bool</span></span>
<span id="cb5-16"><a href="#cb5-16"></a>        <span class="op">*</span>t; <span class="co">// T&amp; is deferenceable</span></span>
<span id="cb5-17"><a href="#cb5-17"></a>        <span class="op">*</span>ct; <span class="co">// const T&amp; is deferenceable</span></span>
<span id="cb5-18"><a href="#cb5-18"></a>    <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19"></a>    <span class="op">&amp;&amp;</span> readable_references<span class="op">&lt;</span>iter_reference_t<span class="op">&lt;</span>T<span class="op">&gt;</span>,        <span class="co">// Ref</span></span>
<span id="cb5-20"><a href="#cb5-20"></a>                           iter_reference_t<span class="op">&lt;</span><span class="kw">const</span> T<span class="op">&gt;&gt;</span>; <span class="co">// ConstRef</span></span>
<span id="cb5-21"><a href="#cb5-21"></a></span>
<span id="cb5-22"><a href="#cb5-22"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb5-23"><a href="#cb5-23"></a><span class="kw">concept</span> wrapped_nullable <span class="op">=</span></span>
<span id="cb5-24"><a href="#cb5-24"></a>    <em>is-reference-wrapper-v</em><span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb5-25"><a href="#cb5-25"></a>    <span class="op">&amp;&amp;</span> <em>nullable</em><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">::</span>type<span class="op">&gt;</span>;</span></code></pre></div>
<h3 data-number="10.2.3" id="class-template-maybe_view"><span class="header-section-number">10.2.3</span> Class template <em>maybe_view</em><a href="#class-template-maybe_view" class="self-link"></a></h3>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2"></a>  <span class="kw">template</span> <span class="op">&lt;</span>copy_constructible Maybe<span class="op">&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>    <span class="kw">requires</span> <span class="op">(</span><em>nullable</em><span class="op">&lt;</span>Maybe<span class="op">&gt;</span> <span class="op">||</span> <em>wrapped-nullable</em><span class="op">&lt;</span>Maybe<span class="op">&gt;)</span></span>
<span id="cb6-4"><a href="#cb6-4"></a>  <span class="kw">class</span> maybe_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op">&lt;</span>maybe_view<span class="op">&lt;</span>Maybe<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb6-5"><a href="#cb6-5"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb6-6"><a href="#cb6-6"></a>    <span class="kw">using</span> T <span class="op">=</span> <span class="co">/* <em>see below</em> */</span></span>
<span id="cb6-7"><a href="#cb6-7"></a>    <em>copyable-box</em><span class="op">&lt;</span>Maybe<span class="op">&gt;</span> value_; <span class="co">// exposition only (see [range.copy.wrap])</span></span>
<span id="cb6-8"><a href="#cb6-8"></a></span>
<span id="cb6-9"><a href="#cb6-9"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb6-10"><a href="#cb6-10"></a>    <span class="kw">constexpr</span> maybe_view<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb6-11"><a href="#cb6-11"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> maybe_view<span class="op">(</span>Maybe <span class="kw">const</span><span class="op">&amp;</span> maybe<span class="op">)</span>;</span>
<span id="cb6-12"><a href="#cb6-12"></a></span>
<span id="cb6-13"><a href="#cb6-13"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> maybe_view<span class="op">(</span>Maybe<span class="op">&amp;&amp;</span> maybe<span class="op">)</span>;</span>
<span id="cb6-14"><a href="#cb6-14"></a></span>
<span id="cb6-15"><a href="#cb6-15"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb6-16"><a href="#cb6-16"></a>    <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>Maybe, Args<span class="op">...&gt;</span></span>
<span id="cb6-17"><a href="#cb6-17"></a>    <span class="kw">constexpr</span> maybe_view<span class="op">(</span>in_place_t, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span>;</span>
<span id="cb6-18"><a href="#cb6-18"></a></span>
<span id="cb6-19"><a href="#cb6-19"></a>    <span class="kw">constexpr</span> T<span class="op">*</span>       begin<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-20"><a href="#cb6-20"></a>    <span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> begin<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-21"><a href="#cb6-21"></a>    <span class="kw">constexpr</span> T<span class="op">*</span>       end<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-22"><a href="#cb6-22"></a>    <span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> end<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-23"><a href="#cb6-23"></a></span>
<span id="cb6-24"><a href="#cb6-24"></a>    <span class="kw">constexpr</span> <span class="dt">size_t</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-25"><a href="#cb6-25"></a></span>
<span id="cb6-26"><a href="#cb6-26"></a>    <span class="kw">constexpr</span> T<span class="op">*</span> data<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-27"><a href="#cb6-27"></a>    <span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> data<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-28"><a href="#cb6-28"></a>  <span class="op">}</span>;</span>
<span id="cb6-29"><a href="#cb6-29"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="co">// For Exposition</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>    <span class="kw">using</span> T <span class="op">=</span> std<span class="op">::</span>remove_reference_t<span class="op">&lt;</span></span>
<span id="cb7-3"><a href="#cb7-3"></a>        iter_reference_t<span class="op">&lt;</span><span class="kw">typename</span> unwrap_reference_t<span class="op">&lt;</span>Maybe<span class="op">&gt;&gt;&gt;</span>;</span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> maybe_view<span class="op">(</span>Maybe <span class="kw">const</span><span class="op">&amp;</span> maybe<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> <em>Effects</em>: Initializes value_ with maybe.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> maybe_view<span class="op">(</span>Maybe<span class="op">&amp;&amp;</span> maybe<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> <em>Effects</em>: Initializes value_ with <code class="sourceCode default">std::move(maybe)</code>.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="kw">constexpr</span> maybe_view<span class="op">(</span>in_place_t, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> <em>Effects</em>: Initializes value_ as if by <code class="sourceCode default">value_{in_place, forward&lt;Args&gt;(args)...}</code>.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">constexpr</span> T<span class="op">*</span> begin<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb11-2"><a href="#cb11-2"></a><span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> begin<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> <em>Effects</em>: Equivalent to: <code class="sourceCode default">return data();</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">constexpr</span> T<span class="op">*</span> end<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb12-2"><a href="#cb12-2"></a><span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> end<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span> <em>Effects</em>: Equivalent to: <code class="sourceCode default">return data() + size();</code>.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> size<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span> <em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></a>        <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>is-reference-wrapper-v</em><span class="op">&lt;</span>Maybe<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2"></a>            <span class="cf">return</span> <span class="dt">bool</span><span class="op">(</span>value_<span class="op">.</span>get<span class="op">().</span>get<span class="op">())</span>;</span>
<span id="cb14-3"><a href="#cb14-3"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4"></a>            <span class="cf">return</span> <span class="dt">bool</span><span class="op">(</span>value_<span class="op">.</span>get<span class="op">())</span>;</span>
<span id="cb14-5"><a href="#cb14-5"></a>        <span class="op">}</span></span></code></pre></div>
<p>🔗</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">constexpr</span> T<span class="op">*</span> data<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span> <em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a>        Maybe<span class="op">&amp;</span> m <span class="op">=</span> <span class="op">*</span>value_;</span>
<span id="cb16-2"><a href="#cb16-2"></a>        <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>is-reference-wrapper-v</em><span class="op">&lt;</span>Maybe<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3"></a>            <span class="cf">return</span> m<span class="op">.</span>get<span class="op">()</span> <span class="op">?</span> addressof<span class="op">(*(</span>m<span class="op">.</span>get<span class="op">()))</span> <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb16-4"><a href="#cb16-4"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5"></a>            <span class="cf">return</span> m <span class="op">?</span> addressof<span class="op">(*</span>m<span class="op">)</span> <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb16-6"><a href="#cb16-6"></a>        <span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1"></a><span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> data<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span> <em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1"></a>        <span class="kw">const</span> Maybe<span class="op">&amp;</span> m <span class="op">=</span> <span class="op">*</span>value_;</span>
<span id="cb18-2"><a href="#cb18-2"></a>        <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>is-reference-wrapper-v</em><span class="op">&lt;</span>Maybe<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3"></a>            <span class="cf">return</span> m<span class="op">.</span>get<span class="op">()</span> <span class="op">?</span> addressof<span class="op">(*(</span>m<span class="op">.</span>get<span class="op">()))</span> <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb18-4"><a href="#cb18-4"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb18-5"><a href="#cb18-5"></a>            <span class="cf">return</span> m <span class="op">?</span> addressof<span class="op">(*</span>m<span class="op">)</span> <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb18-6"><a href="#cb18-6"></a>        <span class="op">}</span></span></code></pre></div>
<h1 data-number="11" id="impact-on-the-standard"><span class="header-section-number">11</span> Impact on the standard<a href="#impact-on-the-standard" class="self-link"></a></h1>
<p>A pure library extension, affecting no other parts of the library or language.</p>
<h1 data-number="12" id="bibliography"><span class="header-section-number">12</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-N4849">
<p>[N4849] Richard Smith. 2020-01-14. Working Draft, Standard for Programming Language C++. <br />
<a href="https://wg21.link/n4849">https://wg21.link/n4849</a></p>
</div>
<div id="ref-P0323R9">
<p>[P0323R9] JF Bastien, Vicente Botet. 2019-08-03. std::expected. <br />
<a href="https://wg21.link/p0323r9">https://wg21.link/p0323r9</a></p>
</div>
<div id="ref-P0896R3">
<p>[P0896R3] Eric Niebler, Casey Carter, Christopher Di Bella. 2018-10-07. The One Ranges Proposal. <br />
<a href="https://wg21.link/p0896r3">https://wg21.link/p0896r3</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
