<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2023-05-18" />
  <title>A control flow operator</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;
}
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>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</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 control flow operator</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2561R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-05-18</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>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@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="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#preface"><span class="toc-section-number">2</span> Preface<span></span></a></li>
<li><a href="#introduction"><span class="toc-section-number">3</span> Introduction<span></span></a></li>
<li><a href="#an-automatic-propagation-operator"><span class="toc-section-number">4</span> An automatic propagation operator<span></span></a>
<ul>
<li><a href="#syntax-for-c"><span class="toc-section-number">4.1</span> Syntax for C++<span></span></a>
<ul>
<li><a href="#postfix-is-better-than-prefix"><span class="toc-section-number">4.1.1</span> Postfix is better than Prefix<span></span></a></li>
<li><a href="#postfix"><span class="toc-section-number">4.1.2</span> Postfix <code class="sourceCode cpp"><span class="op">??</span></code><span></span></a></li>
<li><a href="#why-e.try"><span class="toc-section-number">4.1.3</span> Why <code class="sourceCode cpp">e<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code><span></span></a></li>
<li><a href="#other-potential-syntaxes-considered"><span class="toc-section-number">4.1.4</span> Other potential syntaxes considered<span></span></a></li>
</ul></li>
<li><a href="#semantics"><span class="toc-section-number">4.2</span> Semantics<span></span></a>
<ul>
<li><a href="#lifetime"><span class="toc-section-number">4.2.1</span> Lifetime<span></span></a></li>
<li><a href="#decltype"><span class="toc-section-number">4.2.2</span> <code class="sourceCode cpp"><span class="kw">decltype</span></code><span></span></a></li>
<li><a href="#requires"><span class="toc-section-number">4.2.3</span> <code class="sourceCode cpp"><span class="kw">requires</span></code><span></span></a></li>
</ul></li>
<li><a href="#other-use-cases"><span class="toc-section-number">4.3</span> Other use-cases<span></span></a>
<ul>
<li><a href="#short-circuiting-fold"><span class="toc-section-number">4.3.1</span> Short-circuiting fold<span></span></a></li>
<li><a href="#pattern-matching"><span class="toc-section-number">4.3.2</span> Pattern Matching<span></span></a></li>
<li><a href="#range-of-expected-to-expected-of-range"><span class="toc-section-number">4.3.3</span> Range of <code class="sourceCode cpp">expected</code> to <code class="sourceCode cpp">expected</code> of Range<span></span></a></li>
<li><a href="#internal-iteration"><span class="toc-section-number">4.3.4</span> Internal iteration<span></span></a></li>
<li><a href="#naming"><span class="toc-section-number">4.3.5</span> Naming<span></span></a></li>
</ul></li>
<li><a href="#potential-directions-to-go-from-here"><span class="toc-section-number">4.4</span> Potential directions to go from here<span></span></a>
<ul>
<li><a href="#error-continuations"><span class="toc-section-number">4.4.1</span> Error continuations<span></span></a></li>
<li><a href="#not-propagating-errors"><span class="toc-section-number">4.4.2</span> Not propagating errors<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>The title of <span class="citation" data-cites="P2561R1">[<a href="#ref-P2561R1" role="doc-biblioref">P2561R1</a>]</span> was “An error propagation operator”, but this feature is much more general than simply propagating errors - it’s really about control flow. So renaming to a control flow operator (and a bunch of other renames of the customization points). The operator itself was renamed from <code class="sourceCode cpp">e<span class="op">??</span></code> to <code class="sourceCode cpp">e<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code>.</p>
<p>The title of <span class="citation" data-cites="P2561R0">[<a href="#ref-P2561R0" role="doc-biblioref">P2561R0</a>]</span> was <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">??</span></code>, but isn’t actually proposing that token, so it’s not the best title. Likewise, <code class="sourceCode cpp">try_traits</code> is a bad name for the collection of functionality for the same reason that the paper described <code class="sourceCode cpp"><span class="cf">try</span></code> as being a bad spelling for the operator. <code class="sourceCode cpp">is_ok</code> has been renamed to <code class="sourceCode cpp">has_value</code>, since that’s actually what we name that facility everywhere. A few other details added in addition to the two renames.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="preface"><span class="header-section-number">2</span> Preface<a href="#preface" class="self-link"></a></h1>
<p>It is important to clarify a few things up front. It is not the position of this paper that exceptions are bad. Or that exceptions are good. It is not the goal of this paper to convince you to start using exceptions, nor is it to convince you to stop using exceptions.</p>
<p>This paper simply recognizes that there are many code bases (or parts thereof) that do not use exceptions and probably will not in the future. That could be for performance or space reasons. It could be because exceptions are unsupported on a particular platform. It could be for code understandability reasons. Regardless, some code bases do not use exceptions. Moreover, some problems are not solved well by exceptions – even in code bases that otherwise use them to solve problems that they are more tailored to solve.</p>
<p>The problem is, C++ does not currently have a good story for error handling without exceptions. We’re moving away from returning bool or error codes in favor of solutions like <code class="sourceCode cpp">std<span class="op">::</span>expected</code> (<span class="citation" data-cites="P0323R12">[<a href="#ref-P0323R12" role="doc-biblioref">P0323R12</a>]</span>), but the ergonomics of such types are not there yet. Bad ergonomics leads to code that is clunkier than it needs to be, harder to follow, and, significantly and ironically, error-prone.</p>
<p>We should try to improve such uses too.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">3</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>Let’s start with a fairly small example of a series of functions that can generate errors, but don’t themselves handle them - they just need to propagate them up. With exceptions, this might look like:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">auto</span> foo<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>; <span class="co">// might throw an E</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">auto</span> bar<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>; <span class="co">// might throw an E</span></span>
<span id="cb1-3"><a href="#cb1-3"></a></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>string <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="dt">int</span> f <span class="op">=</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb1-6"><a href="#cb1-6"></a>    <span class="dt">int</span> b <span class="op">=</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb1-7"><a href="#cb1-7"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>There’s a lot to like about exceptions. One nice advantage is the zero syntactic overhead necessary for propagating errors. Errors just propagate. You don’t even have to know which functions can fail.</p>
<p>We don’t even need to declare variables to hold the results of <code class="sourceCode cpp">foo</code> and <code class="sourceCode cpp">bar</code>, we can even use those expressions inline, knowing that we’ll only call <code class="sourceCode cpp">format</code> if neither function throws an exception:</p>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">auto</span> foo<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>; <span class="co">// might throw an E</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> bar<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>; <span class="co">// might throw an E</span></span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>string <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, foo<span class="op">(</span>i<span class="op">)</span>, bar<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>But with the newly adopted <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>, it’s not quite so nice:</p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">auto</span> foo<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, E<span class="op">&gt;</span>;</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw">auto</span> bar<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, E<span class="op">&gt;</span>;</span>
<span id="cb3-3"><a href="#cb3-3"></a></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5"></a><span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6"></a>    <span class="kw">auto</span> f <span class="op">=</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8"></a>        <span class="cf">return</span> std<span class="op">::</span>unexpected<span class="op">(</span>f<span class="op">.</span>error<span class="op">())</span>;</span>
<span id="cb3-9"><a href="#cb3-9"></a>    <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10"></a></span>
<span id="cb3-11"><a href="#cb3-11"></a>    <span class="kw">auto</span> b <span class="op">=</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb3-12"><a href="#cb3-12"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-13"><a href="#cb3-13"></a>        <span class="cf">return</span> std<span class="op">::</span>unexpected<span class="op">(</span>b<span class="op">.</span>error<span class="op">())</span>;</span>
<span id="cb3-14"><a href="#cb3-14"></a>    <span class="op">}</span></span>
<span id="cb3-15"><a href="#cb3-15"></a></span>
<span id="cb3-16"><a href="#cb3-16"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, <span class="op">*</span>f, <span class="op">*</span>b<span class="op">)</span>;</span>
<span id="cb3-17"><a href="#cb3-17"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>This is significantly longer and more tedious because we have to do manual error propagation. This manual error propagation is most of the code in this short example, and is bad not just because of the lengthy boilerplate, but also because:</p>
<ul>
<li>we’re giving a name, <code class="sourceCode cpp">f</code>, to the <code class="sourceCode cpp">expected</code> object, not the success value. The error case is typically immediately handled, but the value case could be used multiple times and now has to be used as <code class="sourceCode cpp"><span class="op">*</span>f</code> (which is pretty weird for something that is decidedly not a pointer or even, unlike iterators, a generalization of pointer) or <code class="sourceCode cpp">f<span class="op">.</span>value<span class="op">()</span></code></li>
<li>the “nice” syntax for propagation - <code class="sourceCode cpp"><span class="cf">return</span> std<span class="op">::</span>unexpected<span class="op">(</span>e<span class="op">)</span></code> - is inefficient - if <code class="sourceCode cpp">E</code> is something more involved than <code class="sourceCode cpp">std<span class="op">::</span>error_code</code>, we really should <code class="sourceCode cpp">std<span class="op">::</span>move<span class="op">(</span>f<span class="op">).</span>error<span class="op">()</span></code> into that. And even then, we’re moving the error twice when we optimally could move it just once. The ideal would be: <code class="sourceCode cpp"><span class="cf">return</span> <span class="op">{</span>std<span class="op">::</span>unexpect, std<span class="op">::</span>move<span class="op">(</span>f<span class="op">).</span>error<span class="op">()}</span>;</code>, which is something I don’t expect a lot of people to actually write.</li>
</ul>
<p>In an effort to avoid… that… many libraries or code bases that use this sort approach to error handling provide a macro, which usually looks like this (<a href="https://www.boost.org/doc/libs/1_75_0/libs/leaf/doc/html/index.html#BOOST_LEAF_ASSIGN">Boost.LEAF</a>, <a href="https://www.boost.org/doc/libs/develop/libs/outcome/doc/html/reference/macros/try.html">Boost.Outcome</a>, <a href="https://github.com/google/mediapipe/blob/master/mediapipe/framework/deps/status_macros.h">mediapipe</a>, <a href="https://github.com/SerenityOS/serenity/blob/50642f85ac547a3caee353affcb08872cac49456/Documentation/Patterns.md#try-error-handling">SerenityOS</a>, etc. Although not all do, neither <code class="sourceCode cpp">folly</code>’s <code class="sourceCode cpp">fb<span class="op">::</span>Expected</code> nor <code class="sourceCode cpp">tl<span class="op">::</span>expected</code> nor <code class="sourceCode cpp">llvm<span class="op">::</span>Expected</code> provide such):</p>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>    SOMETHING_TRY<span class="op">(</span><span class="dt">int</span> f, foo<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb4-4"><a href="#cb4-4"></a>    SOMETHING_TRY<span class="op">(</span><span class="dt">int</span> b, bar<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb4-5"><a href="#cb4-5"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Which avoids all those problems, though each such library type will have its own corresponding macro. Also these <code class="sourceCode cpp">TRY</code> macros (not all of them have <code class="sourceCode cpp">TRY</code> in the name) need to be written on their own line, since they are declarations - thus the one-line version of <code class="sourceCode cpp">strcat</code> in the exception version isn’t possible.</p>
<p>Some more adventurous macros take advantage of the statement-expression extension, which would allow you to do this:</p>
<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="dt">int</span> f <span class="op">=</span> SOMETHING_TRY_EXPR<span class="op">(</span>foo<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb5-4"><a href="#cb5-4"></a>    <span class="dt">int</span> b <span class="op">=</span> SOMETHING_TRY_EXPR<span class="op">(</span>bar<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb5-5"><a href="#cb5-5"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb5-6"><a href="#cb5-6"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>And thus also write both macros inline. But this relies on compiler extensions, and this particular extension isn’t quite as efficient as it could be - and in particular it doesn’t move when it should.</p>
<p>Both macros also suffer when the function in question returns <code class="sourceCode cpp">expected<span class="op">&lt;</span><span class="dt">void</span>, E<span class="op">&gt;</span></code>, since you cannot declare (or assign to) a variable to hold that value, so the macro needs to emit different code to handle this case (<a href="https://www.boost.org/doc/libs/1_75_0/libs/leaf/doc/html/index.html#BOOST_LEAF_CHECK">Boost.LEAF</a>, <a href="https://www.boost.org/doc/libs/develop/libs/outcome/doc/html/reference/macros/tryv.html">Boost.Outcome</a>,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> etc.)</p>
<p>To that end, in search for nice syntax, some people turn to coroutines:</p>
<blockquote>
<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">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>    <span class="dt">int</span> f <span class="op">=</span> <span class="kw">co_await</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb6-4"><a href="#cb6-4"></a>    <span class="dt">int</span> b <span class="op">=</span> <span class="kw">co_await</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb6-5"><a href="#cb6-5"></a>    <span class="kw">co_return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb6-6"><a href="#cb6-6"></a></span>
<span id="cb6-7"><a href="#cb6-7"></a>    <span class="co">// ... or</span></span>
<span id="cb6-8"><a href="#cb6-8"></a>    <span class="kw">co_return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, <span class="kw">co_await</span> foo<span class="op">(</span>i<span class="op">)</span>, <span class="kw">co_await</span> bar<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb6-9"><a href="#cb6-9"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>This can be made to work in a fully-conformant way (at the syntactic cost of having to now write <code class="sourceCode cpp"><span class="kw">co_return</span></code>), and we can use the same syntax for both the <code class="sourceCode cpp"><span class="dt">void</span></code> and non-<code class="sourceCode cpp"><span class="dt">void</span></code> cases.</p>
<p>However, currently even the simple cases allocate which make this approach unusuable in many production contexts. The coroutine machinery also isn’t fully composable and runs into problems once you start doing something like <code class="sourceCode cpp">optional<span class="op">&lt;</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span></code> (or vice versa) or <code class="sourceCode cpp">task<span class="op">&lt;</span>optional<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></code>.</p>
<p>Which means the best-case today still involves <del>being jealous of exceptions</del> macros.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="an-automatic-propagation-operator"><span class="header-section-number">4</span> An automatic propagation operator<a href="#an-automatic-propagation-operator" class="self-link"></a></h1>
<p>Let’s talk about Rust.</p>
<p>Rust’s primary form of error handling is a sum type named <code class="sourceCode cpp">Result<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>. Taking our original example here and rewriting it in Rust (as one does) would look like this:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Rust</strong>
</div></th>
<th><div style="text-align:center">
<strong>C++</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">fn</span> strcat(i<span class="op">:</span> <span class="dt">i32</span>) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span><span class="dt">String</span><span class="op">,</span> E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>    <span class="kw">let</span> f <span class="op">=</span> <span class="kw">match</span> foo(i) <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></a>        <span class="cn">Ok</span>(i) <span class="op">=&gt;</span> i<span class="op">,</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>        <span class="cn">Err</span>(e) <span class="op">=&gt;</span> <span class="kw">return</span> <span class="cn">Err</span>(e)<span class="op">,</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="op">};</span></span>
<span id="cb1-6"><a href="#cb1-6"></a></span>
<span id="cb1-7"><a href="#cb1-7"></a>    <span class="kw">let</span> b <span class="op">=</span> <span class="kw">match</span> bar(i) <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8"></a>        <span class="cn">Ok</span>(i) <span class="op">=&gt;</span> i<span class="op">,</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>        <span class="cn">Err</span>(e) <span class="op">=&gt;</span> <span class="kw">return</span> <span class="cn">Err</span>(e)<span class="op">,</span></span>
<span id="cb1-10"><a href="#cb1-10"></a>    <span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11"></a></span>
<span id="cb1-12"><a href="#cb1-12"></a>    <span class="cn">Ok</span>(<span class="pp">format!</span>(<span class="st">&quot;{}{}&quot;</span><span class="op">,</span> f<span class="op">,</span> b))</span>
<span id="cb1-13"><a href="#cb1-13"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>    <span class="kw">auto</span> f <span class="op">=</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb7-3"><a href="#cb7-3"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4"></a>        <span class="cf">return</span> std<span class="op">::</span>unexpected<span class="op">(</span>f<span class="op">.</span>error<span class="op">())</span>;</span>
<span id="cb7-5"><a href="#cb7-5"></a>    <span class="op">}</span></span>
<span id="cb7-6"><a href="#cb7-6"></a></span>
<span id="cb7-7"><a href="#cb7-7"></a>    <span class="kw">auto</span> b <span class="op">=</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb7-8"><a href="#cb7-8"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9"></a>        <span class="cf">return</span> std<span class="op">::</span>unexpected<span class="op">(</span>b<span class="op">.</span>error<span class="op">())</span>;</span>
<span id="cb7-10"><a href="#cb7-10"></a>    <span class="op">}</span></span>
<span id="cb7-11"><a href="#cb7-11"></a></span>
<span id="cb7-12"><a href="#cb7-12"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, <span class="op">*</span>f, <span class="op">*</span>b<span class="op">)</span>;</span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>This fully manual version is already better than the C++ version due to pattern matching’s ability to just give a name to the thing we care about (the value) and avoid giving a name to the thing we don’t care about (the <code class="sourceCode cpp">Result</code> object).</p>
<p>But this isn’t the way you do things in Rust.</p>
<p>Originally, there was a <a href="https://doc.rust-lang.org/std/macro.try.html"><code class="sourceCode cpp"><span class="cf">try</span><span class="op">!</span></code> macro</a> which was defined mostly as that <code class="sourceCode cpp">match</code> expression I have above. But then this got generalized into <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">?</span></code>, whose behavior is driven by the <a href="https://doc.rust-lang.org/std/ops/trait.Try.html"><code class="sourceCode cpp">Try</code> trait</a> (originally there was <a href="https://rust-lang.github.io/rfcs/1859-try-trait.html">try-v1</a>, now this is <a href="https://rust-lang.github.io/rfcs/3058-try-trait-v2.html">try-v2</a>). That allows simply writing this:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Rust</strong>
</div></th>
<th><div style="text-align:center">
<strong>C++ with exceptions</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">fn</span> strcat(i<span class="op">:</span> <span class="dt">i32</span>) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span><span class="dt">String</span><span class="op">,</span> E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2"></a>    <span class="kw">let</span> f <span class="op">=</span> foo(i)<span class="op">?;</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>    <span class="kw">let</span> b <span class="op">=</span> bar(i)<span class="op">?;</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    <span class="cn">Ok</span>(<span class="pp">format!</span>(<span class="st">&quot;{}{}&quot;</span><span class="op">,</span> f<span class="op">,</span> b))</span>
<span id="cb2-5"><a href="#cb2-5"></a></span>
<span id="cb2-6"><a href="#cb2-6"></a>    <span class="co">// ... or simply ...</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>    <span class="cn">Ok</span>(<span class="pp">format!</span>(<span class="st">&quot;{}{}&quot;</span><span class="op">,</span> foo(i)<span class="op">?,</span> bar(i)<span class="op">?</span>))</span>
<span id="cb2-8"><a href="#cb2-8"></a><span class="op">}</span></span></code></pre></div></td>
<td><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">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>string <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2"></a>    <span class="dt">int</span> f <span class="op">=</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb8-3"><a href="#cb8-3"></a>    <span class="dt">int</span> b <span class="op">=</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb8-4"><a href="#cb8-4"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb8-5"><a href="#cb8-5"></a></span>
<span id="cb8-6"><a href="#cb8-6"></a>    <span class="co">// ... or simply ...</span></span>
<span id="cb8-7"><a href="#cb8-7"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, foo<span class="op">(</span>i<span class="op">)</span>, bar<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb8-8"><a href="#cb8-8"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>Now, Rust still has manual error propagation, but it’s the minimal possible syntactic overhead: one character per expression.</p>
<p>Importantly, one character per expression is still actually an enormous amount more overhead than zero characters per expression, since that implies that you cannot have error-neutral functions - they have to manually propagate errors too.</p>
<p>But to those people who write code using types like <code class="sourceCode cpp">std<span class="op">::</span>expected</code> today, who may use the kinds of macros I showed earlier or foray into coroutines, this is kind of a dream?</p>
<h2 data-number="4.1" id="syntax-for-c"><span class="header-section-number">4.1</span> Syntax for C++<a href="#syntax-for-c" class="self-link"></a></h2>
<p>Before diving too much into semantics, let’s just start by syntax. Unfortunately, C++ cannot simply grab the Rust syntax of a postfix <code class="sourceCode cpp"><span class="op">?</span></code> here, because we also have the conditional operator <code class="sourceCode cpp"><span class="op">?:</span></code>, with which it can be ambiguous:</p>
<blockquote>
<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">auto</span> res <span class="op">=</span> a <span class="op">?</span> <span class="op">*</span> b <span class="op">?</span> <span class="op">*</span> c <span class="op">:</span> d;</span></code></pre></div>
</blockquote>
<p>That could be parsed two ways:</p>
<blockquote>
<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">auto</span> res1 <span class="op">=</span> a <span class="op">?</span> <span class="op">(*(</span>b<span class="op">?)</span> <span class="op">*</span> c<span class="op">)</span> <span class="op">:</span> d;</span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="kw">auto</span> res2 <span class="op">=</span> <span class="op">((</span>a<span class="op">?)</span> <span class="op">*</span> b<span class="op">)</span> <span class="op">?</span> <span class="op">(*</span>c<span class="op">)</span> <span class="op">:</span> d;</span></code></pre></div>
</blockquote>
<p>What if you assume that a <code class="sourceCode cpp"><span class="op">?</span></code> is a conditional operator and try to parse that until it fails, then back up and try again to parse a postfix <code class="sourceCode cpp"><span class="op">?</span></code> operator? Is that really a viable strategy? If we assume both <code class="sourceCode cpp"><span class="op">?</span></code>s are the beginning of a conditional, then that will eventually fail since we hit a <code class="sourceCode cpp">;</code> before a second <code class="sourceCode cpp"><span class="op">:</span></code> - but it’s the outer <code class="sourceCode cpp"><span class="op">?</span></code> that failed, not the inner - do we retry the inner first (which would lead to the <code class="sourceCode cpp">res1</code> parse eventually) or the outer first (which would lead to the <code class="sourceCode cpp">res2</code> one)?</p>
<p>Maybe this is doable with parsing heroics, but at some point I have to ask if it’s worth it.</p>
<p>Another reason that a single <code class="sourceCode cpp"><span class="op">?</span></code> might not be a good idea, even if it were possible to parse, would be <a href="#error-continuations">optional chaining</a>. With that facility, if <code class="sourceCode cpp">o</code> were an <code class="sourceCode cpp">optional<span class="op">&lt;</span>string<span class="op">&gt;</span></code>, <code class="sourceCode cpp">o<span class="op">?.</span>size<span class="op">()</span></code> would be an <code class="sourceCode cpp">optional<span class="op">&lt;</span><span class="dt">size_t</span><span class="op">&gt;</span></code> (that is either engaged with the original string’s size, or empty). But if <code class="sourceCode cpp">o<span class="op">?</span></code> propagated the error, then <code class="sourceCode cpp">o<span class="op">?.</span>size<span class="op">()</span></code> would itself be a valid expression that is a <code class="sourceCode cpp"><span class="dt">size_t</span></code> (the string’s size, and if we didn’t have a string we would have returned). So if we want to support error continuations, we’d need distinct syntax for these cases.</p>
<p>So if <code class="sourceCode cpp">expr<span class="op">?</span></code> is not viable, what can we choose instead? There’s a bunch of things to consider.</p>
<h3 data-number="4.1.1" id="postfix-is-better-than-prefix"><span class="header-section-number">4.1.1</span> Postfix is better than Prefix<a href="#postfix-is-better-than-prefix" class="self-link"></a></h3>
<p>For the purposes of this section, let’s stick with <code class="sourceCode cpp"><span class="op">?</span></code> as the token, and talk about whether this should be a prefix operator or postfix operator. Now, <code class="sourceCode cpp"><span class="op">?</span></code> would be viable as a prefix operator whereas it’s not viable as a postfix operator, but it’s still worth going through an example nevertheless:</p>
<blockquote>
<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">struct</span> U <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb11-2"><a href="#cb11-2"></a></span>
<span id="cb11-3"><a href="#cb11-3"></a><span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4"></a>    <span class="kw">auto</span> next<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>U, E<span class="op">&gt;</span>;</span>
<span id="cb11-5"><a href="#cb11-5"></a><span class="op">}</span>;</span>
<span id="cb11-6"><a href="#cb11-6"></a></span>
<span id="cb11-7"><a href="#cb11-7"></a><span class="kw">auto</span> lookup<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span>;</span>
<span id="cb11-8"><a href="#cb11-8"></a></span>
<span id="cb11-9"><a href="#cb11-9"></a><span class="kw">auto</span> func<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>U, E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-10"><a href="#cb11-10"></a>    <span class="co">// as postfix</span></span>
<span id="cb11-11"><a href="#cb11-11"></a>    U u <span class="op">=</span> lookup<span class="op">()?.</span>next<span class="op">()?</span>;</span>
<span id="cb11-12"><a href="#cb11-12"></a></span>
<span id="cb11-13"><a href="#cb11-13"></a>    <span class="co">// using the monadic operations</span></span>
<span id="cb11-14"><a href="#cb11-14"></a>    U u <span class="op">=</span> lookup<span class="op">().</span>and_then<span class="op">(&amp;</span>T<span class="op">::</span>next<span class="op">)</span>;</span>
<span id="cb11-15"><a href="#cb11-15"></a></span>
<span id="cb11-16"><a href="#cb11-16"></a>    <span class="co">// as prefix</span></span>
<span id="cb11-17"><a href="#cb11-17"></a>    U u <span class="op">=</span> <span class="op">?(?</span>lookup<span class="op">()).</span>next<span class="op">()</span>;</span>
<span id="cb11-18"><a href="#cb11-18"></a></span>
<span id="cb11-19"><a href="#cb11-19"></a>    do_something_with<span class="op">(</span>u<span class="op">)</span>;</span>
<span id="cb11-20"><a href="#cb11-20"></a></span>
<span id="cb11-21"><a href="#cb11-21"></a>    <span class="cf">return</span> u;</span>
<span id="cb11-22"><a href="#cb11-22"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>The postfix version chains in a way that is quite easy to read.</p>
<p>Using the monadic operations (<span class="citation" data-cites="P2505R4">[<a href="#ref-P2505R4" role="doc-biblioref">P2505R4</a>]</span>) is fine, they’re nice in this case (which is basically optimal for them) but they tend to be quite tedious once you stray from this exact formulation (e.g. if <code class="sourceCode cpp">T<span class="op">::</span>next<span class="op">()</span></code> took another argument).</p>
<p>The prefix version is borderline illegible to me once the expression you need to propagate is even slightly complicated.</p>
<p>Even if we consider only one or the other side of the member access as needing propagation:</p>
<ul>
<li>Accessing a member after propagating: <code class="sourceCode cpp">x<span class="op">?.</span>y</code> vs <code class="sourceCode cpp"><span class="op">(?</span>x<span class="op">).</span>y</code></li>
<li>Propagating after accessing a member: <code class="sourceCode cpp">x<span class="op">.</span>y<span class="op">?</span></code> vs <code class="sourceCode cpp"><span class="op">?</span>x<span class="op">.</span>y</code> or <code class="sourceCode cpp"><span class="op">?(</span>x<span class="op">.</span>y<span class="op">)</span></code></li>
</ul>
<p>The postfix operator is quite a bit easier to understand, since it’s always right next to the expression that is potentially failing.</p>
<h3 data-number="4.1.2" id="postfix"><span class="header-section-number">4.1.2</span> Postfix <code class="sourceCode cpp"><span class="op">??</span></code><a href="#postfix" class="self-link"></a></h3>
<p>While postfix <code class="sourceCode cpp"><span class="op">?</span></code> isn’t viable, postfix <code class="sourceCode cpp"><span class="op">??</span></code> could be. And a previous revision of this paper proposed just that <span class="citation" data-cites="P2561R1">[<a href="#ref-P2561R1" role="doc-biblioref">P2561R1</a>]</span>. However, while <code class="sourceCode cpp"><span class="op">?</span></code> has precedent in Rust for exactly the operation being proposed here, <code class="sourceCode cpp"><span class="op">??</span></code> has precedent in other languages as well - just for something quite different.</p>
<p><code class="sourceCode cpp"><span class="op">??</span></code> is called a “null (or nil) coalescing operator” in some languages (like C# or JavaScript or Swift) where <code class="sourceCode cpp">x <span class="op">??</span> y</code> is roughly equivalent to what C++ would spell as <code class="sourceCode cpp">x <span class="op">?</span> <span class="op">*</span>x <span class="op">:</span> y</code> except that <code class="sourceCode cpp">x</code> is only evaluated once. Kotlin spells this operator <code class="sourceCode cpp"><span class="op">?:</span></code>, but it behaves differently from the gcc extension since <code class="sourceCode cpp">x <span class="op">?:</span> y</code> in gcc evaluates as <code class="sourceCode cpp">x <span class="op">?</span> x <span class="op">:</span> y</code> rather than <code class="sourceCode cpp">x <span class="op">?</span> <span class="op">*</span>x <span class="op">:</span> y</code>.</p>
<p>For <code class="sourceCode cpp">x</code> being some kind of <code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code> or <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>, this can <em>mostly</em> already be spelled <code class="sourceCode cpp">x<span class="op">.</span>value_or<span class="op">(</span>y<span class="op">)</span></code>. The difference is that here <code class="sourceCode cpp">y</code> is unconditionally evaluated, which is why <span class="citation" data-cites="P2218R0">[<a href="#ref-P2218R0" role="doc-biblioref">P2218R0</a>]</span> proposes a separate <code class="sourceCode cpp">opt<span class="op">.</span>value_or_else<span class="op">(</span>f<span class="op">)</span></code> which invokes <code class="sourceCode cpp">f</code>. Which would make a proper equivalence be spelled <code class="sourceCode cpp">x<span class="op">.</span>value_or_else<span class="op">([&amp;]{</span> <span class="cf">return</span> y; <span class="op">})</span></code>.</p>
<p>I’m not aware of any proposals to add this particular operator in C++, but because we already have two types that directly provide that functionality (as would many other non-<code class="sourceCode cpp">std</code> flavors thereof), and because it’s fairly straightforward to write such an algorithm generically, it wouldn’t seem especially valuable to have a dedicated operator for this functionality – so it’s probably safe to take for this use-case.</p>
<p>It certainly would be nice to have both, but given a choice between a null coalescing operator and a control flow propagation one, I’d choose the latter. That said, given that <code class="sourceCode cpp"><span class="op">??</span></code> does appear in many languages as this one particular thing, even if I don’t personally consider that particular thing useful in C++, I don’t think it’s a good idea to take that operator in C++ to mean something very different.</p>
<h3 data-number="4.1.3" id="why-e.try"><span class="header-section-number">4.1.3</span> Why <code class="sourceCode cpp">e<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code><a href="#why-e.try" class="self-link"></a></h3>
<p>For those libraries that provide this operation as a macro, the name is usually <code class="sourceCode cpp">TRY</code> and <span class="citation" data-cites="P0779R0">[<a href="#ref-P0779R0" role="doc-biblioref">P0779R0</a>]</span> previously suggested this sort of facility under the name <code class="sourceCode cpp"><span class="kw">operator</span> <span class="cf">try</span></code>. As mentioned, Rust previously had an error propagation macro named <code class="sourceCode cpp"><span class="cf">try</span><span class="op">!</span></code> and multiple other languages have such an error propagation operator (<a href="https://ziglang.org/documentation/master/#try">Zig</a>, <a href="https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html">Swift</a>, <a href="http://joeduffyblog.com/2016/02/07/the-error-model/">Midori</a>, etc.).</p>
<p>The problem is, in C++, <code class="sourceCode cpp"><span class="cf">try</span></code> is strongly associated with <em>exceptions</em>. That’s what a <code class="sourceCode cpp"><span class="cf">try</span></code> block is for: to catch exceptions. In <span class="citation" data-cites="P0709R4">[<a href="#ref-P0709R4" role="doc-biblioref">P0709R4</a>]</span>, there was a proposal for a <code class="sourceCode cpp"><span class="cf">try</span></code> expression (in §4.5.1). That, too, was tied in with exceptions. Not only for us is it tied into exceptions, but it’s used to <em>not</em> propagate the exception - <code class="sourceCode cpp"><span class="cf">try</span></code> blocks are for handling errors.</p>
<p>Having a facility for error propagation in C++ which has nothing to do with exceptions still use the keyword <code class="sourceCode cpp"><span class="cf">try</span></code> and do the opposite of a what a <code class="sourceCode cpp"><span class="cf">try</span></code> block does today (i.e. propagate the error, instead of handling it) would be, I think, potentially misleading. And the goal here isn’t to interact with exceptions at all - it’s simply to provide automated error propagation for those error handling cases that <em>don’t</em> use exceptions.</p>
<p>That said, postfix <code class="sourceCode cpp"><span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> is viable syntax (it’s ill-formed today) and would be better than prefix <code class="sourceCode cpp"><span class="cf">try</span> e</code> or <code class="sourceCode cpp"><span class="cf">try</span><span class="op">?</span> e</code> (as discussed <a href="#postfix-is-better-than-prefix">earlier</a>), and despite being unrelated to exceptions, it is quite commonly used in practice for this functionality in C++ anyway. It seems like a pretty reasonable choice, all things considered.</p>
<h3 data-number="4.1.4" id="other-potential-syntaxes-considered"><span class="header-section-number">4.1.4</span> Other potential syntaxes considered<a href="#other-potential-syntaxes-considered" class="self-link"></a></h3>
<p>Here is a list of other potential syntaxes I’ve considered:</p>
<table>
<colgroup>
<col style="width: 20%"></col>
<col style="width: 80%"></col>
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Syntax</strong>
</div></th>
<th><div style="text-align:center">
<strong>Notes</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode cpp"><span class="op">?</span>e</code></td>
<td>Don’t like the prefix</td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp"><span class="cf">try</span> e</code> or <code class="sourceCode cpp"><span class="cf">try</span><span class="op">?</span> e</code></td>
<td>Don’t like the prefix</td>
</tr>
<tr class="odd">
<td><code class="sourceCode cpp">e<span class="op">???</span></code></td>
<td><code class="sourceCode cpp"><span class="op">???</span></code> was the trigraph for <code class="sourceCode cpp"><span class="op">?</span></code>, and looks ridiculous, but at least doesn’t conflict with other languages’ <code class="sourceCode cpp"><span class="op">??</span></code></td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp">e<span class="op">!</span></code></td>
<td>Viable, but seems like the wrong punctuation for something that may or may not continue</td>
</tr>
<tr class="odd">
<td><code class="sourceCode cpp">e<span class="op">.</span><span class="cf">continue</span><span class="op">?</span></code></td>
<td>Viable, and not completely terrible, but doesn’t seem as nice as <code class="sourceCode cpp">e<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code></td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp">e<span class="op">.</span>or_return<span class="op">?</span></code></td>
<td>Clearly expresses behavior, but seems strictly worse than using <code class="sourceCode cpp"><span class="cf">try</span><span class="op">?</span></code> or <code class="sourceCode cpp"><span class="cf">continue</span><span class="op">?</span></code></td>
</tr>
</tbody>
</table>
<h2 data-number="4.2" id="semantics"><span class="header-section-number">4.2</span> Semantics<a href="#semantics" class="self-link"></a></h2>
<p>Regardless of what the right choice of syntax is (which admittedly keeps changing in every revision of this paper), we do have to talk about semantics.</p>
<p>This paper suggests that <code class="sourceCode cpp"><span class="cf">try</span><span class="op">?</span></code> evaluate roughly as follows:</p>
<table>
<tbody>
<tr class="odd">
<td><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">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2"></a><span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3"></a></span>
<span id="cb12-4"><a href="#cb12-4"></a></span>
<span id="cb12-5"><a href="#cb12-5"></a>    <span class="dt">int</span> f <span class="op">=</span> foo<span class="op">(</span>i<span class="op">).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb12-6"><a href="#cb12-6"></a></span>
<span id="cb12-7"><a href="#cb12-7"></a></span>
<span id="cb12-8"><a href="#cb12-8"></a></span>
<span id="cb12-9"><a href="#cb12-9"></a></span>
<span id="cb12-10"><a href="#cb12-10"></a></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>
<span id="cb12-14"><a href="#cb12-14"></a></span>
<span id="cb12-15"><a href="#cb12-15"></a>    <span class="dt">int</span> b <span class="op">=</span> bar<span class="op">(</span>i<span class="op">).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb12-16"><a href="#cb12-16"></a></span>
<span id="cb12-17"><a href="#cb12-17"></a></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>
<span id="cb12-21"><a href="#cb12-21"></a></span>
<span id="cb12-22"><a href="#cb12-22"></a></span>
<span id="cb12-23"><a href="#cb12-23"></a></span>
<span id="cb12-24"><a href="#cb12-24"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb12-25"><a href="#cb12-25"></a><span class="op">}</span></span></code></pre></div></td>
<td><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">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2"></a><span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3"></a>    <span class="kw">using</span> <em>_Return</em> <span class="op">=</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span></span>
<span id="cb13-4"><a href="#cb13-4"></a>        std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;&gt;</span>;</span>
<span id="cb13-5"><a href="#cb13-5"></a></span>
<span id="cb13-6"><a href="#cb13-6"></a>    <span class="kw">auto</span><span class="op">&amp;&amp;</span> <em>__f</em> <span class="op">=</span> foo<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb13-7"><a href="#cb13-7"></a>    <span class="kw">using</span> <em>_TraitsF</em> <span class="op">=</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span></span>
<span id="cb13-8"><a href="#cb13-8"></a>        std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><em>__f</em><span class="op">)&gt;&gt;</span>;</span>
<span id="cb13-9"><a href="#cb13-9"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> <em>_TraitsF</em><span class="op">::</span>should_continue<span class="op">(</span><em>__f</em><span class="op">))</span> <span class="op">{</span></span>
<span id="cb13-10"><a href="#cb13-10"></a>        <span class="cf">return</span> <em>_Return</em><span class="op">::</span>from_break<span class="op">(</span></span>
<span id="cb13-11"><a href="#cb13-11"></a>            <em>_TraitsF</em><span class="op">::</span>extract_break<span class="op">(</span>FWD<span class="op">(</span><em>__f</em><span class="op">)))</span>;</span>
<span id="cb13-12"><a href="#cb13-12"></a>    <span class="op">}</span></span>
<span id="cb13-13"><a href="#cb13-13"></a>    <span class="dt">int</span> f <span class="op">=</span> <em>_TraitsF</em><span class="op">::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span><em>__f</em><span class="op">))</span>;</span>
<span id="cb13-14"><a href="#cb13-14"></a></span>
<span id="cb13-15"><a href="#cb13-15"></a>    <span class="kw">auto</span><span class="op">&amp;&amp;</span> <em>__b</em> <span class="op">=</span> bar<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb13-16"><a href="#cb13-16"></a>    <span class="kw">using</span> <em>_TraitsB</em> <span class="op">=</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span></span>
<span id="cb13-17"><a href="#cb13-17"></a>        std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><em>__b</em><span class="op">)&gt;&gt;</span>;</span>
<span id="cb13-18"><a href="#cb13-18"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> <em>_TraitsB</em><span class="op">::</span>should_continue<span class="op">(</span>__b<span class="op">))</span> <span class="op">{</span></span>
<span id="cb13-19"><a href="#cb13-19"></a>        <span class="cf">return</span> <em>_Return</em><span class="op">::</span>from_break<span class="op">(</span></span>
<span id="cb13-20"><a href="#cb13-20"></a>            <em>_TraitsB</em><span class="op">::</span>extract_break<span class="op">(</span>FWD<span class="op">(</span><em>__b</em><span class="op">)))</span>;</span>
<span id="cb13-21"><a href="#cb13-21"></a>    <span class="op">}</span></span>
<span id="cb13-22"><a href="#cb13-22"></a>    <span class="dt">int</span> b <span class="op">=</span> <em>_TraitsB</em><span class="op">::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span><em>__b</em><span class="op">))</span>;</span>
<span id="cb13-23"><a href="#cb13-23"></a></span>
<span id="cb13-24"><a href="#cb13-24"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, f, b<span class="op">)</span>;</span>
<span id="cb13-25"><a href="#cb13-25"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>The functionality here is driven by a new traits type called <code class="sourceCode cpp">std<span class="op">::</span>try_traits</code>, such that a given specialization supports:</p>
<ul>
<li>telling us when the object is truthy: <code class="sourceCode cpp">should_continue</code></li>
<li>extracting the continue type (<code class="sourceCode cpp">extract_continue</code>) or break type (<code class="sourceCode cpp">extract_break</code>) from it</li>
<li>constructing a new object from either the continuation type (<code class="sourceCode cpp">from_continue</code>, not necessary in the above example, but will demonstrate a use later) or the break type (<code class="sourceCode cpp">from_break</code>)</li>
</ul>
<p>Note that this does not support deducing return type, since we need the return type in order to know how construct it - the above desugaring uses the return type of <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span></code> to know how to re-wrap the potential error that <code class="sourceCode cpp">foo<span class="op">(</span>i<span class="op">)</span></code> or <code class="sourceCode cpp">bar<span class="op">(</span>i<span class="op">)</span></code> could return. This is important because it avoids the overhead that nicer syntax like <code class="sourceCode cpp">std<span class="op">::</span>unexpected</code> or <code class="sourceCode cpp">outcome<span class="op">::</span>failure</code> introduces (neither of which allow for deducing return type anyway, at least unless the function unconditionally fails), while still allowing nicer syntax.</p>
<p>This isn’t really a huge loss, since in these contexts, you can’t really deduce the return type anyway - since you’ll have some error type and some value type. So this restriction isn’t actually restrictive in practice.</p>
<p>These functions are all very easy to implement for the kinds of types that would want to support a facility like <code class="sourceCode cpp"><span class="cf">try</span><span class="op">?</span></code>. Here are examples for <code class="sourceCode cpp">optional</code> and <code class="sourceCode cpp">expected</code> (with <code class="sourceCode cpp"><span class="kw">constexpr</span></code> omitted to fit):</p>
<table>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></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="cb14-2"><a href="#cb14-2"></a><span class="kw">struct</span> try_traits<span class="op">&lt;</span>optional<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3"></a>  <span class="kw">using</span> continue_type <span class="op">=</span> T;</span>
<span id="cb14-4"><a href="#cb14-4"></a>  <span class="kw">using</span> break_type <span class="op">=</span> nullopt_t;</span>
<span id="cb14-5"><a href="#cb14-5"></a></span>
<span id="cb14-6"><a href="#cb14-6"></a>  <span class="kw">auto</span> should_continue<span class="op">(</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> o<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb14-7"><a href="#cb14-7"></a>    <span class="cf">return</span> o<span class="op">.</span>has_value<span class="op">()</span>;</span>
<span id="cb14-8"><a href="#cb14-8"></a>  <span class="op">}</span></span>
<span id="cb14-9"><a href="#cb14-9"></a></span>
<span id="cb14-10"><a href="#cb14-10"></a>  <span class="co">// extractors</span></span>
<span id="cb14-11"><a href="#cb14-11"></a>  <span class="kw">auto</span> extract_continue<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> o<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12"></a>    <span class="cf">return</span> <span class="op">*</span>FWD<span class="op">(</span>o<span class="op">)</span>;</span>
<span id="cb14-13"><a href="#cb14-13"></a>  <span class="op">}</span></span>
<span id="cb14-14"><a href="#cb14-14"></a>  <span class="kw">auto</span> extract_break<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> error_type <span class="op">{</span></span>
<span id="cb14-15"><a href="#cb14-15"></a>    <span class="cf">return</span> nullopt;</span>
<span id="cb14-16"><a href="#cb14-16"></a>  <span class="op">}</span></span>
<span id="cb14-17"><a href="#cb14-17"></a></span>
<span id="cb14-18"><a href="#cb14-18"></a>  <span class="co">// factories</span></span>
<span id="cb14-19"><a href="#cb14-19"></a>  <span class="kw">auto</span> from_continue<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> v<span class="op">)</span> <span class="op">-&gt;</span> optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-20"><a href="#cb14-20"></a>    <span class="cf">return</span> optional<span class="op">&lt;</span>T<span class="op">&gt;(</span>in_place, FWD<span class="op">(</span>v<span class="op">))</span>;</span>
<span id="cb14-21"><a href="#cb14-21"></a>  <span class="op">}</span></span>
<span id="cb14-22"><a href="#cb14-22"></a>  <span class="kw">auto</span> from_break<span class="op">(</span>nullopt_t<span class="op">)</span> <span class="op">-&gt;</span> optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-23"><a href="#cb14-23"></a>    <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb14-24"><a href="#cb14-24"></a>  <span class="op">}</span></span>
<span id="cb14-25"><a href="#cb14-25"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><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">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> E<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2"></a><span class="kw">struct</span> try_traits<span class="op">&lt;</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3"></a>  <span class="kw">using</span> continue_type <span class="op">=</span> T;</span>
<span id="cb15-4"><a href="#cb15-4"></a>  <span class="kw">using</span> break_type <span class="op">=</span> E;</span>
<span id="cb15-5"><a href="#cb15-5"></a></span>
<span id="cb15-6"><a href="#cb15-6"></a>  <span class="kw">auto</span> should_continue<span class="op">(</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> e<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb15-7"><a href="#cb15-7"></a>    <span class="cf">return</span> e<span class="op">.</span>has_value<span class="op">()</span>;</span>
<span id="cb15-8"><a href="#cb15-8"></a>  <span class="op">}</span></span>
<span id="cb15-9"><a href="#cb15-9"></a></span>
<span id="cb15-10"><a href="#cb15-10"></a>  <span class="co">// extractors</span></span>
<span id="cb15-11"><a href="#cb15-11"></a>  <span class="kw">auto</span> extract_continue<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> e<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">{</span></span>
<span id="cb15-12"><a href="#cb15-12"></a>    <span class="cf">return</span> <span class="op">*</span>FWD<span class="op">(</span>e<span class="op">)</span>;</span>
<span id="cb15-13"><a href="#cb15-13"></a>  <span class="op">}</span></span>
<span id="cb15-14"><a href="#cb15-14"></a>  <span class="kw">auto</span> extract_break<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> e<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">{</span></span>
<span id="cb15-15"><a href="#cb15-15"></a>    <span class="cf">return</span> FWD<span class="op">(</span>e<span class="op">).</span>error<span class="op">()</span>;</span>
<span id="cb15-16"><a href="#cb15-16"></a>  <span class="op">}</span></span>
<span id="cb15-17"><a href="#cb15-17"></a></span>
<span id="cb15-18"><a href="#cb15-18"></a>  <span class="co">// factories</span></span>
<span id="cb15-19"><a href="#cb15-19"></a>  <span class="kw">auto</span> from_continue<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> v<span class="op">)</span> <span class="op">-&gt;</span> expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb15-20"><a href="#cb15-20"></a>    <span class="cf">return</span> expected<span class="op">&lt;</span>T, E<span class="op">&gt;(</span>in_place, FWD<span class="op">(</span>v<span class="op">))</span>;</span>
<span id="cb15-21"><a href="#cb15-21"></a>  <span class="op">}</span></span>
<span id="cb15-22"><a href="#cb15-22"></a>  <span class="kw">auto</span> from_break<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> e<span class="op">)</span> <span class="op">-&gt;</span> expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb15-23"><a href="#cb15-23"></a>    <span class="cf">return</span> expected<span class="op">&lt;</span>T, E<span class="op">&gt;(</span>unexpect, FWD<span class="op">(</span>e<span class="op">))</span>;</span>
<span id="cb15-24"><a href="#cb15-24"></a>  <span class="op">}</span></span>
<span id="cb15-25"><a href="#cb15-25"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>This also helps demonstrate the requirements for what <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>O<span class="op">&gt;</span></code> have to return:</p>
<ul>
<li><code class="sourceCode cpp">should_continue</code> is invoked on an lvalue of type <code class="sourceCode cpp">O</code> and returns <code class="sourceCode cpp"><span class="dt">bool</span></code></li>
<li><code class="sourceCode cpp">extract_continue</code> takes some kind of <code class="sourceCode cpp">O</code> and returns a type that, after stripping qualifiers, is <code class="sourceCode cpp">value_type</code></li>
<li><code class="sourceCode cpp">extract_break</code> takes some kind of <code class="sourceCode cpp">O</code> and returns a type that, after stripping qualifiers, is <code class="sourceCode cpp">error_type</code></li>
<li><code class="sourceCode cpp">from_continue</code> and <code class="sourceCode cpp">from_break</code> each returns an <code class="sourceCode cpp">O</code> (though their arguments need not be specifically a <code class="sourceCode cpp">value_type</code> or an <code class="sourceCode cpp">error_type</code>)</li>
</ul>
<p>In the above case, <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;::</span>extract_break</code> will always give some kind of reference to <code class="sourceCode cpp">E</code> (either <code class="sourceCode cpp">E<span class="op">&amp;</span></code>, <code class="sourceCode cpp">E <span class="kw">const</span><span class="op">&amp;</span></code>, <code class="sourceCode cpp">E<span class="op">&amp;&amp;</span></code>, or <code class="sourceCode cpp">E <span class="kw">const</span><span class="op">&amp;&amp;</span></code>, depending on the value category of the argument), while <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>optional<span class="op">&lt;</span>T<span class="op">&gt;&gt;::</span>extract_break</code> will always be <code class="sourceCode cpp">std<span class="op">::</span>nullopt_t</code>, by value. Both are fine, it simply depends on the type.</p>
<p>Since the extractors are only invoked on an <code class="sourceCode cpp">O</code> directly, you can safely assume that the object passed in is basically a forwarding reference to <code class="sourceCode cpp">O</code>, so <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">&amp;&amp;</span></code> is fine (at least pending something like <span class="citation" data-cites="P2481R1">[<a href="#ref-P2481R1" role="doc-biblioref">P2481R1</a>]</span>). The extractors have the implicit precondition that the object is in the state specified (e.g. <code class="sourceCode cpp">extract_continue<span class="op">(</span>o<span class="op">)</span></code> should only be called if <code class="sourceCode cpp">should_continue<span class="op">(</span>o<span class="op">)</span></code>, with the converse for <code class="sourceCode cpp">extract_break<span class="op">(</span>o<span class="op">)</span></code>). The factories can accept anything though, and should probably be constrained.</p>
<p>The choice of desugaring based specifically on the return type (rather than relying on each object to produce some kind of construction disambiguator like <code class="sourceCode cpp">nullopt_t</code> or <code class="sourceCode cpp">unexpected<span class="op">&lt;</span>E<span class="op">&gt;</span></code>) is not only that we can be more performant, but also we can allow conversions between different kinds of error types, which is useful when joining various libraries together:</p>
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">auto</span> foo<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> tl<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, E<span class="op">&gt;</span>;</span>
<span id="cb16-2"><a href="#cb16-2"></a><span class="kw">auto</span> bar<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, E<span class="op">&gt;</span>;</span>
<span id="cb16-3"><a href="#cb16-3"></a></span>
<span id="cb16-4"><a href="#cb16-4"></a><span class="kw">auto</span> strcat<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> Result<span class="op">&lt;</span>string, E<span class="op">&gt;</span></span>
<span id="cb16-5"><a href="#cb16-5"></a><span class="op">{</span></span>
<span id="cb16-6"><a href="#cb16-6"></a>    <span class="co">// this works</span></span>
<span id="cb16-7"><a href="#cb16-7"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;{}{}&quot;</span>, foo<span class="op">(</span>i<span class="op">).</span><span class="cf">try</span><span class="op">?</span>, bar<span class="op">(</span>i<span class="op">).</span><span class="cf">try</span><span class="op">?)</span>;</span>
<span id="cb16-8"><a href="#cb16-8"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>As long as each of these various error types opts into <code class="sourceCode cpp">try_traits</code> so that they can properly be constructed from an error, this will work just fine.</p>
<h3 data-number="4.2.1" id="lifetime"><span class="header-section-number">4.2.1</span> Lifetime<a href="#lifetime" class="self-link"></a></h3>
<p>Let’s consider some function declarations, where <code class="sourceCode cpp">T</code>, <code class="sourceCode cpp">U</code>, <code class="sourceCode cpp">V</code>, and <code class="sourceCode cpp">E</code> are some well-behaved object types.</p>
<blockquote>
<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">auto</span> foo<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;)</span> <span class="op">-&gt;</span> V;</span>
<span id="cb17-2"><a href="#cb17-2"></a><span class="kw">auto</span> bar<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span>;</span>
<span id="cb17-3"><a href="#cb17-3"></a><span class="kw">auto</span> quux<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>U, E<span class="op">&gt;</span>;</span></code></pre></div>
</blockquote>
<p>Now, consider the following fragment:</p>
<blockquote>
<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">auto</span> a <span class="op">=</span> foo<span class="op">(</span>bar<span class="op">().</span><span class="cf">try</span><span class="op">?)</span>;</span></code></pre></div>
</blockquote>
<p>The lifetime implications here should follow from the rest of the rules of the languages. Temporaries are destroyed at the end of the full-expression, temporaries bound to references do lifetime extension. In this case, <code class="sourceCode cpp">bar<span class="op">()</span></code> is a temporary of type <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>, which lasts until the end of the statement, <code class="sourceCode cpp">bar<span class="op">().</span><span class="cf">try</span><span class="op">?</span></code> gives you a <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code> which refers into that temporary - which will be bound to the parameter of <code class="sourceCode cpp">foo<span class="op">()</span></code> - but that’s safe because the <code class="sourceCode cpp">T</code> itself isn’t going to be destroyed until the <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code> is destroyed, which is after the call to <code class="sourceCode cpp">foo<span class="op">()</span></code> ends.</p>
<p>Note that this behavior is not really possible to express today using a statement rewrite. The inline macros for <code class="sourceCode cpp">bar<span class="op">().</span><span class="cf">try</span><span class="op">?</span></code> would do something like this:</p>
<blockquote>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1"></a><span class="kw">auto</span> a <span class="op">=</span> foo<span class="op">(</span></span>
<span id="cb19-2"><a href="#cb19-2"></a>    <span class="op">({</span></span>
<span id="cb19-3"><a href="#cb19-3"></a>        <span class="kw">auto</span> __tmp <span class="op">=</span> bar<span class="op">()</span>;</span>
<span id="cb19-4"><a href="#cb19-4"></a>        <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> __tmp<span class="op">)</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span>__tmp<span class="op">).</span>error<span class="op">()</span>;</span>
<span id="cb19-5"><a href="#cb19-5"></a>        <span class="op">*</span>__tmp;</span>
<span id="cb19-6"><a href="#cb19-6"></a>        <span class="co">// __tmp destroyed here</span></span>
<span id="cb19-7"><a href="#cb19-7"></a>    <span class="op">})</span></span>
<span id="cb19-8"><a href="#cb19-8"></a><span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>Using the statement-expression extension, the <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code> will actually be destroyed <em>before</em> the call to <code class="sourceCode cpp">foo</code>. This would give us a dangling reference, except that statement-expressions are always prvalues, so this would incur an extra (unnecessary) move of <code class="sourceCode cpp">T</code>. This can be seen more explicitly using the proposed <code class="sourceCode cpp"><span class="cf">do</span></code>-expression propsoal <span class="citation" data-cites="P2806R1">[<a href="#ref-P2806R1" role="doc-biblioref">P2806R1</a>]</span>:</p>
<blockquote>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1"></a><span class="kw">auto</span> a <span class="op">=</span> foo<span class="op">(</span><span class="cf">do</span> <span class="op">-&gt;</span> <em>TYPE</em> <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2"></a>    <span class="kw">auto</span> __tmp <span class="op">=</span> bar<span class="op">()</span>;</span>
<span id="cb20-3"><a href="#cb20-3"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> __tmp<span class="op">)</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span>__tmp<span class="op">).</span>error<span class="op">()</span>;</span>
<span id="cb20-4"><a href="#cb20-4"></a>    <span class="cf">do</span> <span class="cf">return</span> <span class="op">*</span>std<span class="op">::</span>move<span class="op">(</span>__tmp<span class="op">)</span>;</span>
<span id="cb20-5"><a href="#cb20-5"></a>    <span class="co">// __tmp destroyed here</span></span>
<span id="cb20-6"><a href="#cb20-6"></a><span class="op">})</span>;</span></code></pre></div>
</blockquote>
<p>Here, a <code class="sourceCode cpp"><span class="cf">do</span></code> expression can actually be a glvalue, so if <code class="sourceCode cpp"><em>TYPE</em></code> were <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>, then this would be a dangling reference. If <code class="sourceCode cpp"><em>TYPE</em></code> were <code class="sourceCode cpp">T</code>, then this would be fine - except that we’re incurring an extra move of <code class="sourceCode cpp">T</code> that wouldn’t strictly be necessary if we just held onto the <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code> for a little bit longer.</p>
<p>The coroutine rewrite wouldn’t have this problem, for the same reason the suggested <code class="sourceCode cpp">bar<span class="op">().</span><span class="cf">try</span><span class="op">?</span></code> approach doesn’t:</p>
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1"></a><span class="kw">auto</span> a <span class="op">=</span> foo<span class="op">(</span><span class="kw">co_await</span> bar<span class="op">())</span>;</span></code></pre></div>
</blockquote>
<p>Now consider:</p>
<blockquote>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> b <span class="op">=</span> quux<span class="op">().</span><span class="cf">try</span><span class="op">?</span>;</span></code></pre></div>
</blockquote>
<p>Here, extracting the value from <code class="sourceCode cpp">quux<span class="op">()</span></code> will give us a <code class="sourceCode cpp">U<span class="op">&amp;&amp;</span></code> that <code class="sourceCode cpp">b</code> binds to.</p>
<p>If this does not do lifetime extension, then the <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>U, E<span class="op">&gt;</span></code> is destroyed at the end of the statement. And we, once again, get a dangling reference. Note that this problem shows up either either of the macro propagation versions, all for the same reasons:</p>
<blockquote>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a>TRY<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> b, quux<span class="op">())</span>;  <span class="co">// dangles</span></span>
<span id="cb23-2"><a href="#cb23-2"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> b <span class="op">=</span> TRY<span class="op">(</span>quux<span class="op">())</span>; <span class="co">// doesn&#39;t dangle, but incurs an extra move of T</span></span></code></pre></div>
</blockquote>
<p>One way to avoid this issue is to have <code class="sourceCode cpp">extract_continue</code>, when given an rvalue, return a temporary instead of an rvalue reference. This has performance implications though - you get an extra move that may not be necessary.</p>
<p>But a better way would be to recognize this pattern in the language itself, and allow lifetime extension for this case. Because we can recognize this situation (binding a reference to the result of <code class="sourceCode cpp">E<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code>), we probably should.</p>
<p>That is:</p>
<blockquote>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a>TRY<span class="op">(</span>U<span class="op">&amp;&amp;</span> a, quux<span class="op">())</span>;  <span class="co">// dangles</span></span>
<span id="cb24-2"><a href="#cb24-2"></a>U<span class="op">&amp;&amp;</span> b <span class="op">=</span> TRY<span class="op">(</span>quux<span class="op">())</span>; <span class="co">// extra move</span></span>
<span id="cb24-3"><a href="#cb24-3"></a>U<span class="op">&amp;&amp;</span> c <span class="op">=</span> quux<span class="op">().</span><span class="cf">try</span><span class="op">?</span>; <span class="co">// lifetime-extends the temporary quux(), no extra move</span></span></code></pre></div>
</blockquote>
<p>Yet another advantage of the language feature.</p>
<h3 data-number="4.2.2" id="decltype"><span class="header-section-number">4.2.2</span> <code class="sourceCode cpp"><span class="kw">decltype</span></code><a href="#decltype" class="self-link"></a></h3>
<p>What does <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>E<span class="op">.</span><span class="cf">try</span><span class="op">?)</span></code> evaluate to? Even though there’s complex machinery going on here for actually propagating the error, the value type of <code class="sourceCode cpp">E<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> itself isn’t based on the return type of the function, it is based solely on <code class="sourceCode cpp">E</code>:</p>
<p>It is:</p>
<blockquote>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>try_traits<span class="op">&lt;</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>E<span class="op">)&gt;&gt;::</span>extract_continue<span class="op">(</span>E<span class="op">))</span></span></code></pre></div>
</blockquote>
<p>As such, while <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="kw">co_await</span> E<span class="op">)</span></code> is ill-formed, <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>E<span class="op">.</span><span class="cf">try</span><span class="op">?)</span></code> should be fine.</p>
<h3 data-number="4.2.3" id="requires"><span class="header-section-number">4.2.3</span> <code class="sourceCode cpp"><span class="kw">requires</span></code><a href="#requires" class="self-link"></a></h3>
<p>Consider this concept:</p>
<blockquote>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1"></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="cb26-2"><a href="#cb26-2"></a><span class="kw">concept</span> Try <span class="op">=</span> <span class="kw">requires</span> <span class="op">(</span>t t<span class="op">)</span> <span class="op">{</span> t<span class="op">.</span><span class="cf">try</span><span class="op">?</span>; <span class="op">}</span></span></code></pre></div>
</blockquote>
<p>With <code class="sourceCode cpp"><span class="kw">decltype</span></code>, the type of <code class="sourceCode cpp">E<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> is a function only of <code class="sourceCode cpp">E</code>. But in a broader context, the validity of the expression <code class="sourceCode cpp">E<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> is based on both <code class="sourceCode cpp">E</code> and the return type of the function. For instance:</p>
<blockquote>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1"></a><span class="kw">auto</span> try_something<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>;</span>
<span id="cb27-2"><a href="#cb27-2"></a></span>
<span id="cb27-3"><a href="#cb27-3"></a><span class="kw">auto</span> f<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>optional<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb27-4"><a href="#cb27-4"></a>    <span class="cf">return</span> std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;Got {}</span><span class="sc">\n</span><span class="st">&quot;</span>, try_something<span class="op">().</span><span class="cf">try</span><span class="op">?)</span>;</span>
<span id="cb27-5"><a href="#cb27-5"></a><span class="op">}</span></span>
<span id="cb27-6"><a href="#cb27-6"></a></span>
<span id="cb27-7"><a href="#cb27-7"></a><span class="kw">auto</span> g<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb27-8"><a href="#cb27-8"></a>    <span class="cf">return</span> try_something<span class="op">().</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb27-9"><a href="#cb27-9"></a><span class="op">}</span></span>
<span id="cb27-10"><a href="#cb27-10"></a></span>
<span id="cb27-11"><a href="#cb27-11"></a><span class="kw">auto</span> h<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb27-12"><a href="#cb27-12"></a>    <span class="cf">return</span> try_something<span class="op">().</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb27-13"><a href="#cb27-13"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>The usage in <code class="sourceCode cpp">f<span class="op">()</span></code> is fine, because both <code class="sourceCode cpp">optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code> and <code class="sourceCode cpp">optional<span class="op">&lt;</span>string<span class="op">&gt;</span></code> opt in to <code class="sourceCode cpp">try_traits</code>, and <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>optional<span class="op">&lt;</span>string<span class="op">&gt;&gt;::</span>from_break<span class="op">(</span>try_traits<span class="op">&lt;</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;&gt;::</span>extract_break<span class="op">(</span>try_something<span class="op">()))</span></code> is valid. Yes, that’s a mouthful.</p>
<p>But <code class="sourceCode cpp"><span class="dt">int</span></code> doesn’t opt-in to <code class="sourceCode cpp">try_traits</code> at all, and while <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span></code> does, its <code class="sourceCode cpp">from_break</code> would take a require something convertible to <code class="sourceCode cpp">std<span class="op">::</span>string</code>, which <code class="sourceCode cpp">std<span class="op">::</span>nullopt_t</code> is not. So both <code class="sourceCode cpp">g<span class="op">()</span></code> and <code class="sourceCode cpp">h<span class="op">()</span></code> must be ill-formed. Context is everything.</p>
<p>What does this say about what <code class="sourceCode cpp">Try<span class="op">&lt;</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;&gt;</span></code> should mean? I think it probably should be valid.</p>
<h2 data-number="4.3" id="other-use-cases"><span class="header-section-number">4.3</span> Other use-cases<a href="#other-use-cases" class="self-link"></a></h2>
<p>While the bulk of this paper up to this point is focused on the specific use case if propagating errors, there are several other uses for this kind of operator, which is part of why calling it an <em>error</em>-propagation operator specifically is not a good name.</p>
<h3 data-number="4.3.1" id="short-circuiting-fold"><span class="header-section-number">4.3.1</span> Short-circuiting fold<a href="#short-circuiting-fold" class="self-link"></a></h3>
<p>One of the algorithms considered in the <code class="sourceCode cpp">ranges<span class="op">::</span>fold</code> paper (<span class="citation" data-cites="P2322R5">[<a href="#ref-P2322R5" role="doc-biblioref">P2322R5</a>]</span>) was a short-circuiting fold. That paper ultimately didn’t propose such an algorithm, since there isn’t really a good way to generically write such a thing. Probably the best option in the paper was to have a mutating accumulation function that returns <code class="sourceCode cpp"><span class="dt">bool</span></code> on failure?</p>
<p>But with this facility, there is a clear direction for how to write a generic, short-circuiting fold:</p>
<blockquote>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1"></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="cb28-2"><a href="#cb28-2"></a><span class="kw">concept</span> Try <span class="op">=</span> <span class="kw">requires</span> <span class="op">(</span>T t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-3"><a href="#cb28-3"></a>    <span class="kw">typename</span> try_traits<span class="op">&lt;</span>T<span class="op">&gt;::</span>continue_type;</span>
<span id="cb28-4"><a href="#cb28-4"></a>    <span class="kw">typename</span> try_traits<span class="op">&lt;</span>T<span class="op">&gt;::</span>break_type;</span>
<span id="cb28-5"><a href="#cb28-5"></a></span>
<span id="cb28-6"><a href="#cb28-6"></a>    <span class="op">{</span> try_traits<span class="op">&lt;</span>T<span class="op">&gt;::</span>should_continue<span class="op">(</span>t<span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> <em>boolean-testable</em>;</span>
<span id="cb28-7"><a href="#cb28-7"></a>    <span class="co">// etc. ...</span></span>
<span id="cb28-8"><a href="#cb28-8"></a><span class="op">}</span>;</span>
<span id="cb28-9"><a href="#cb28-9"></a></span>
<span id="cb28-10"><a href="#cb28-10"></a><span class="kw">template</span> <span class="op">&lt;</span>input_iterator I,</span>
<span id="cb28-11"><a href="#cb28-11"></a>          sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S,</span>
<span id="cb28-12"><a href="#cb28-12"></a>          <span class="kw">class</span> T,</span>
<span id="cb28-13"><a href="#cb28-13"></a>          invocable<span class="op">&lt;</span>T, iter_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span> F,</span>
<span id="cb28-14"><a href="#cb28-14"></a>          Try Return <span class="op">=</span> invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, iter_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span></span>
<span id="cb28-15"><a href="#cb28-15"></a>    <span class="kw">requires</span> same_as<span class="op">&lt;</span></span>
<span id="cb28-16"><a href="#cb28-16"></a>        <span class="kw">typename</span> try_traits<span class="op">&lt;</span>Return<span class="op">&gt;::</span>continue_type,</span>
<span id="cb28-17"><a href="#cb28-17"></a>        T<span class="op">&gt;</span></span>
<span id="cb28-18"><a href="#cb28-18"></a><span class="kw">constexpr</span> <span class="kw">auto</span> try_fold<span class="op">(</span>I first, S last, T init, F accum<span class="op">)</span> <span class="op">-&gt;</span> Ret</span>
<span id="cb28-19"><a href="#cb28-19"></a><span class="op">{</span></span>
<span id="cb28-20"><a href="#cb28-20"></a>    <span class="cf">for</span> <span class="op">(</span>; first <span class="op">!=</span> last; <span class="op">++</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-21"><a href="#cb28-21"></a>        init <span class="op">=</span> std<span class="op">::</span>invoke<span class="op">(</span>accum,</span>
<span id="cb28-22"><a href="#cb28-22"></a>            std<span class="op">::</span>move<span class="op">(</span>init<span class="op">)</span>,</span>
<span id="cb28-23"><a href="#cb28-23"></a>            <span class="op">*</span>first<span class="op">).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb28-24"><a href="#cb28-24"></a>    <span class="op">}</span></span>
<span id="cb28-25"><a href="#cb28-25"></a></span>
<span id="cb28-26"><a href="#cb28-26"></a>    <span class="cf">return</span> try_traits<span class="op">&lt;</span>Ret<span class="op">&gt;::</span>from_continue<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>init<span class="op">))</span>;</span>
<span id="cb28-27"><a href="#cb28-27"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>This <code class="sourceCode cpp">try_fold</code> can be used with an accumulation function that returns <code class="sourceCode cpp">optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code> or <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code> or <code class="sourceCode cpp">boost<span class="op">::</span>outcome<span class="op">::</span>result<span class="op">&lt;</span>T<span class="op">&gt;</span></code> or … Any type that opts into being a <code class="sourceCode cpp">Try</code> will work.</p>
<p>Note that this may not be exactly the way we’d specify this algorithm, since we probably want to return something like a <code class="sourceCode cpp">pair<span class="op">&lt;</span>I, Ret<span class="op">&gt;</span></code> instead, so the body wouldn’t be able to use <code class="sourceCode cpp"><span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> and would have to go through <code class="sourceCode cpp">try_traits</code> manually for the error propogation. But that’s still okay, since the important part was being able to have a generic algorithm to begin with.</p>
<h3 data-number="4.3.2" id="pattern-matching"><span class="header-section-number">4.3.2</span> Pattern Matching<a href="#pattern-matching" class="self-link"></a></h3>
<p>One of the patterns proposed in the pattern matching papers <span class="citation" data-cites="P1371R3">[<a href="#ref-P1371R3" role="doc-biblioref">P1371R3</a>]</span> <span class="citation" data-cites="P2688R0">[<a href="#ref-P2688R0" role="doc-biblioref">P2688R0</a>]</span> is the dereference pattern (spelled <code class="sourceCode cpp"><span class="op">(*?)</span> <em>pattern</em></code> in the first paper and <code class="sourceCode cpp"><span class="op">?</span> <em>pattern</em></code> in the second). Rather than having that pattern be built on contextual conversion to bool and then dereference, it could be built on top of the customization point presented here as well.</p>
<h3 data-number="4.3.3" id="range-of-expected-to-expected-of-range"><span class="header-section-number">4.3.3</span> Range of <code class="sourceCode cpp">expected</code> to <code class="sourceCode cpp">expected</code> of Range<a href="#range-of-expected-to-expected-of-range" class="self-link"></a></h3>
<p>There’s an algorithm in Haskell called <code class="sourceCode cpp">sequence</code> which takes a <code class="sourceCode cpp">t <span class="op">(</span>m a<span class="op">)</span></code> and yields a <code class="sourceCode cpp">m <span class="op">(</span>t a<span class="op">)</span></code>. In C++ terms, that might be an algorithm that takes a range of <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code> and yields a <code class="sourceCode cpp">expected<span class="op">&lt;</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span>, E<span class="op">&gt;</span></code> - which contains either all the results or the first error.</p>
<p>With the same <code class="sourceCode cpp">Try</code> concept from a above, this can be generalized to also work for <code class="sourceCode cpp">optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code> or any number of other <code class="sourceCode cpp">Result</code>-like types:</p>
<blockquote>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1"></a><span class="kw">template</span> <span class="op">&lt;</span>ranges<span class="op">::</span>input_range R,</span>
<span id="cb29-2"><a href="#cb29-2"></a>          Try T <span class="op">=</span> remove_cvref_t<span class="op">&lt;</span>ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span>,</span>
<span id="cb29-3"><a href="#cb29-3"></a>          <span class="kw">typename</span> Traits <span class="op">=</span> try_traits<span class="op">&lt;</span>T<span class="op">&gt;</span>,</span>
<span id="cb29-4"><a href="#cb29-4"></a>          <span class="kw">typename</span> Result <span class="op">=</span> Traits<span class="op">::</span>rebind<span class="op">&lt;</span>vector<span class="op">&lt;</span><span class="kw">typename</span> Traits<span class="op">::</span>value_type<span class="op">&gt;&gt;&gt;</span></span>
<span id="cb29-5"><a href="#cb29-5"></a><span class="kw">auto</span> sequence<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span> <span class="op">-&gt;</span> Result</span>
<span id="cb29-6"><a href="#cb29-6"></a><span class="op">{</span></span>
<span id="cb29-7"><a href="#cb29-7"></a>    vector<span class="op">&lt;</span><span class="kw">typename</span> Traits<span class="op">::</span>value_type<span class="op">&gt;</span> results;</span>
<span id="cb29-8"><a href="#cb29-8"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> it <span class="op">=</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span>; it <span class="op">!=</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>; <span class="op">++</span>it<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-9"><a href="#cb29-9"></a>        results<span class="op">.</span>push_back<span class="op">((*</span>it<span class="op">).</span><span class="cf">try</span><span class="op">?)</span>;</span>
<span id="cb29-10"><a href="#cb29-10"></a>    <span class="op">}</span></span>
<span id="cb29-11"><a href="#cb29-11"></a>    <span class="cf">return</span> Result<span class="op">::</span>from_continue<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>results<span class="op">))</span>;</span>
<span id="cb29-12"><a href="#cb29-12"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<h3 data-number="4.3.4" id="internal-iteration"><span class="header-section-number">4.3.4</span> Internal iteration<a href="#internal-iteration" class="self-link"></a></h3>
<p>With internal iteration, using a sink function that gets pushed values (instead of having an iterator that pulls values), there is a need for the sink to indicate when to stop receiving values. That’s not an error, per se, that’s just a signal to break. Having a control flow propagation operator makes such generators much more convenient to write:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Current</strong>
</div></th>
<th><div style="text-align:center">
<strong>Proposed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1"></a><span class="kw">struct</span> generator123 <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">auto</span> sink<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb30-3"><a href="#cb30-3"></a>        std<span class="op">::</span>control_flow flow <span class="op">=</span> sink<span class="op">(</span><span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb30-4"><a href="#cb30-4"></a>        <span class="cf">if</span> <span class="op">(!</span>flow<span class="op">)</span> <span class="cf">return</span> flow;</span>
<span id="cb30-5"><a href="#cb30-5"></a></span>
<span id="cb30-6"><a href="#cb30-6"></a>        flow <span class="op">=</span> sink<span class="op">(</span><span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb30-7"><a href="#cb30-7"></a>        <span class="cf">if</span> <span class="op">(!</span>flow<span class="op">)</span> <span class="cf">return</span> flow;</span>
<span id="cb30-8"><a href="#cb30-8"></a></span>
<span id="cb30-9"><a href="#cb30-9"></a>        <span class="cf">return</span> sink<span class="op">(</span><span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb30-10"><a href="#cb30-10"></a>    <span class="op">}</span></span>
<span id="cb30-11"><a href="#cb30-11"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1"></a><span class="kw">struct</span> generator123 <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">auto</span> sink<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> control_flow <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3"></a>        sink<span class="op">(</span><span class="dv">1</span><span class="op">).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb31-4"><a href="#cb31-4"></a></span>
<span id="cb31-5"><a href="#cb31-5"></a></span>
<span id="cb31-6"><a href="#cb31-6"></a>        sink<span class="op">(</span><span class="dv">2</span><span class="op">).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb31-7"><a href="#cb31-7"></a></span>
<span id="cb31-8"><a href="#cb31-8"></a></span>
<span id="cb31-9"><a href="#cb31-9"></a>        <span class="cf">return</span> sink<span class="op">(</span><span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb31-10"><a href="#cb31-10"></a>    <span class="op">}</span></span>
<span id="cb31-11"><a href="#cb31-11"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1"></a><span class="kw">template</span> <span class="op">&lt;</span>range R, <span class="kw">class</span> Pred<span class="op">&gt;</span></span>
<span id="cb32-2"><a href="#cb32-2"></a><span class="kw">auto</span> filter<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, Pred pred<span class="op">)</span></span>
<span id="cb32-3"><a href="#cb32-3"></a><span class="op">{</span></span>
<span id="cb32-4"><a href="#cb32-4"></a>    <span class="cf">return</span> <span class="op">[</span>pred, <span class="op">&amp;</span>r<span class="op">](</span><span class="kw">auto</span> sink<span class="op">){</span></span>
<span id="cb32-5"><a href="#cb32-5"></a>        <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> elem <span class="op">:</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-6"><a href="#cb32-6"></a>            <span class="cf">if</span> <span class="op">(</span>pred<span class="op">(</span>elem<span class="op">))</span> <span class="op">{</span></span>
<span id="cb32-7"><a href="#cb32-7"></a>                <span class="kw">auto</span> result <span class="op">=</span> sink<span class="op">(</span>FWD<span class="op">(</span>elem<span class="op">))</span>;</span>
<span id="cb32-8"><a href="#cb32-8"></a>                <span class="cf">if</span> <span class="op">(</span>result <span class="op">==</span> break_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-9"><a href="#cb32-9"></a>                    <span class="cf">return</span> break_;</span>
<span id="cb32-10"><a href="#cb32-10"></a>                <span class="op">}</span></span>
<span id="cb32-11"><a href="#cb32-11"></a>            <span class="op">}</span></span>
<span id="cb32-12"><a href="#cb32-12"></a>        <span class="op">}</span></span>
<span id="cb32-13"><a href="#cb32-13"></a>        <span class="cf">return</span> continue_;</span>
<span id="cb32-14"><a href="#cb32-14"></a>    <span class="op">}</span>;</span>
<span id="cb32-15"><a href="#cb32-15"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1"></a><span class="kw">template</span> <span class="op">&lt;</span>range R, <span class="kw">class</span> Pred<span class="op">&gt;</span></span>
<span id="cb33-2"><a href="#cb33-2"></a><span class="kw">auto</span> filter<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, Pred pred<span class="op">)</span></span>
<span id="cb33-3"><a href="#cb33-3"></a><span class="op">{</span></span>
<span id="cb33-4"><a href="#cb33-4"></a>    <span class="cf">return</span> <span class="op">[</span>pred, <span class="op">&amp;</span>r<span class="op">](</span><span class="kw">auto</span> sink<span class="op">)</span> <span class="op">-&gt;</span> control_flow <span class="op">{</span></span>
<span id="cb33-5"><a href="#cb33-5"></a>        <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> elem <span class="op">:</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-6"><a href="#cb33-6"></a>            <span class="cf">if</span> <span class="op">(</span>pred<span class="op">(</span>elem<span class="op">))</span> <span class="op">{</span></span>
<span id="cb33-7"><a href="#cb33-7"></a>                sink<span class="op">(</span>FWD<span class="op">(</span>elem<span class="op">)).</span><span class="cf">try</span><span class="op">?</span>;</span>
<span id="cb33-8"><a href="#cb33-8"></a></span>
<span id="cb33-9"><a href="#cb33-9"></a></span>
<span id="cb33-10"><a href="#cb33-10"></a></span>
<span id="cb33-11"><a href="#cb33-11"></a>            <span class="op">}</span></span>
<span id="cb33-12"><a href="#cb33-12"></a>        <span class="op">}</span></span>
<span id="cb33-13"><a href="#cb33-13"></a>        <span class="cf">return</span> continue_;</span>
<span id="cb33-14"><a href="#cb33-14"></a>    <span class="op">}</span>;</span>
<span id="cb33-15"><a href="#cb33-15"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>See <span class="citation" data-cites="P2881R0">[<a href="#ref-P2881R0" role="doc-biblioref">P2881R0</a>]</span> for more information.</p>
<h3 data-number="4.3.5" id="naming"><span class="header-section-number">4.3.5</span> Naming<a href="#naming" class="self-link"></a></h3>
<p>Because we don’t have a proper language customization mechanism, we need to have two distinct things:</p>
<ul>
<li>a class template that contains all the functionality (which I’m naming here <code class="sourceCode cpp">std<span class="op">::</span>try_traits</code>)</li>
<li>a <code class="sourceCode cpp"><span class="kw">concept</span></code> that checks if this class template is (a) specialized (b) correctly (which I’m naming here… <code class="sourceCode cpp">Try</code>)</li>
</ul>
<p>I think it’s unfortunate that we need two different names for this, but that’s the way of things at the moment. Also I have no idea what a good name for this <code class="sourceCode cpp"><span class="kw">concept</span></code> is. Rust calls this <code class="sourceCode cpp">Try</code>, but we want our concepts to be <code class="sourceCode cpp">snake_case</code>, and <code class="sourceCode cpp"><span class="cf">try</span></code> is not an option. I’m open to suggestion.</p>
<h2 data-number="4.4" id="potential-directions-to-go-from-here"><span class="header-section-number">4.4</span> Potential directions to go from here<a href="#potential-directions-to-go-from-here" class="self-link"></a></h2>
<p>This paper is proposing just <code class="sourceCode cpp"><span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> and the machinery necessary to make that work (including a <code class="sourceCode cpp"><span class="kw">concept</span></code>, opt-ins for <code class="sourceCode cpp">optional</code> and <code class="sourceCode cpp">expected</code>, but not the short-circuiting fold algorithm).</p>
<p>However, it’s worth it for completeness to point out a few other directions that such an operator can take us.</p>
<h3 data-number="4.4.1" id="error-continuations"><span class="header-section-number">4.4.1</span> Error continuations<a href="#error-continuations" class="self-link"></a></h3>
<p>Several languages have a facility that allows for continuing to invoke member functions on optional values. This facility is called something different in every language (optional chaining in Swift, null-conditional operator in C#, safe call operator in Kotlin), but somehow it’s all spelled the same and does the same thing anyway.</p>
<p>Given a <code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span></code> named <code class="sourceCode cpp">opt</code>, what that operator – spelled <code class="sourceCode cpp"><span class="op">?.</span></code> – means is approximately:</p>
<table>
<colgroup>
<col style="width: 25%"></col>
<col style="width: 75%"></col>
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>expression</strong>
</div></th>
<th><div style="text-align:center">
<strong>C++ equivalent</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode cpp">opt<span class="op">?.</span>size<span class="op">()</span></code></td>
<td><code class="sourceCode cpp">opt<span class="op">.</span>transform<span class="op">(&amp;</span>std<span class="op">::</span>string<span class="op">::</span>size<span class="op">)</span> <span class="co">// technically UB</span></code></td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp">opt<span class="op">?.</span>substr<span class="op">(</span>from, to<span class="op">)</span></code></td>
<td><code class="sourceCode cpp">opt<span class="op">.</span>transform<span class="op">([&amp;](</span><span class="kw">auto</span><span class="op">&amp;</span> s<span class="op">){</span> <span class="cf">return</span> s<span class="op">.</span>substr<span class="op">(</span>from, to<span class="op">)</span>; <span class="op">})</span></code></td>
</tr>
</tbody>
</table>
<p>Like the null coalescing meaning of <code class="sourceCode cpp"><span class="op">??</span></code> <a href="#in-other-languages">described above</a>, the semantics of <code class="sourceCode cpp">opt<span class="op">?.</span>f<span class="op">()</span></code> can be achieved using library facilities today. The expression <code class="sourceCode cpp">E1<span class="op">?.</span>E2</code>, if <code class="sourceCode cpp">E1</code> is an <code class="sourceCode cpp">optional</code>, basically means <code class="sourceCode cpp">E1<span class="op">.</span>transform<span class="op">([&amp;](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> e<span class="op">){</span> <span class="cf">return</span> FWD<span class="op">(</span>e<span class="op">).</span>E2; <span class="op">})</span></code></p>
<p>Quite unlike <code class="sourceCode cpp"><span class="op">??</span></code>, there is a significant drop in readability and just the general nice-ness of the syntax.</p>
<p>The <code class="sourceCode cpp">try_traits</code> facility very nearly gives us the tools necessary to support such a continuation operator. Since what we need to do is:</p>
<ul>
<li>check is <code class="sourceCode cpp">E1</code> is truthy or falsey (<code class="sourceCode cpp">Traits<span class="op">::</span>should_continue<span class="op">(</span>E1<span class="op">)</span></code>)</li>
<li>extract the value of <code class="sourceCode cpp">E1</code> in order to perform the subsequent operation (<code class="sourceCode cpp">Traits<span class="op">::</span>extract_continue<span class="op">(</span>E1<span class="op">).</span>E2</code>)</li>
<li>extract the error of <code class="sourceCode cpp">E1</code> in order to return early (<code class="sourceCode cpp">Traits<span class="op">::</span>extract_break<span class="op">(</span>E2<span class="op">)</span></code>)</li>
</ul>
<p>We mostly need one more customization point: to put the types back together. What I mean is, consider:</p>
<blockquote>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1"></a><span class="kw">auto</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>string, E<span class="op">&gt;</span>;</span>
<span id="cb34-2"><a href="#cb34-2"></a></span>
<span id="cb34-3"><a href="#cb34-3"></a><span class="kw">auto</span> x <span class="op">=</span> f<span class="op">(</span><span class="dv">42</span><span class="op">)?.</span>size<span class="op">()</span>;</span></code></pre></div>
</blockquote>
<p>The type of <code class="sourceCode cpp">x</code> needs to be <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">size_t</span>, E<span class="op">&gt;</span></code>, since that’s what the value case ends up being here. If we call that customization point <code class="sourceCode cpp">rebind</code>, as in:</p>
<blockquote>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> E<span class="op">&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2"></a><span class="kw">struct</span> try_traits<span class="op">&lt;</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb35-3"><a href="#cb35-3"></a>    <span class="co">// ... rest as before ...</span></span>
<span id="cb35-4"><a href="#cb35-4"></a></span>
<span id="cb35-5"><a href="#cb35-5"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb35-6"><a href="#cb35-6"></a>    <span class="kw">using</span> rebind <span class="op">=</span> expected<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>U<span class="op">&gt;</span>, E<span class="op">&gt;</span>;</span>
<span id="cb35-7"><a href="#cb35-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>Then the above can be desugared into:</p>
<blockquote>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1"></a><span class="kw">using</span> <em>_Traits</em> <span class="op">=</span> try_traits<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>f<span class="op">(</span><span class="dv">42</span><span class="op">))&gt;&gt;</span>;</span>
<span id="cb36-2"><a href="#cb36-2"></a><span class="kw">using</span> <em>_R</em> <span class="op">=</span> <em>_Traits</em><span class="op">::</span>rebind<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><em>_Traits</em><span class="op">::</span>extract_continue<span class="op">(</span>f<span class="op">(</span><span class="dv">42</span><span class="op">)).</span>size<span class="op">())&gt;</span>;</span>
<span id="cb36-3"><a href="#cb36-3"></a></span>
<span id="cb36-4"><a href="#cb36-4"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <em>e</em> <span class="op">=</span> f<span class="op">(</span><span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb36-5"><a href="#cb36-5"></a><span class="kw">auto</span> x <span class="op">=</span> <em>_Traits</em><span class="op">::</span>should_continue<span class="op">(</span><em>e</em><span class="op">)</span></span>
<span id="cb36-6"><a href="#cb36-6"></a>       <span class="op">?</span> try_traits<span class="op">&lt;</span><em>_R</em><span class="op">&gt;::</span>from_continue<span class="op">(</span><em>_Traits</em><span class="op">::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span><em>e</em><span class="op">)).</span>size<span class="op">())</span></span>
<span id="cb36-7"><a href="#cb36-7"></a>       <span class="op">:</span> try_traits<span class="op">&lt;</span><em>_R</em><span class="op">&gt;::</span>from_break<span class="op">(</span><em>_Traits</em><span class="op">::</span>extract_break<span class="op">(</span>FWD<span class="op">(</span><em>e</em><span class="op">)))</span>;</span></code></pre></div>
</blockquote>
<p>That may seem like a mouthful. Because it is a mouthful. But it’s a mouthful that the user doesn’t have to write any part of, they just put <code class="sourceCode cpp">f<span class="op">(</span><span class="dv">42</span><span class="op">)?.</span>size<span class="op">()</span></code> and this does do the right thing.</p>
<p>At least, this mostly does the right thing. We still have to talk about copy elision. Consider this version:</p>
<blockquote>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb37-2"><a href="#cb37-2"></a>    <span class="kw">auto</span> f<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>mutex;</span>
<span id="cb37-3"><a href="#cb37-3"></a><span class="op">}</span>;</span>
<span id="cb37-4"><a href="#cb37-4"></a></span>
<span id="cb37-5"><a href="#cb37-5"></a><span class="kw">auto</span> g<span class="op">()</span> <span class="op">-&gt;</span> Result<span class="op">&lt;</span>X, E<span class="op">&gt;</span>;</span>
<span id="cb37-6"><a href="#cb37-6"></a><span class="kw">auto</span> n <span class="op">=</span> g<span class="op">()?.</span>f<span class="op">()</span>;</span></code></pre></div>
</blockquote>
<p>Presumably, <code class="sourceCode cpp">n</code> is a <code class="sourceCode cpp">Result<span class="op">&lt;</span>std<span class="op">::</span>mutex, E<span class="op">&gt;</span></code>, but in order for this to work, we can’t just evaluate this as something like <code class="sourceCode cpp">Result<span class="op">&lt;</span>std<span class="op">::</span>mutex, E<span class="op">&gt;(</span>g<span class="op">().</span>value<span class="op">().</span>f<span class="op">())</span></code>. <code class="sourceCode cpp">std<span class="op">::</span>mutex</code> isn’t movable.</p>
<p>The only way for this to work today is be able to pass a callable all the way through into this <code class="sourceCode cpp">Result</code>’s constructor. Which is to say, we desugar like so:</p>
<blockquote>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <em>e</em> <span class="op">=</span> g<span class="op">()</span>;</span>
<span id="cb38-2"><a href="#cb38-2"></a><span class="kw">auto</span> n <span class="op">=</span> <em>_Traits</em><span class="op">::</span>should_continue<span class="op">(</span><em>e</em><span class="op">)</span></span>
<span id="cb38-3"><a href="#cb38-3"></a>       <span class="op">?</span> try_traits<span class="op">&lt;</span><em>_R</em><span class="op">&gt;::</span>from_continue_func<span class="op">([&amp;]()</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-4"><a href="#cb38-4"></a>            <span class="cf">return</span> <em>_Traits</em><span class="op">::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span><em>e</em><span class="op">)).</span>f<span class="op">()</span></span>
<span id="cb38-5"><a href="#cb38-5"></a>         <span class="op">})</span></span>
<span id="cb38-6"><a href="#cb38-6"></a>       <span class="op">:</span> try_traits<span class="op">&lt;</span><em>_R</em><span class="op">&gt;::</span>from_break<span class="op">(</span><em>_Traits</em><span class="op">::</span>extract_break<span class="op">(</span>FWD<span class="op">(</span><em>e</em><span class="op">)))</span>;</span></code></pre></div>
</blockquote>
<p>By default, <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>R<span class="op">&gt;::</span>from_continue_func<span class="op">(</span>f<span class="op">)</span></code> would just be <code class="sourceCode cpp">try_traits<span class="op">&lt;</span>R<span class="op">&gt;::</span>from_continue<span class="op">(</span>f<span class="op">())</span></code>.</p>
<p>This is weird, but it’s something to think about.</p>
<p>Note also error continuation would only help in the member function or member variable cases. If we want to continue into a non-member function, you’d need the sort of <code class="sourceCode cpp"><span class="op">.</span>transform<span class="op">()</span></code> member function anyway.</p>
<h3 data-number="4.4.2" id="not-propagating-errors"><span class="header-section-number">4.4.2</span> Not propagating errors<a href="#not-propagating-errors" class="self-link"></a></h3>
<p>The <code class="sourceCode cpp"><span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> approach seems to work quite well at propagating errors: it’s syntactically cheap, performant, and allows for integrating multiple libraries.</p>
<p>But what if we didn’t want to propagate the error, but rather do something else with it? For <code class="sourceCode cpp">std<span class="op">::</span>optional</code> and <code class="sourceCode cpp">std<span class="op">::</span>expected</code>, we already have a UB-if-error accessor in the form of <code class="sourceCode cpp"><span class="op">*</span>x</code> and a throw-if-error accessor in the form of <code class="sourceCode cpp">x<span class="op">.</span>value<span class="op">()</span></code>. It seems like the corollary to an error-propagating <code class="sourceCode cpp">x<span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> would be some sort of <code class="sourceCode cpp">x<span class="op">.</span><span class="cf">try</span><span class="op">!</span></code> that somehow forces the error differently.</p>
<p>While propagating the error only really has one way to go (you return it), there are quite a few different things you can do differently:</p>
<ul>
<li><code class="sourceCode cpp"><span class="ot">assert</span></code> that <code class="sourceCode cpp">should_continue<span class="op">()</span></code></li>
<li><code class="sourceCode cpp">abort<span class="op">()</span></code> if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code></li>
<li><code class="sourceCode cpp">terminate<span class="op">()</span></code> if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code></li>
<li><code class="sourceCode cpp">unreachable<span class="op">()</span></code> (or <code class="sourceCode cpp"><span class="op">[[</span><span class="at">assume</span><span class="op">]]</span></code>) if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code></li>
<li><code class="sourceCode cpp"><span class="cf">throw</span> extract_break<span class="op">()</span></code> if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code></li>
<li><code class="sourceCode cpp"><span class="cf">throw</span> f<span class="op">(</span>extract_break<span class="op">())</span></code> if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code> for some <code class="sourceCode cpp">f</code></li>
<li>log an error and come up with some default value if <code class="sourceCode cpp"><span class="kw">not</span> should_continue<span class="op">()</span></code></li>
</ul>
<p>That’s a lot of different options, and the right one likely depends on context too.</p>
<p>An additional template parameter on the error type could drive what <code class="sourceCode cpp">x<span class="op">.</span><span class="cf">try</span><span class="op">!</span></code> does (as Boost.Outcome does, for instance), which would allow you to preserve the nice syntax if a particular error handling strategy is sufficiently common (maybe you always <code class="sourceCode cpp"><span class="cf">throw</span></code>, so why would you want to write extra syntax for this case), but at a cost of suddenly having way more types. Although the <code class="sourceCode cpp">try_traits</code> approach does at least allow those “way more types” to interact well.</p>
<p>This behavior can be achieved by adding a new function to <code class="sourceCode cpp">try_traits</code> which desugars as follows:</p>
<table>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1"></a><span class="kw">auto</span> val <span class="op">=</span> expr<span class="op">.</span><span class="cf">try</span><span class="op">!</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <em>__val</em> <span class="op">=</span> expr;</span>
<span id="cb40-2"><a href="#cb40-2"></a><span class="kw">using</span> <em>_Traits</em> <span class="op">=</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span></span>
<span id="cb40-3"><a href="#cb40-3"></a>  std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><em>__val</em><span class="op">)&gt;&gt;</span>;</span>
<span id="cb40-4"><a href="#cb40-4"></a><span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> <em>_Traits</em><span class="op">::</span>should_continue<span class="op">(</span><em>__val</em><span class="op">))</span> <span class="op">{</span></span>
<span id="cb40-5"><a href="#cb40-5"></a>  <em>_Traits</em><span class="op">::</span>fail<span class="op">(</span>FWD<span class="op">(</span><em>__val</em><span class="op">))</span>;</span>
<span id="cb40-6"><a href="#cb40-6"></a><span class="op">}</span></span>
<span id="cb40-7"><a href="#cb40-7"></a><span class="kw">auto</span> val <span class="op">=</span> <em>_Traits</em><span class="op">::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span><em>__val</em><span class="op">))</span>;</span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>But this doesn’t seem as valuable as <code class="sourceCode cpp"><span class="op">.</span><span class="cf">try</span><span class="op">?</span></code> or even <code class="sourceCode cpp">e<span class="op">?.</span>x</code> since this case is easy to add as a member function. Indeed, that’s what <code class="sourceCode cpp">x<span class="op">.</span>value<span class="op">()</span></code> and <code class="sourceCode cpp"><span class="op">*</span>x</code> do for <code class="sourceCode cpp">optional</code> and <code class="sourceCode cpp">expected</code> (throw and undefined behavior, respectively).</p>
<p>Moreover, any of the kinds of behavior you want can be written as a free function:</p>
<blockquote>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, Try U <span class="op">=</span> std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb41-2"><a href="#cb41-2"></a><span class="kw">auto</span> narrow_value<span class="op">(</span>T<span class="op">&amp;&amp;</span> t<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-3"><a href="#cb41-3"></a>    <span class="ot">assert</span><span class="op">(</span>std<span class="op">::</span>try_traits<span class="op">&lt;</span>U<span class="op">&gt;::</span>should_continue<span class="op">(</span>t<span class="op">))</span>;</span>
<span id="cb41-4"><a href="#cb41-4"></a>    <span class="cf">return</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span>U<span class="op">&gt;::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span>t<span class="op">))</span>;</span>
<span id="cb41-5"><a href="#cb41-5"></a><span class="op">}</span></span>
<span id="cb41-6"><a href="#cb41-6"></a></span>
<span id="cb41-7"><a href="#cb41-7"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, Try U <span class="op">=</span> std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb41-8"><a href="#cb41-8"></a><span class="kw">auto</span> wide_value<span class="op">(</span>T<span class="op">&amp;&amp;</span> t<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-9"><a href="#cb41-9"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span>U<span class="op">&gt;::</span>should_continue<span class="op">(</span>t<span class="op">))</span> <span class="op">{</span></span>
<span id="cb41-10"><a href="#cb41-10"></a>        <span class="op">[[</span><span class="at">unlikely</span><span class="op">]]</span> <span class="cf">throw</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span>U<span class="op">&gt;::</span>extact_error<span class="op">(</span>FWD<span class="op">(</span>t<span class="op">))</span>;</span>
<span id="cb41-11"><a href="#cb41-11"></a>    <span class="op">}</span></span>
<span id="cb41-12"><a href="#cb41-12"></a>    <span class="cf">return</span> std<span class="op">::</span>try_traits<span class="op">&lt;</span>U<span class="op">&gt;::</span>extract_continue<span class="op">(</span>FWD<span class="op">(</span>t<span class="op">))</span>;</span>
<span id="cb41-13"><a href="#cb41-13"></a><span class="op">}</span></span>
<span id="cb41-14"><a href="#cb41-14"></a></span>
<span id="cb41-15"><a href="#cb41-15"></a><span class="co">// etc.</span></span></code></pre></div>
</blockquote>
<p>Which further demonstrates the utility of the proposed facility.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-P0323R12">
<p>[P0323R12] Vicente Botet, JF Bastien, Jonathan Wakely. 2022-01-07. std::expected. <br />
<a href="https://wg21.link/p0323r12">https://wg21.link/p0323r12</a></p>
</div>
<div id="ref-P0709R4">
<p>[P0709R4] Herb Sutter. 2019-08-04. Zero-overhead deterministic exceptions: Throwing values. <br />
<a href="https://wg21.link/p0709r4">https://wg21.link/p0709r4</a></p>
</div>
<div id="ref-P0779R0">
<p>[P0779R0] Niall Douglas. 2017-10-15. Proposing operator try() (with added native C++ macro functions!). <br />
<a href="https://wg21.link/p0779r0">https://wg21.link/p0779r0</a></p>
</div>
<div id="ref-P1371R3">
<p>[P1371R3] Michael Park, Bruno Cardoso Lopes, Sergei Murzin, David Sankel, Dan Sarginson, Bjarne Stroustrup. 2020-09-15. Pattern Matching. <br />
<a href="https://wg21.link/p1371r3">https://wg21.link/p1371r3</a></p>
</div>
<div id="ref-P2218R0">
<p>[P2218R0] Marc Mutz. 2020-09-15. More flexible optional::value_or(). <br />
<a href="https://wg21.link/p2218r0">https://wg21.link/p2218r0</a></p>
</div>
<div id="ref-P2322R5">
<p>[P2322R5] Barry Revzin. 2021-10-18. ranges::fold. <br />
<a href="https://wg21.link/p2322r5">https://wg21.link/p2322r5</a></p>
</div>
<div id="ref-P2481R1">
<p>[P2481R1] Barry Revzin. 2022-07-15. Forwarding reference to specific type/template. <br />
<a href="https://wg21.link/p2481r1">https://wg21.link/p2481r1</a></p>
</div>
<div id="ref-P2505R4">
<p>[P2505R4] Jeff Garland. 2022-06-17. Monadic Functions for std::expected. <br />
<a href="https://wg21.link/p2505r4">https://wg21.link/p2505r4</a></p>
</div>
<div id="ref-P2561R0">
<p>[P2561R0] Barry Revzin. 2022-07-11. operator?? <br />
<a href="https://wg21.link/p2561r0">https://wg21.link/p2561r0</a></p>
</div>
<div id="ref-P2561R1">
<p>[P2561R1] Barry Revzin. 2022-10-11. An error propagation operator. <br />
<a href="https://wg21.link/p2561r1">https://wg21.link/p2561r1</a></p>
</div>
<div id="ref-P2688R0">
<p>[P2688R0] Michael Park. 2022-10-16. Pattern Matching Discussion for Kona 2022. <br />
<a href="https://wg21.link/p2688r0">https://wg21.link/p2688r0</a></p>
</div>
<div id="ref-P2806R1">
<p>[P2806R1] Barry Revzin, Bruno Cardoso Lopez, Zach Laine, Michael Park. 2023-03-12. do expressions. <br />
<a href="https://wg21.link/p2806r1">https://wg21.link/p2806r1</a></p>
</div>
<div id="ref-P2881R0">
<p>[P2881R0] Jonathan Müller and Barry Revzin. 2023-05-18. Generator-based for loop. <br />
<a href="https://isocpp.org/files/papers/P2881R0.html">https://isocpp.org/files/papers/P2881R0.html</a></p>
</div>
</div>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Outcome’s <code class="sourceCode cpp">TRY</code> macro uses preprocessor overloading so void results don’t get assigned e.g. <code class="sourceCode cpp">TRY<span class="op">(</span><span class="kw">auto</span> x, expr<span class="op">)</span></code> sets <code class="sourceCode cpp">x</code> to <code class="sourceCode cpp">expr<span class="op">.</span>value<span class="op">()</span></code> while <code class="sourceCode cpp">TRY<span class="op">(</span>expr<span class="op">)</span></code> ignores <code class="sourceCode cpp">expr<span class="op">.</span>value<span class="op">()</span></code>. <code class="sourceCode cpp">TRVA</code> and <code class="sourceCode cpp">TRYV</code> <em>require</em> <code class="sourceCode cpp">expr</code> to have a value or for the value to be ignored respectively. One of them gets called by <code class="sourceCode cpp">TRY<span class="op">()</span></code>depending on argument count supplied.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
