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

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Pattern Matching:
<em>variant-like</em> and <code class="sourceCode cpp">std<span class="op">::</span>expected</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>
      P3527R1
      [<a href="https://wg21.link/P3527">Latest</a>]
      [<a href="https://wg21.link/P3527/status">Status</a>]
    </td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-01-13</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>
      Evolution<br>
      Library Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Michael Park<br>&lt;<a href="mailto:mcypark@gmail.com" class="email">mcypark@gmail.com</a>&gt;<br>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#motivation-and-scope" id="toc-motivation-and-scope"><span class="toc-section-number">1</span> Motivation and
Scope<span></span></a>
<ul>
<li><a href="#the-variant-protocol" id="toc-the-variant-protocol"><span class="toc-section-number">1.1</span> The Variant
Protocol<span></span></a></li>
</ul></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">2</span> Design<span></span></a>
<ul>
<li><a href="#optional-additions" id="toc-optional-additions"><span class="toc-section-number">2.1</span> Optional
additions<span></span></a></li>
<li><a href="#not-included-modifying-stdvisit" id="toc-not-included-modifying-stdvisit"><span class="toc-section-number">2.2</span> Not included: modifying
<code class="sourceCode cpp">std<span class="op">::</span>visit</code><span></span></a></li>
<li><a href="#a-note-about-stdbad_variant_access" id="toc-a-note-about-stdbad_variant_access"><span class="toc-section-number">2.3</span> A note about <code class="sourceCode cpp">std<span class="op">::</span>bad_variant_access</code><span></span></a></li>
</ul></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">3</span> Proposed
Wording<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">4</span> Implementation
Experience<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="motivation-and-scope"><span class="header-section-number">1</span> Motivation and Scope<a href="#motivation-and-scope" class="self-link"></a></h1>
<p><span class="citation" data-cites="P2688R3"><a href="https://wg21.link/p2688r3" role="doc-biblioref">[P2688R3]</a></span> introduces pattern matching
for C++, including handling of
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>s.
For example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> v <span class="op">=</span> std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int32_t</span>, <span class="dt">int64_t</span>, <span class="dt">float</span>, <span class="dt">double</span><span class="op">&gt;{</span><span class="co">/* ... */</span><span class="op">}</span>;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int32_t</span><span class="op">:</span> <span class="cf">let</span> i32 <span class="op">=&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got int32: {}&quot;</span>, i32<span class="op">)</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int64_t</span><span class="op">:</span> <span class="cf">let</span> i64 <span class="op">=&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got int64: {}&quot;</span>, i64<span class="op">)</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span><span class="op">:</span> <span class="cf">let</span> f <span class="op">=&gt;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got float: {}&quot;</span>, f<span class="op">)</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">double</span><span class="op">:</span> <span class="cf">let</span> d <span class="op">=&gt;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got double: {}&quot;</span>, d<span class="op">)</span>;</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>However, there is an unsupported type in the standard that is
variant-like but is not covered by <span class="citation" data-cites="P2688R3"><a href="https://wg21.link/p2688r3" role="doc-biblioref">[P2688R3]</a></span> without explicit library
support. That type is <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p>
<p>This proposal does not interact with the pattern matching language
feature, nor does it interact with user defined types; it only affects
whether <code class="sourceCode cpp">std<span class="op">::</span>expected</code>
interoperates gracefully with the language feature.</p>
<p>This paper adds library facilities that allow <code class="sourceCode cpp">std<span class="op">::</span>expected</code> to
conform to the notion of variant-like used in the pattern matching core
wording. In order to accomplish this, we propose to add an API for <code class="sourceCode cpp">std<span class="op">::</span>expected</code> that
is syntactically and semantically equivalent to the API used by pattern
matching to match
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>s.</p>
<h2 data-number="1.1" id="the-variant-protocol"><span class="header-section-number">1.1</span> The Variant Protocol<a href="#the-variant-protocol" class="self-link"></a></h2>
<p>The language semantics for pattern matching (<span class="citation" data-cites="P2688R3"><a href="https://wg21.link/p2688r3" role="doc-biblioref">[P2688R3]</a></span>) include the notion of a
“variant protocol”. This is analogous to the tuple protocol used for
structured bindings. The tuple protocol is used in defining the behavior
of pattern matching as well.</p>
<p>This section does not describe a library change, and is not part of
this proposal. It is here to describe the relevant language part of the
pattern matching design, since that language design informs the library
design in this paper.</p>
<p>To match based on the currently-engaged value of a variant-like
object <code class="sourceCode cpp">v</code> of type
<code class="sourceCode cpp">V</code>, the pattern matching language
feature uses <code class="sourceCode cpp">std<span class="op">::</span>variant_size<span class="op">&lt;</span>V<span class="op">&gt;</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>variant_alternative<span class="op">&lt;</span>V<span class="op">&gt;</span></code>,
<code class="sourceCode cpp">get<span class="op">&lt;</span>I<span class="op">&gt;(</span>v<span class="op">)</span></code>,
and <code class="sourceCode cpp">v<span class="op">.</span>index<span class="op">()</span></code>.
<code class="sourceCode cpp">get<span class="op">()</span></code> is
used via ADL-only calls. The template parameter passed to
<code class="sourceCode cpp">get<span class="op">()</span></code> is a
<code class="sourceCode cpp"><span class="dt">size_t</span></code> NTTP,
not a type.</p>
<h1 data-number="2" id="design"><span class="header-section-number">2</span> Design<a href="#design" class="self-link"></a></h1>
<p>The minimal design is this.</p>
<ul>
<li><p>Add an
<code class="sourceCode cpp">index<span class="op">()</span></code>
member function to <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
<li><p>Add specializations of <code class="sourceCode cpp">std<span class="op">::</span>variant_size</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>variant_alternative</code>
that work with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
<li><p>Add
<code class="sourceCode cpp"><span class="dt">size_t</span></code>-parameter
overloads of
<code class="sourceCode cpp">std<span class="op">::</span>get</code>
that work with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
</ul>
<p>By making these changes, <code class="sourceCode cpp">std<span class="op">::</span>expected</code> will
be compatible with
<code class="sourceCode cpp"><span class="cf">match</span></code>
expressions wherever
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
is.</p>
<h2 data-number="2.1" id="optional-additions"><span class="header-section-number">2.1</span> Optional additions<a href="#optional-additions" class="self-link"></a></h2>
<p>The changes above make <code class="sourceCode cpp">std<span class="op">::</span>expected</code> very
close to
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
in many ways, but there are a few ways in which the two differ. Since
the main design above brings them into such near-alignment, it might be
useful to add even more compatability, so that the user can treat
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
and <code class="sourceCode cpp">std<span class="op">::</span>expected</code> as
equivalent in most generic code. The optional changes are:</p>
<ul>
<li><p>Add a version of <code class="sourceCode cpp">std<span class="op">::</span>holds_alternative<span class="op">()</span></code>
that works with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
<li><p>Add type overloads of
<code class="sourceCode cpp">std<span class="op">::</span>get</code>
that work with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
<li><p>Add overloads of
<code class="sourceCode cpp">std<span class="op">::</span>get_if</code>
that work with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p></li>
</ul>
<p>The costs of wording and implementing these additions is low, so they
seem like good additions for the sake of consistency.</p>
<h2 data-number="2.2" id="not-included-modifying-stdvisit"><span class="header-section-number">2.2</span> Not included: modifying
<code class="sourceCode cpp">std<span class="op">::</span>visit</code><a href="#not-included-modifying-stdvisit" class="self-link"></a></h2>
<p>The list of optional additions above leaves out a pretty important
API –
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>.
These are the reasons the authors chose not to include it.</p>
<ol type="1">
<li><p><code class="sourceCode cpp">std<span class="op">::</span>expected</code> is
fixed at two alternatives. No one would write
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>
when they can simply write
<code class="sourceCode cpp"><span class="cf">if</span></code>, unless
perhaps they were handling variant-like types generically, in which
case…</p></li>
<li><p>…, the advent of pattern matching as a language feature means we
can use that for generic handling of variant-like types. No one has to
write
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>
ever again, and that’s for the better.</p></li>
<li><p>There was an increased-complexity cost (and associated compile
time cost) to implementing
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>
support for <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.
This stems from the fact that
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>
takes a variadic pack of variants. If some elements of the pack were
also allowed to be <code class="sourceCode cpp">std<span class="op">::</span>expected</code>s,
there would have to be compile-time conditional handling for these two
types added to each element of the pack.</p></li>
</ol>
<p>The benefits are nearly zero, and the costs are non-zero. Worse
still, the costs apply to code that never uses <code class="sourceCode cpp">std<span class="op">::</span>expected</code> with
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>,
which violates the “don’t pay for what you don’t use” principle.</p>
<h2 data-number="2.3" id="a-note-about-stdbad_variant_access"><span class="header-section-number">2.3</span> A note about <code class="sourceCode cpp">std<span class="op">::</span>bad_variant_access</code><a href="#a-note-about-stdbad_variant_access" class="self-link"></a></h2>
<p>Much of the API proposed here is throwing. Each throwing function
throws <code class="sourceCode cpp">std<span class="op">::</span>bad_variant_access</code>,
same as the ones that work with
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>.
There exists another exception type associated with <code class="sourceCode cpp">std<span class="op">::</span>expected</code>,
<code class="sourceCode cpp">std<span class="op">::</span>bad_expected_access</code>.
However, this is the wrong type to use. <code class="sourceCode cpp">std<span class="op">::</span>bad_expected_access</code>
is thrown when the user attempts to access the value of an
<code class="sourceCode cpp">expected</code>, when that
<code class="sourceCode cpp">expected</code> has an error engaged, not a
value.</p>
<h1 data-number="3" id="proposed-wording"><span class="header-section-number">3</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<p>Add to the end of <span>22.8.2
<a href="https://wg21.link/expected.syn">[expected.syn]</a></span>:</p>
<div>
<div class="sourceCode" id="cb2"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ // [expected.helper], expected helper class specializations</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, class E&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct variant_size&lt;expected&lt;T, E&gt;&gt;;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct variant_alternative&lt;I, expected&lt;T, E&gt;&gt;;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="va">+ // [expected.get], value access</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr bool holds_alternative(const expected&lt;T, E&gt;&amp;) noexcept;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(expected&lt;T, E&gt;&amp;);                                          // freestanding-deleted</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;&amp;</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(expected&lt;T, E&gt;&amp;&amp;);                                         // freestanding-deleted</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(const expected&lt;T, E&gt;&amp;);                                    // freestanding-deleted</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;&amp;</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(const expected&lt;T, E&gt;&amp;&amp;);                                   // freestanding-deleted</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr T&amp; get(expected&lt;T, E&gt;&amp;);                               // freestanding-deleted</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr T&amp;&amp; get(expected&lt;T, E&gt;&amp;&amp;);                             // freestanding-deleted</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const T&amp; get(const expected&lt;T, E&gt;&amp;);                   // freestanding-deleted</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const T&amp;&amp; get(const expected&lt;T, E&gt;&amp;&amp;);                 // freestanding-deleted</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&gt;</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(expected&lt;T, E&gt;*) noexcept;</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&gt;</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(const expected&lt;T, E&gt;*) noexcept;</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;T&gt;</span></span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(expected&lt;T, E&gt;*) noexcept;</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;const T&gt;</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(const expected&lt;T, E&gt;*) noexcept;</span></span></code></pre></div>
</div>
<p>Add a new member function <code class="sourceCode cpp">index</code>
to <span>22.8.6.1
<a href="https://wg21.link/expected.object.general">[expected.object.general]</a></span></p>
<h3 class="unnumbered unlisted" id="expected.object.general-general"><span>22.8.6.1
<a href="https://wg21.link/expected.object.general">[expected.object.general]</a></span>
General<a href="#expected.object.general-general" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb3"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>namespace std {</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  template&lt;class T, class E&gt;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  class expected {</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  public:</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    ...</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    // [expected.object.obs], observers</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    ...</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    template&lt;class U&gt; constexpr T value_or(U&amp;&amp;) const &amp;;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    template&lt;class U&gt; constexpr T value_or(U&amp;&amp;) &amp;&amp;;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    template&lt;class G = E&gt; constexpr E error_or(G&amp;&amp;) const &amp;;</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    template&lt;class G = E&gt; constexpr E error_or(G&amp;&amp;) &amp;&amp;;</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr size_t index() const noexcept;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    ...</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
<p>Add a new member function <code class="sourceCode cpp">index</code>
to <span>22.8.6.6
<a href="https://wg21.link/expected.object.obs">[expected.object.obs]</a></span></p>
<h3 class="unnumbered unlisted" id="expected.object.obs-observers"><span>22.8.6.6
<a href="https://wg21.link/expected.object.obs">[expected.object.obs]</a></span>
Observers<a href="#expected.object.obs-observers" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr size_t index() const noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">26</a></span>
<em>Returns</em>:
<code class="sourceCode default">has_value() ? 0 : 1</code>.</p>
</div>
<p>Add a new member function <code class="sourceCode cpp">index</code>
to <span>22.8.7.1
<a href="https://wg21.link/expected.void.general">[expected.void.general]</a></span></p>
<h3 class="unnumbered unlisted" id="expected.void.general-general"><span>22.8.7.1
<a href="https://wg21.link/expected.void.general">[expected.void.general]</a></span>
General<a href="#expected.void.general-general" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb5"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T, class E&gt; requires is_void_v&lt;T&gt;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>class expected {</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>public:</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  ...</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  // [expected.void.obs], observers</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  ...</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  template&lt;class G = E&gt; constexpr E error_or(G&amp;&amp;) const &amp;;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>  template&lt;class G = E&gt; constexpr E error_or(G&amp;&amp;) &amp;&amp;;</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr size_t index() const noexcept;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>   ...</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a> };</span></code></pre></div>
</div>
<p>Add a new member function <code class="sourceCode cpp">index</code>
to <span>22.8.7.6
<a href="https://wg21.link/expected.void.obs">[expected.void.obs]</a></span></p>
<h3 class="unnumbered unlisted" id="expected.void.obs-observers"><span>22.8.7.6
<a href="https://wg21.link/expected.void.obs">[expected.void.obs]</a></span>
Observers<a href="#expected.void.obs-observers" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr size_t index() const noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Returns</em>:
<code class="sourceCode default">has_value() ? 0 : 1</code>.</p>
</div>
<p>Add a new section [expected.helpers] after <span>22.8.7.8
<a href="https://wg21.link/expected.void.eq">[expected.void.eq]</a></span>:</p>
<h3 class="unnumbered unlisted" id="expected.helpers-expected-helper-class-specializations">22.8.7.8+1
[expected.helpers] <code class="sourceCode cpp">expected</code> helper
class specializations<a href="#expected.helpers-expected-helper-class-specializations" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb7"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, class E&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct variant_size&lt;expected&lt;T, E&gt;&gt; : integral_constant&lt;size_t, 2&gt; { };</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct variant_alternative&lt;I, expected&lt;T, E&gt;&gt; {</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     using type = <em>see below</em> ;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   };</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Mandates</em>: <code class="sourceCode default">I &lt; 2</code></p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Type</em>: The type is <code class="sourceCode default">T</code> if
<code class="sourceCode default">I</code> is
<code class="sourceCode default">0</code>. Otherwise, the type is
<code class="sourceCode default">E</code>.</p>
</div>
<p>Add a new section [expected.helpers] after <span>22.8.7.8
<a href="https://wg21.link/expected.void.eq">[expected.void.eq]</a></span>:</p>
<h3 class="unnumbered unlisted" id="expected.get-value-access">22.8.7.8+2 [expected.get] Value access<a href="#expected.get-value-access" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb8"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr bool holds_alternative(const expected&lt;T, E&gt;&amp; e) noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Returns</em>: <code class="sourceCode default">true</code> if <code class="sourceCode default">e.index() == 0 &amp;&amp; e.has_value()</code>
is <code class="sourceCode default">true</code>, or if <code class="sourceCode default">e.index() == 1 &amp;&amp; e.has_error()</code>
is <code class="sourceCode default">true</code>. Otherwise, returns
<code class="sourceCode default">false</code>.</p>
</div>
<div>
<div class="sourceCode" id="cb9"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(expected&lt;T, E&gt;&amp; e);                                          // freestanding-deleted</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;&amp;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(expected&lt;T, E&gt;&amp;&amp; e);                                         // freestanding-deleted</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(const expected&lt;T, E&gt;&amp; e);                                    // freestanding-deleted</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&amp;&amp;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="va">+     get(const expected&lt;T, E&gt;&amp;&amp; e);                                   // freestanding-deleted</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Mandates</em>: <code class="sourceCode default">I &lt; 2</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Throws</em>:
<code class="sourceCode default">bad_variant_access</code> if
<code class="sourceCode default">e.index() != I</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Returns</em>: <code class="sourceCode default">*e</code> if
<code class="sourceCode default">has_value()</code> is
<code class="sourceCode default">true</code>, and
<code class="sourceCode default">e.error()</code> otherwise.</p>
</div>
<div>
<div class="sourceCode" id="cb10"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr T&amp; get(expected&lt;T, E&gt;&amp; e);                               // freestanding-deleted</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr T&amp;&amp; get(expected&lt;T, E&gt;&amp;&amp; e);                             // freestanding-deleted</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const T&amp; get(const expected&lt;T, E&gt;&amp; e);                   // freestanding-deleted</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr const T&amp;&amp; get(const expected&lt;T, E&gt;&amp;&amp; e);                 // freestanding-deleted</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Effects</em>: If <code class="sourceCode default">e</code> holds a
value of type <code class="sourceCode default">U</code>, returns a
reference to that value. Otherwise, throws an exception of type
<code class="sourceCode default">bad_variant_access</code>.</p>
</div>
<div>
<div class="sourceCode" id="cb11"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(expected&lt;T, E&gt;* e) noexcept;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;size_t I, class T, class E&gt;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;const variant_alternative_t&lt;I, expected&lt;T, E&gt;&gt;&gt;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(const expected&lt;T, E&gt;* e) noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Mandates</em>: <code class="sourceCode default">I &lt; 2</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Returns</em>: A pointer to the value stored in the expected, if
<code class="sourceCode default">e != nullptr</code> and
<code class="sourceCode default">v-&gt;index() == I</code>. Otherwise,
returns <code class="sourceCode default">nullptr</code>.</p>
</div>
<div>
<div class="sourceCode" id="cb12"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;T&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(expected&lt;T, E&gt;* e) noexcept;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class U, class T, class E&gt;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr add_pointer_t&lt;const T&gt;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     get_if(const expected&lt;T, E&gt;* e) noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Effects</em>: If <code class="sourceCode default">e</code> holds a
value of type <code class="sourceCode default">U</code>, returns a
pointer to that value. Otherwise, returns
<code class="sourceCode default">nullptr</code>.</p>
</div>
<h1 data-number="4" id="implementation-experience"><span class="header-section-number">4</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>One of the authors implemented all the changes proposed here in a
branch of Clang/libc++. The implementation was straightforward, and
posed no unforseen challenges. The changes did not cause any of the
pre-existing libc++ tests to fail.</p>
<p>The changes can be found <a href="https://github.com/mpark/llvm-project/pull/1">here</a>.</p>
<h1 data-number="5" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-P2688R3" class="csl-entry" role="doc-biblioentry">
[P2688R3] Michael Park. 2024-10-16. Pattern Matching: `match`
Expression. <a href="https://wg21.link/p2688r3"><div class="csl-block">https://wg21.link/p2688r3</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
