<!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="2024-09-17" />
  <title>Pattern Matching: `match` Expression</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:
<code class="sourceCode cpp"><span class="cf">match</span></code>
Expression</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2688R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-09-17</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      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>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#updates-since-r1" id="toc-updates-since-r1"><span class="toc-section-number">1</span> Updates since
R1<span></span></a></li>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">2</span> Introduction<span></span></a></li>
<li><a href="#motivation-and-scope" id="toc-motivation-and-scope"><span class="toc-section-number">3</span> Motivation and
Scope<span></span></a></li>
<li><a href="#comparison-tables" id="toc-comparison-tables"><span class="toc-section-number">4</span> Comparison Tables<span></span></a>
<ul>
<li><a href="#matching-integrals" id="toc-matching-integrals"><span class="toc-section-number">4.1</span> Matching
Integrals<span></span></a></li>
<li><a href="#matching-strings" id="toc-matching-strings"><span class="toc-section-number">4.2</span> Matching
Strings<span></span></a></li>
<li><a href="#matching-tuples" id="toc-matching-tuples"><span class="toc-section-number">4.3</span> Matching
Tuples<span></span></a></li>
<li><a href="#matching-variants" id="toc-matching-variants"><span class="toc-section-number">4.4</span> Matching
Variants<span></span></a></li>
<li><a href="#matching-polymorphic-types" id="toc-matching-polymorphic-types"><span class="toc-section-number">4.5</span> Matching Polymorphic
Types<span></span></a></li>
<li><a href="#matching-nested-structures" id="toc-matching-nested-structures"><span class="toc-section-number">4.6</span> Matching Nested
Structures<span></span></a></li>
</ul></li>
<li><a href="#design-overview" id="toc-design-overview"><span class="toc-section-number">5</span> Design Overview<span></span></a>
<ul>
<li><a href="#syntax-overview" id="toc-syntax-overview"><span class="toc-section-number">5.1</span> Syntax
Overview<span></span></a></li>
<li><a href="#pattern-specifications" id="toc-pattern-specifications"><span class="toc-section-number">5.2</span> Pattern
Specifications<span></span></a>
<ul>
<li><a href="#wildcard-pattern" id="toc-wildcard-pattern"><span class="toc-section-number">5.2.1</span> Wildcard
Pattern<span></span></a></li>
<li><a href="#let-pattern" id="toc-let-pattern"><span class="toc-section-number">5.2.2</span> Let
Pattern<span></span></a></li>
<li><a href="#constant-pattern" id="toc-constant-pattern"><span class="toc-section-number">5.2.3</span> Constant
Pattern<span></span></a></li>
<li><a href="#parenthesized-pattern" id="toc-parenthesized-pattern"><span class="toc-section-number">5.2.4</span> Parenthesized
Pattern<span></span></a></li>
<li><a href="#optional-pattern" id="toc-optional-pattern"><span class="toc-section-number">5.2.5</span> Optional
Pattern<span></span></a></li>
<li><a href="#alternative-pattern" id="toc-alternative-pattern"><span class="toc-section-number">5.2.6</span> Alternative
Pattern<span></span></a></li>
<li><a href="#structured-bindings-pattern" id="toc-structured-bindings-pattern"><span class="toc-section-number">5.2.7</span> Structured Bindings
Pattern<span></span></a></li>
</ul></li>
<li><a href="#scope-of-bindings" id="toc-scope-of-bindings"><span class="toc-section-number">5.3</span> Scope of
Bindings<span></span></a></li>
<li><a href="#static-and-dynamic-conditions" id="toc-static-and-dynamic-conditions"><span class="toc-section-number">5.4</span> Static and Dynamic
Conditions<span></span></a>
<ul>
<li><a href="#static-conditions" id="toc-static-conditions"><span class="toc-section-number">5.4.1</span> Static
Conditions<span></span></a></li>
<li><a href="#dynamic-conditions" id="toc-dynamic-conditions"><span class="toc-section-number">5.4.2</span> Dynamic
Conditions<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">6</span> Proposed Wording<span></span></a>
<ul>
<li><a href="#language" id="toc-language"><span class="toc-section-number">6.1</span> Language<span></span></a></li>
</ul></li>
<li><a href="#design-decisions-and-discussions" id="toc-design-decisions-and-discussions"><span class="toc-section-number">7</span> Design Decisions and
Discussions<span></span></a>
<ul>
<li><a href="#unified-match-expression" id="toc-unified-match-expression"><span class="toc-section-number">7.1</span> Unified
<code class="sourceCode cpp"><span class="cf">match</span></code>
Expression<span></span></a></li>
<li><a href="#wildcard-pattern-syntax" id="toc-wildcard-pattern-syntax"><span class="toc-section-number">7.2</span> Wildcard Pattern
Syntax<span></span></a></li>
<li><a href="#why-we-want-expressions-in-patterns" id="toc-why-we-want-expressions-in-patterns"><span class="toc-section-number">7.3</span> Why We Want Expressions in
Patterns<span></span></a></li>
<li><a href="#exploration-of-variable-declaration-syntax-for-alternative-pattern" id="toc-exploration-of-variable-declaration-syntax-for-alternative-pattern"><span class="toc-section-number">7.4</span> Exploration of Variable
Declaration Syntax for Alternative Pattern<span></span></a></li>
<li><a href="#discussion-on-variant-like-types" id="toc-discussion-on-variant-like-types"><span class="toc-section-number">7.5</span> Discussion on Variant-like
Types<span></span></a></li>
<li><a href="#reflection-based-tuple-like-and-variant-like-customization-points" id="toc-reflection-based-tuple-like-and-variant-like-customization-points"><span class="toc-section-number">7.6</span> Reflection-based Tuple-like and
Variant-like Customization Points<span></span></a></li>
<li><a href="#more-on-static-conditions" id="toc-more-on-static-conditions"><span class="toc-section-number">7.7</span> More on Static
Conditions<span></span></a></li>
<li><a href="#operator-precedence-of-match" id="toc-operator-precedence-of-match"><span class="toc-section-number">7.8</span> Operator Precedence of
<code class="sourceCode cpp"><span class="cf">match</span></code><span></span></a>
<ul>
<li><a href="#proposed-solution-between-pointer-to-member-and-multiplicative-operator" id="toc-proposed-solution-between-pointer-to-member-and-multiplicative-operator"><span class="toc-section-number">7.8.1</span> Proposed Solution: Between
Pointer-to-member and Multiplicative Operator<span></span></a></li>
<li><a href="#alternative-considered-between-spaceship-and-relational-operator" id="toc-alternative-considered-between-spaceship-and-relational-operator"><span class="toc-section-number">7.8.2</span> Alternative Considered: Between
Spaceship and Relational Operator<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#future-extension-exploration" id="toc-future-extension-exploration"><span class="toc-section-number">8</span> Future Extension
Exploration<span></span></a>
<ul>
<li><a href="#static-type-checking-with-constraint-pattern" id="toc-static-type-checking-with-constraint-pattern"><span class="toc-section-number">8.1</span> Static Type Checking with
Constraint Pattern<span></span></a></li>
<li><a href="#testing-the-static-conditions-with-match-requires" id="toc-testing-the-static-conditions-with-match-requires"><span class="toc-section-number">8.2</span> Testing the Static Conditions with
<code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code><span></span></a></li>
<li><a href="#pattern-combinators" id="toc-pattern-combinators"><span class="toc-section-number">8.3</span> Pattern
Combinators<span></span></a></li>
<li><a href="#designator-support-for-structured-bindings" id="toc-designator-support-for-structured-bindings"><span class="toc-section-number">8.4</span> Designator Support for Structured
Bindings<span></span></a></li>
<li><a href="#value-based-discriminators" id="toc-value-based-discriminators"><span class="toc-section-number">8.5</span> Value-based
discriminators<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">9</span> Implementation
Experience<span></span></a>
<ul>
<li><a href="#parsing-the-match-operator" id="toc-parsing-the-match-operator"><span class="toc-section-number">9.1</span> Parsing the
<code class="sourceCode cpp"><span class="cf">match</span></code>
operator<span></span></a></li>
<li><a href="#parsing-the-parenthesized-pattern" id="toc-parsing-the-parenthesized-pattern"><span class="toc-section-number">9.2</span> Parsing the Parenthesized
Pattern<span></span></a></li>
</ul></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">10</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">11</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="updates-since-r1"><span class="header-section-number">1</span> Updates since R1<a href="#updates-since-r1" class="self-link"></a></h1>
<ul>
<li>Gained further <a href="#implementation-experience">Implementation
Experience</a></li>
<li>Started on <a href="#proposed-wording">Proposed Wording</a></li>
<li>Defined <a href="#operator-precedence-of-match">Operator Precedence
of
<code class="sourceCode cpp"><span class="cf">match</span></code></a></li>
<li>Decided against proposing a reflection-based tuple-like and
variant-like protocols.</li>
</ul>
<h1 data-number="2" id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This paper fleshes out the version of pattern matching that was
described in <span class="citation" data-cites="P2688R0">[<a href="https://wg21.link/p2688r0" role="doc-biblioref">P2688R0</a>]</span>. It introduces a unified
<code class="sourceCode cpp"><span class="cf">match</span></code>
expression that can perform a single pattern match using the syntax:</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><em>expression</em> <span class="cf">match</span> <em>pattern</em></span></code></pre></div>
<p>as well as the selection of pattern matches using the following
syntax:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><em>expression</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <span class="op">=&gt;</span> <em>expression-statement</em></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">/* ... */</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A single pattern match yields a boolean, and therefore can be used in
other contexts such as
<code class="sourceCode cpp"><span class="cf">if</span></code>,
<code class="sourceCode cpp"><span class="cf">while</span></code>,
<code class="sourceCode cpp"><span class="cf">for</span></code>, and
<code class="sourceCode cpp"><span class="kw">requires</span></code>.</p>
<p><code class="sourceCode cpp"><span class="cf">let</span></code> is
used to introduce new names within patterns, and are always “bindings”
like the ones introduced by structured bindings in C++17 <span class="citation" data-cites="P0144R2">[<a href="https://wg21.link/p0144r2" role="doc-biblioref">P0144R2</a>]</span>.</p>
<p>The set of patterns are trimmed down to match the following
entities:</p>
<ol type="1">
<li>Values
(e.g. <code class="sourceCode cpp"><span class="dv">42</span></code>,
<code class="sourceCode cpp"><span class="st">&quot;hello&quot;</span></code>,
<code class="sourceCode cpp">compute_value<span class="op">()</span></code>)</li>
<li>Pointer-like types
(e.g. <code class="sourceCode cpp">T<span class="op">*</span></code>,
<code class="sourceCode cpp">optional</code>)</li>
<li>Tuple-like types, extending structured bindings
(e.g. <code class="sourceCode cpp">pair</code>,
<code class="sourceCode cpp">tuple</code>)</li>
<li>Sum types (e.g. <code class="sourceCode cpp">variant</code>,
<code class="sourceCode cpp">expected</code>,
<code class="sourceCode cpp">any</code>,
<code class="sourceCode cpp">exception_ptr</code>, polymorphic
types)</li>
</ol>
<h1 data-number="3" id="motivation-and-scope"><span class="header-section-number">3</span> Motivation and Scope<a href="#motivation-and-scope" class="self-link"></a></h1>
<p>The goal and motivation of this paper is to make further progress on
pattern matching for C++.</p>
<p>At the Kona meeting in November 2022, the previous version of this
paper <span class="citation" data-cites="P2688R0">[<a href="https://wg21.link/p2688r0" role="doc-biblioref">P2688R0</a>]</span> and <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span> was discussed over whether
patterns should be composed vs chained. EWG clearly expressed the desire
for patterns to be composable (i.e. nested patterns):</p>
<blockquote>
<p>Poll: “EWG prefers composition over chaining in pattern matching
syntax.”</p>
<p>Result: SF: 13, F: 9, N: 2, A: 1, SA: 0</p>
</blockquote>
<p>This paper presents (as did <span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span>) a design that continues to
offer composable patterns.</p>
<p>At the EWG Telecon July 7, 2021, EWG clearly expressed the desire for
pattern matching to be available outside of
<code class="sourceCode cpp"><span class="cf">inspect</span></code>:</p>
<blockquote>
<p>Poll: “Should we spend more time on patmat expressions outside of
<code class="sourceCode cpp"><span class="cf">inspect</span></code> (as
proposed in P2392 or otherwise), knowing that time is limited and we
already have put in a lot of effort towards another patmat
proposal?”</p>
<p>Result: SF: 11, F: 12, N:4, A: 2, SA: 0</p>
</blockquote>
<p>This paper offers single pattern matching via <code class="sourceCode cpp"><em>expression</em> <span class="cf">match</span> <em>pattern</em></code>
which is similar to the
<code class="sourceCode cpp"><span class="cf">is</span></code>-expression
from <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span>. See</p>
<p>Additionally, it aims to address the following pieces of
feedback:</p>
<blockquote>
<p>“Declaration of new names should have an introducer like most other
places in the language.”</p>
</blockquote>
<p>New names need the
<code class="sourceCode cpp"><span class="cf">let</span></code>
introducer to introduce bindings, just like other new names in most
other places in the language.</p>
<blockquote>
<p>“We shouldn’t bifurcate expressions like this.”</p>
</blockquote>
<p>That is, expressions are just expressions without needing anything
everywhere else in the language. This is true in this design. That is,
<code class="sourceCode cpp">x</code> by itself is an expression
referring to an existing name like it does everywhere else.</p>
<blockquote>
<p>“I don’t want the documentation of pattern matching to have to
mention a caveat that <code class="sourceCode cpp">x</code> is a new
name and therefore shadows an existing variable.”</p>
</blockquote>
<p>As mentioned above, <code class="sourceCode cpp">x</code> is an
expression that refers to an existing variable.</p>
<p>Another contribution of this paper is <a href="#static-and-dynamic-conditions">Static and Dynamic Conditions</a>,
which aim to more clearly specify and discuss the framework of
requirements for patterns. They determine how uses of patterns are
checked and/or tested at compile-time and/or runtime, within template
contexts and outside.</p>
<p>Features such as predicates, extractors, structured bindings with
designators, static type matching by type or concepts, and pattern
combinators
<code class="sourceCode cpp"><span class="kw">and</span></code> and
<code class="sourceCode cpp"><span class="kw">or</span></code> are
proposed to be deferred as future extensions.</p>
<p>The following is a list of key goals of the paper:</p>
<ul>
<li>Introduce
<code class="sourceCode cpp"><span class="cf">match</span></code>
expression with
<code class="sourceCode cpp"><span class="cf">let</span></code>
bindings.</li>
<li>Trim down the set of patterns to focus on.</li>
<li>Allow pattern matching in more places.</li>
<li>Determine how patterns should be treated in templates.</li>
</ul>
<h1 data-number="4" id="comparison-tables"><span class="header-section-number">4</span> Comparison Tables<a href="#comparison-tables" class="self-link"></a></h1>
<p>The following are 4-way comparison tables between C++23, <span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span>, <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span>, and this paper.</p>
<h2 data-number="4.1" id="matching-integrals"><span class="header-section-number">4.1</span> Matching Integrals<a href="#matching-integrals" class="self-link"></a></h2>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="cf">switch</span> <span class="op">(</span>x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">0</span><span class="op">:</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got zero&quot;</span><span class="op">)</span>; <span class="cf">break</span>;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">case</span> <span class="dv">1</span><span class="op">:</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got one&quot;</span><span class="op">)</span>; <span class="cf">break</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">default</span><span class="op">:</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got zero&quot;</span><span class="op">)</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got one&quot;</span><span class="op">)</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  __ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> <span class="dv">0</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got zero&quot;</span><span class="op">)</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> <span class="dv">1</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got one&quot;</span><span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> _ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>x <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got zero&quot;</span><span class="op">)</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got one&quot;</span><span class="op">)</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="4.2" id="matching-strings"><span class="header-section-number">4.2</span> Matching Strings<a href="#matching-strings" class="self-link"></a></h2>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>s <span class="op">==</span> <span class="st">&quot;foo&quot;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got foo&quot;</span><span class="op">)</span>;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>s <span class="op">==</span> <span class="st">&quot;bar&quot;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got bar&quot;</span><span class="op">)</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="st">&quot;foo&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got foo&quot;</span><span class="op">)</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="st">&quot;bar&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got bar&quot;</span><span class="op">)</span>;</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  __ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> <span class="st">&quot;foo&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got foo&quot;</span><span class="op">)</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> <span class="st">&quot;bar&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got bar&quot;</span><span class="op">)</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> _ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>s <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="st">&quot;foo&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got foo&quot;</span><span class="op">)</span>;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="st">&quot;bar&quot;</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got bar&quot;</span><span class="op">)</span>;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;don&#39;t care&quot;</span><span class="op">)</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="4.3" id="matching-tuples"><span class="header-section-number">4.3</span> Matching Tuples<a href="#matching-tuples" class="self-link"></a></h2>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=</span> p;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> <span class="dv">0</span> <span class="op">&amp;&amp;</span> y <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on origin&quot;</span><span class="op">)</span>;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on y-axis at {}&quot;</span>, y<span class="op">)</span>;</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>y <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on x-axis at {}&quot;</span>, x<span class="op">)</span>;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;at {}, {}&quot;</span>, x, y<span class="op">)</span>;</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on origin&quot;</span><span class="op">)</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, y<span class="op">]</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on y-axis at {}&quot;</span>, y<span class="op">)</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>x, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on x-axis at {}&quot;</span>, x<span class="op">)</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;at {}, {}&quot;</span>, x, y<span class="op">)</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> <span class="op">[</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on origin&quot;</span><span class="op">)</span>;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>_, y<span class="op">]</span> <span class="cf">is</span> <span class="op">[</span><span class="dv">0</span>, _<span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on y-axis at {}&quot;</span>, y<span class="op">)</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>x, _<span class="op">]</span> <span class="cf">is</span> <span class="op">[</span>_, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on x-axis at {}&quot;</span>, x<span class="op">)</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>x, y<span class="op">]</span> <span class="cf">is</span> _ <span class="op">=&gt;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;at {}, {}&quot;</span>, x, y<span class="op">)</span>;</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>p <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on origin&quot;</span><span class="op">)</span>;</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> y<span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on y-axis at {}&quot;</span>, y<span class="op">)</span>;</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="cf">let</span> x, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;on x-axis at {}&quot;</span>, x<span class="op">)</span>;</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=&gt;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;at {}, {}&quot;</span>, x, y<span class="op">)</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="4.4" id="matching-variants"><span class="header-section-number">4.4</span> Matching Variants<a href="#matching-variants" class="self-link"></a></h2>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> visitor <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int32_t</span> i32<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3" 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="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int64_t</span> i64<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb15-6"><a href="#cb15-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="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">float</span> f<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb15-9"><a href="#cb15-9" 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="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">double</span> d<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb15-12"><a href="#cb15-12" 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="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>visit<span class="op">(</span>visitor<span class="op">{}</span>, v<span class="op">)</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span><span class="dt">int32_t</span><span class="op">&gt;</span> i32 <span class="op">=&gt;</span></span>
<span id="cb16-3"><a href="#cb16-3" 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="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span><span class="dt">int64_t</span><span class="op">&gt;</span> i64 <span class="op">=&gt;</span></span>
<span id="cb16-5"><a href="#cb16-5" 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="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;</span> f <span class="op">=&gt;</span></span>
<span id="cb16-7"><a href="#cb16-7" 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="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;</span> d <span class="op">=&gt;</span></span>
<span id="cb16-9"><a href="#cb16-9" 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="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  i32 <span class="cf">as</span> <span class="dt">int32_t</span> <span class="op">=&gt;</span></span>
<span id="cb17-3"><a href="#cb17-3" 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="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  i64 <span class="cf">as</span> <span class="dt">int64_t</span> <span class="op">=&gt;</span></span>
<span id="cb17-5"><a href="#cb17-5" 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="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>  f <span class="cf">as</span> <span class="dt">float</span> <span class="op">=&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7" 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="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>  d <span class="cf">as</span> <span class="dt">double</span> <span class="op">=&gt;</span></span>
<span id="cb17-9"><a href="#cb17-9" 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="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" 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="cb18-3"><a href="#cb18-3" 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="cb18-4"><a href="#cb18-4" 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="cb18-5"><a href="#cb18-5" 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="cb18-6"><a href="#cb18-6" 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="cb18-7"><a href="#cb18-7" 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="cb18-8"><a href="#cb18-8" 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="cb18-9"><a href="#cb18-9" 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="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>This example is matching the variant alternatives using concepts.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> visitor <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>integral <span class="kw">auto</span> i<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got integral: {}&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>floating_point <span class="kw">auto</span> f<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-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="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>visit<span class="op">(</span>visitor<span class="op">{}</span>, v<span class="op">)</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>std<span class="op">::</span>integral<span class="op">&gt;</span> i <span class="op">=&gt;</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got integral: {}&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>std<span class="op">::</span>floating_point<span class="op">&gt;</span> f <span class="op">=&gt;</span></span>
<span id="cb20-5"><a href="#cb20-5" 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="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="co">// not supported</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>integral<span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;got integral: {}&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>floating_point<span class="op">:</span> <span class="cf">let</span> f <span class="op">=&gt;</span></span>
<span id="cb22-5"><a href="#cb22-5" 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="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="4.5" id="matching-polymorphic-types"><span class="header-section-number">4.5</span> Matching Polymorphic Types<a href="#matching-polymorphic-types" class="self-link"></a></h2>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Shape <span class="op">{</span> <span class="kw">virtual</span> <span class="op">~</span>Shape<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="op">}</span>;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Circle <span class="op">:</span> Shape <span class="op">{</span> <span class="dt">int</span> radius; <span class="op">}</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Rectangle <span class="op">:</span> Shape <span class="op">{</span> <span class="dt">int</span> width, height; <span class="op">}</span>;</span></code></pre></div>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">virtual</span> <span class="dt">int</span> Shape<span class="op">::</span>get_area<span class="op">()</span> <span class="kw">const</span> <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> Circle<span class="op">::</span>get_area<span class="op">()</span> <span class="kw">const</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="fl">3.14</span> <span class="op">*</span> radius <span class="op">*</span> radius;</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> Rectangle<span class="op">::</span>get_area<span class="op">()</span> <span class="kw">const</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> width <span class="op">*</span> height;</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> get_area<span class="op">(</span><span class="kw">const</span> Shape<span class="op">&amp;</span> shape<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="cf">inspect</span> <span class="op">(</span>shape<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>Circle<span class="op">&gt;</span> <span class="op">[</span>r<span class="op">]</span> <span class="op">=&gt;</span> <span class="fl">3.14</span> <span class="op">*</span> r <span class="op">*</span> r;</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>Rectangle<span class="op">&gt;</span> <span class="op">[</span>w, h<span class="op">]</span> <span class="op">=&gt;</span> w <span class="op">*</span> h;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> get_area<span class="op">(</span><span class="kw">const</span> Shape<span class="op">&amp;</span> shape<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="cf">inspect</span> <span class="op">(</span>shape<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">[</span>r<span class="op">]</span> <span class="cf">as</span> Circle <span class="op">=&gt;</span> <span class="fl">3.14</span> <span class="op">*</span> r <span class="op">*</span> r;</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">[</span>w, h<span class="op">]</span> <span class="cf">as</span> Rectangle <span class="op">=&gt;</span> w <span class="op">*</span> h;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> get_area<span class="op">(</span><span class="kw">const</span> Shape<span class="op">&amp;</span> shape<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> shape <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>    Circle<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>r<span class="op">]</span> <span class="op">=&gt;</span> <span class="fl">3.14</span> <span class="op">*</span> r <span class="op">*</span> r;</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>    Rectangle<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>w, h<span class="op">]</span> <span class="op">=&gt;</span> w <span class="op">*</span> h;</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="4.6" id="matching-nested-structures"><span class="header-section-number">4.6</span> Matching Nested Structures<a href="#matching-nested-structures" class="self-link"></a></h2>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Rgb <span class="op">{</span> <span class="dt">int</span> r, g, b; <span class="op">}</span>;</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Hsv <span class="op">{</span> <span class="dt">int</span> h, s, v; <span class="op">}</span>;</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Color <span class="op">=</span> variant<span class="op">&lt;</span>Rgb, Hsv<span class="op">&gt;</span>;</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Quit <span class="op">{}</span>;</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Move <span class="op">{</span> <span class="dt">int</span> x, y; <span class="op">}</span>;</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Write <span class="op">{</span> string s; <span class="op">}</span>;</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ChangeColor <span class="op">{</span> Color c; <span class="op">}</span>;</span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Command <span class="op">=</span> variant<span class="op">&lt;</span>Quit, Move, Write, ChangeColor<span class="op">&gt;</span>;</span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>Command cmd <span class="op">=</span> ChangeColor <span class="op">{</span> Hsv <span class="op">{</span> <span class="dv">0</span>, <span class="dv">160</span>, <span class="dv">255</span> <span class="op">}</span> <span class="op">}</span>;</span></code></pre></div>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>P1371R3</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> CommandVisitor <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span>Quit<span class="op">)</span> <span class="kw">const</span> <span class="op">{}</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Move<span class="op">&amp;</span> move<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=</span> move;</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Write<span class="op">&amp;</span> write<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> text <span class="op">=</span> write<span class="op">.</span>s;</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> ChangeColor<span class="op">&amp;</span> cc<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ColorVisitor <span class="op">{</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>      <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Rgb<span class="op">&amp;</span> rgb<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>r, g, b<span class="op">]</span> <span class="op">=</span> rgb;</span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a>      <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Hsv<span class="op">&amp;</span> hsv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>h, s, v<span class="op">]</span> <span class="op">=</span> hsv;</span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>visit<span class="op">(</span>ColorVisitor<span class="op">{}</span>, cc<span class="op">.</span>c<span class="op">)</span>;</span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>visit<span class="op">(</span>CommandVisitor<span class="op">{}</span>, cmd<span class="op">)</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>cmd<span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>Quit<span class="op">&gt;</span> _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>Move<span class="op">&gt;</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>Write<span class="op">&gt;</span> <span class="op">[</span>text<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>ChangeColor<span class="op">&gt;</span> <span class="op">[&lt;</span>Rgb<span class="op">&gt;</span> <span class="op">[</span>r, g, b<span class="op">]]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>ChangeColor<span class="op">&gt;</span> <span class="op">[&lt;</span>Hsv<span class="op">&gt;</span> <span class="op">[</span>h, s, v<span class="op">]]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>P2392R2</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="cf">inspect</span> <span class="op">(</span>cmd<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">is</span> Quit <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>x, y<span class="op">]</span> <span class="cf">as</span> Move <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span>text<span class="op">]</span> <span class="cf">as</span> Write <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">r</span>,<span class="at"> g</span>,<span class="at"> b</span><span class="op">]]</span> <span class="cf">as</span> ChangeColor <span class="cf">as</span> <span class="op">[</span>Rgb<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">h</span>,<span class="at"> s</span>,<span class="at"> v</span><span class="op">]]</span> <span class="cf">as</span> ChangeColor <span class="cf">as</span> <span class="op">[</span>Hsv<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>cmd <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  Quit<span class="op">:</span> _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  Move<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>  Write<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>text<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>  ChangeColor<span class="op">:</span> <span class="op">[</span>Rgb<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>r, g, b<span class="op">]]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>  ChangeColor<span class="op">:</span> <span class="op">[</span>Hsv<span class="op">:</span> <span class="cf">let</span> <span class="op">[</span>h, s, v<span class="op">]]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>Example from <a href="https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-nested-structs-and-enums">Destructuring
Nested Structs and Enums</a> section from Rust documentation.</p>
<h1 data-number="5" id="design-overview"><span class="header-section-number">5</span> Design Overview<a href="#design-overview" class="self-link"></a></h1>
<p>The overall idea is to introduce a single
<code class="sourceCode cpp"><span class="cf">match</span></code>
construct that can be used to perform single pattern match, or a
selection of pattern matches.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><em>expression</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>  <em>pattern</em> <span class="op">=&gt;</span> <em>expression-statement</em></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code class="sourceCode cpp"><span class="cf">let</span></code>
denotes that an identifier is a new name rather than an existing
name.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> x <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a><em>expression</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>  x <span class="op">=&gt;</span> <span class="op">...</span> <span class="co">// match against existing `x`</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="op">...</span> <span class="co">// introduce new x.</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>On the right of
<code class="sourceCode cpp"><span class="op">=&gt;</span></code> is an
<em>expression-statement</em> rather than a <em>statement</em>. This
means that only expressions are allowed, and I believe it will be best
to pursue <code class="sourceCode cpp"><span class="cf">do</span></code>
expressions <span class="citation" data-cites="P2806R2">[<a href="https://wg21.link/p2806r2" role="doc-biblioref">P2806R2</a>]</span> to do <em>statement</em>
things.</p>
<p>The following is used to match a value against a single pattern.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><em>expression</em> <span class="cf">match</span> <em>pattern</em></span></code></pre></div>
<p>The following is the
<code class="sourceCode cpp"><span class="cf">match</span></code>
expression being used within an
<code class="sourceCode cpp"><span class="cf">if</span></code>
statement.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span><em>expr</em> <span class="cf">match</span> <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> foo<span class="op">])</span> <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// `foo` is available here</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// but not here</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A optional guard can be added for a single pattern match as well:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> fetch<span class="op">(</span><span class="dt">int</span> id<span class="op">)</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_acceptable<span class="op">(</span><span class="dt">int</span> id, <span class="dt">int</span> abs_limit<span class="op">)</span> <span class="op">{</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> fetch<span class="op">(</span>id<span class="op">)</span> <span class="cf">match</span> <span class="cf">let</span> <span class="op">[</span>min, max<span class="op">]</span> <span class="cf">if</span> <span class="op">-</span>abs_limit <span class="op">&lt;=</span> min <span class="op">&amp;&amp;</span> max <span class="op">&lt;=</span> abs_limit;</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.1" id="syntax-overview"><span class="header-section-number">5.1</span> Syntax Overview<a href="#syntax-overview" class="self-link"></a></h2>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Single pattern match</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><em>expr-or-braced-init-list</em> <span class="cf">match</span> <code class="sourceCode cpp"><span class="kw">constexpr</span></code><em><sub>opt</sub></em> <em>pattern</em> <em>guard<sub>opt</sub></em></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Selection pattern match</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><em>expr-or-braced-init-list</em> <span class="cf">match</span> <code class="sourceCode cpp"><span class="kw">constexpr</span></code><em><sub>opt</sub></em> <em>trailing-return-type<sub>opt</sub></em> <span class="op">{</span></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <em>guard<sub>opt</sub></em> <span class="op">=&gt;</span> <em>expr-or-braced-init-list</em> ;</span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <em>guard<sub>opt</sub></em> <span class="op">=&gt;</span> <span class="cf">break</span> ;</span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <em>guard<sub>opt</sub></em> <span class="op">=&gt;</span> <span class="cf">continue</span> ;</span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <em>guard<sub>opt</sub></em> <span class="op">=&gt;</span> <span class="cf">return</span> <em>expr-or-braced-init-list<sub>opt</sub></em> ;</span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>    <em>pattern</em> <em>guard<sub>opt</sub></em> <span class="op">=&gt;</span> <span class="kw">co_return</span> <em>expr-or-braced-init-list<sub>opt</sub></em> ;</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a><em>guard</em><span class="op">:</span></span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <em>expression</em></span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a><em>pattern</em><span class="op">:</span></span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a>    <em>match-pattern</em></span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <em>binding-pattern</em></span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a>    <em>match-pattern</em> <span class="cf">let</span> <em>binding-pattern</em></span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span>  <span class="co">// only in structured bindings pattern (P1061)</span></span>
<span id="cb38-21"><a href="#cb38-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-22"><a href="#cb38-22" aria-hidden="true" tabindex="-1"></a><em>match-pattern</em><span class="op">:</span></span>
<span id="cb38-23"><a href="#cb38-23" aria-hidden="true" tabindex="-1"></a>    _                         <span class="co">// wildcard</span></span>
<span id="cb38-24"><a href="#cb38-24" aria-hidden="true" tabindex="-1"></a>    <em>constant-expression</em>       <span class="co">// value</span></span>
<span id="cb38-25"><a href="#cb38-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span> <em>pattern</em> <span class="op">)</span>               <span class="co">// grouping</span></span>
<span id="cb38-26"><a href="#cb38-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">?</span> <em>pattern</em>                 <span class="co">// pointer-like</span></span>
<span id="cb38-27"><a href="#cb38-27" aria-hidden="true" tabindex="-1"></a>    <em>discriminator</em> <span class="op">:</span> <em>pattern</em>   <span class="co">// variant-like, polymorphic, etc.</span></span>
<span id="cb38-28"><a href="#cb38-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">[</span> <em>pattern-<code class="sourceCode default">0</code></em> , … , <em>pattern-<code class="sourceCode cpp">N</code></em> <span class="op">]</span>    <span class="co">// tuple-like</span></span>
<span id="cb38-29"><a href="#cb38-29" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb38-30"><a href="#cb38-30" aria-hidden="true" tabindex="-1"></a><em>binding-pattern</em><span class="op">:</span></span>
<span id="cb38-31"><a href="#cb38-31" aria-hidden="true" tabindex="-1"></a>    <em>identifier</em></span>
<span id="cb38-32"><a href="#cb38-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">[</span> <em>binding-pattern-<code class="sourceCode default">0</code></em> , … , <em>binding-pattern-<code class="sourceCode cpp">N</code></em> <span class="op">]</span></span>
<span id="cb38-33"><a href="#cb38-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span> <em>identifier</em>  <span class="co">// only in structured bindings pattern (P1061)</span></span>
<span id="cb38-34"><a href="#cb38-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-35"><a href="#cb38-35" aria-hidden="true" tabindex="-1"></a><em>discriminator</em><span class="op">:</span></span>
<span id="cb38-36"><a href="#cb38-36" aria-hidden="true" tabindex="-1"></a>    <em>type-id</em></span>
<span id="cb38-37"><a href="#cb38-37" aria-hidden="true" tabindex="-1"></a>    <em>type-constraint</em></span></code></pre></div>
<h2 data-number="5.2" id="pattern-specifications"><span class="header-section-number">5.2</span> Pattern Specifications<a href="#pattern-specifications" class="self-link"></a></h2>
<h3 data-number="5.2.1" id="wildcard-pattern"><span class="header-section-number">5.2.1</span> Wildcard Pattern<a href="#wildcard-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp">_</code></div>
</blockquote>
<p>A wildcard pattern always matches any <em>subject</em>.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> v <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;ignored&quot;</span><span class="op">)</span>;</span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a><span class="co">//  ^  wildcard pattern</span></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This paper reattempts for <code class="sourceCode cpp">_</code> to be
the wildcard pattern. See <a href="#wildcard-pattern-syntax">Wildcard
Pattern Syntax</a> for further discussion.</p>
<ul>
<li>Matching Condition: None</li>
</ul>
<h3 data-number="5.2.2" id="let-pattern"><span class="header-section-number">5.2.2</span> Let Pattern<a href="#let-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="cf">let</span> <em>binding-pattern</em></code></div>
</blockquote>
<p>A let pattern always matches any <em>subject</em>. The
<em>binding-pattern</em> is either an <em>identifier</em> or a
structured bindings pattern.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> v <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> x <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;ignored&quot;</span><span class="op">)</span>;</span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="co">//  ^^^^^  let pattern</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><code class="sourceCode cpp"><span class="cf">let</span></code> can
be used to introduce new names individually, or all-in-one.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="cf">let</span> x           <span class="co">// x is new</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="op">[</span>a, <span class="cf">let</span> y<span class="op">]</span>      <span class="co">// a is old, y is new</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><span class="op">[</span><span class="cf">let</span> x, b<span class="op">]</span>      <span class="co">// x is new, b is old</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a><span class="cf">let</span> <span class="op">[</span>x, y<span class="op">]</span>      <span class="co">// x and y are both new</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a><span class="cf">let</span> <span class="op">[</span>x, <span class="op">[</span>y, z<span class="op">]]</span> <span class="co">// x, y, z are all new</span></span></code></pre></div>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><em>match-pattern</em> <span class="cf">let</span> <em>binding-pattern</em></code></div>
</blockquote>
<p>A <code class="sourceCode cpp"><span class="cf">let</span></code>
pattern can appear after a <em>match-pattern</em> to create bindings to
the value that was matched with <em>match-pattern</em>.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>i <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">42</span> <span class="op">=&gt;</span> <span class="co">// match 42</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// bind name</span></span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>  <span class="dv">42</span> <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// match 42 and bind name at the same time</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>pair p <span class="op">=</span> <span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">}</span>;</span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>p <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> y<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// match and bind a piece</span></span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> whole <span class="op">=&gt;</span> <span class="co">// bind whole pair</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> y<span class="op">]</span> <span class="cf">let</span> whole <span class="op">=&gt;</span> <span class="co">// do both</span></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="5.2.3" id="constant-pattern"><span class="header-section-number">5.2.3</span> Constant Pattern<a href="#constant-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><em>constant-expression</em></code></div>
</blockquote>
<p>A constant pattern tests the value of
<code class="sourceCode cpp"><em>subject</em></code> against the value
of the constant pattern. The constant pattern can be any
<code class="sourceCode cpp"><em>constant-expression</em></code>, such
as literals,
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
variables, or values of an
<code class="sourceCode cpp"><span class="kw">enum</span></code>.</p>
<ul>
<li>Matching Condition: <code class="sourceCode cpp"><span class="dt">bool</span><span class="op">(</span><em>subject</em> <span class="op">==</span> <em>constant-expression</em><span class="op">)</span>;</code></li>
</ul>
<h3 data-number="5.2.4" id="parenthesized-pattern"><span class="header-section-number">5.2.4</span> Parenthesized Pattern<a href="#parenthesized-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="op">(</span> <em>pattern</em> <span class="op">)</span></code></div>
</blockquote>
<p>A parenthesized pattern is used to group undelimited patterns.</p>
<ul>
<li>Matching Condition: <code class="sourceCode cpp"><em>subject</em> <span class="cf">match</span> <em>pattern</em></code></li>
</ul>
<p>Example:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">const</span> Shape<span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>    s <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">?</span> <span class="op">(</span>Circle<span class="op">:</span> <span class="cf">let</span> c<span class="op">)</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">?</span> <span class="op">(</span>Rectangle<span class="op">:</span> <span class="cf">let</span> r<span class="op">)</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> maybe_int<span class="op">()</span>;</span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>    maybe_int<span class="op">()</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">(?</span> <span class="cf">let</span> i<span class="op">)</span> <span class="cf">let</span> o <span class="op">=&gt;</span> <span class="co">// i is int, o is the whole optional</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>        _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="5.2.5" id="optional-pattern"><span class="header-section-number">5.2.5</span> Optional Pattern<a href="#optional-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="op">?</span> <em>pattern</em></code></div>
</blockquote>
<p>An optional pattern tests pointer-like objects. It matches if
<code class="sourceCode cpp"><em>subject</em></code> contextually
converts to
<code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp"><span class="op">*</span><em>subject</em></code>
matches <code class="sourceCode cpp"><em>pattern</em></code>.</p>
<ul>
<li>Matching Condition: <code class="sourceCode cpp"><span class="dt">bool</span><span class="op">(</span><em>subject</em><span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">*</span><em>subject</em> <span class="cf">match</span> <em>pattern</em></code></li>
</ul>
<h3 data-number="5.2.6" id="alternative-pattern"><span class="header-section-number">5.2.6</span> Alternative Pattern<a href="#alternative-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><em>type-id</em> <span class="op">:</span> <em>pattern</em></code><br />
<code class="sourceCode cpp"><em>type-constraint</em> <span class="op">:</span> <em>pattern</em></code></div>
</blockquote>
<p>An alternative pattern tests sum type objects such as
<code class="sourceCode cpp">variant</code>,
<code class="sourceCode cpp">any</code>, and polymorphic types.</p>
<p>Let <code class="sourceCode cpp">s</code> be <em>subject</em>,
<code class="sourceCode cpp">S</code> be <code class="sourceCode cpp">std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><em>subject</em><span class="op">)&gt;</span></code>.</p>
<p><strong>Case 1</strong>: Variant-like</p>
<p>An alternative pattern matches if the
<code class="sourceCode cpp">variant</code>-like object stores a value
of type <em>type-id</em> or the value of type satisfies
<em>type-constraint</em>, and the stored value matches
<em>pattern</em>.</p>
<p>If <code class="sourceCode cpp">std<span class="op">::</span>variant_size<span class="op">&lt;</span>S<span class="op">&gt;</span></code>
is well-formed and <code class="sourceCode cpp">std<span class="op">::</span>variant_size<span class="op">&lt;</span>S<span class="op">&gt;::</span>value</code>
is an integral, let <code class="sourceCode cpp">I</code> be the value
of <code class="sourceCode cpp">s<span class="op">.</span>index<span class="op">()</span></code>.
An alternative pattern matches if <code class="sourceCode cpp">std<span class="op">::</span>variant_alternative_t<span class="op">&lt;</span>I, S<span class="op">&gt;</span></code>
is <em>type-id</em> or if it satisfies <em>type-constraint</em>, and
<em>pattern</em> matches <code class="sourceCode cpp">get<span class="op">&lt;</span>I<span class="op">&gt;(</span>s<span class="op">)</span></code>.</p>
<p><strong>Case 2</strong>: Casts</p>
<p>If <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">*</span> p <span class="op">=</span> cast<span class="op">&lt;</span>S<span class="op">&gt;::</span><span class="kw">operator</span><span class="op">()&lt;</span><em>type-id</em><span class="op">&gt;(</span>s<span class="op">)</span></code>
is well-formed, alternative pattern matches if
<code class="sourceCode cpp">p</code> contextually converts to
<code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp">std<span class="op">::</span>forward_like<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>s<span class="op">)&gt;(*</span>p<span class="op">)</span></code>
matches <em>pattern</em>.</p>
<p>A <code class="sourceCode cpp">cast</code> customization point is
proposed, rather than using
<code class="sourceCode cpp">any_cast</code>. Since
<code class="sourceCode cpp">any</code> has an implicit constructor from
anything, overloading <code class="sourceCode cpp">any_cast</code> which
takes <code class="sourceCode cpp"><span class="kw">const</span> any<span class="op">&amp;</span></code>
will likely cause a problem. Moreover, <span class="citation" data-cites="P2927R0">[<a href="https://wg21.link/p2927r0" role="doc-biblioref">P2927R0</a>]</span> is in the process of
introducing <code class="sourceCode cpp">std<span class="op">::</span>try_cast</code>.</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">&gt;</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> cast;</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> cast<span class="op">&lt;</span>std<span class="op">::</span>any<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-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="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">const</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> std<span class="op">::</span>any<span class="op">&amp;</span> a<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>any_cast<span class="op">&lt;</span>T<span class="op">&gt;(&amp;</span>a<span class="op">)</span>;</span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-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="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">()(</span>std<span class="op">::</span>any<span class="op">&amp;</span> a<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb45-13"><a href="#cb45-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>any_cast<span class="op">&lt;</span>T<span class="op">&gt;(&amp;</span>a<span class="op">)</span>;</span>
<span id="cb45-14"><a href="#cb45-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb45-15"><a href="#cb45-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb45-16"><a href="#cb45-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-17"><a href="#cb45-17" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span></span>
<span id="cb45-18"><a href="#cb45-18" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> cast<span class="op">&lt;</span>std<span class="op">::</span>exception_ptr<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb45-19"><a href="#cb45-19" aria-hidden="true" tabindex="-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="cb45-20"><a href="#cb45-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">const</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> std<span class="op">::</span>exception_ptr<span class="op">&amp;</span> p<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb45-21"><a href="#cb45-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>try_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>p<span class="op">)</span>; <span class="co">// P2927R0</span></span>
<span id="cb45-22"><a href="#cb45-22" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb45-23"><a href="#cb45-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><strong>Case 3</strong>: Polymorphic Types</p>
<p>This is listed as a separate case in case it’s needed for
optimization flexibility. In principle though, the following
specialization of <code class="sourceCode cpp">cast</code> should
provide the desired semantics.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Base<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> std<span class="op">::</span>is_polymorphic_v<span class="op">&lt;</span>T<span class="op">&gt;</span>; <span class="op">}</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> cast<span class="op">&lt;</span>Base<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-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="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">const</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> Base<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">dynamic_cast</span><span class="op">&lt;</span><span class="kw">const</span> T<span class="op">*&gt;(&amp;</span>b<span class="op">)</span>;</span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-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="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">()(</span>Base<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">dynamic_cast</span><span class="op">&lt;</span>T<span class="op">*&gt;(&amp;</span>b<span class="op">)</span>;</span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="5.2.7" id="structured-bindings-pattern"><span class="header-section-number">5.2.7</span> Structured Bindings Pattern<a href="#structured-bindings-pattern" class="self-link"></a></h3>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="op">[</span> <em>pattern-<code class="sourceCode default">0</code></em> , … , <em>pattern-<code class="sourceCode cpp">N</code></em> <span class="op">]</span></code></div>
</blockquote>
<p>Given the following structured binding declaration:</p>
<p><code class="sourceCode cpp"><span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">[</span> <em>e-<code class="sourceCode default">0</code></em>, …, <em>e-<code class="sourceCode cpp">N</code></em> <span class="op">]</span> <span class="op">=</span> <em>subject</em> ;</code></p>
<p>Let <em>e-i</em> be a unique exposition-only identifier if
<em>pattern-i</em> is a <em>pattern</em> and an ellipsis
(<code class="sourceCode cpp"><span class="op">...</span></code>) if
<em>pattern-i</em> is an ellipsis
(<code class="sourceCode cpp"><span class="op">...</span></code>).
Structured bindings pattern matches <em>subject</em> if <em>e-i</em>
matches <em>pattern-i</em> for all <em>i</em> where <em>e-i</em> is an
identifier.</p>
<h2 data-number="5.3" id="scope-of-bindings"><span class="header-section-number">5.3</span> Scope of Bindings<a href="#scope-of-bindings" class="self-link"></a></h2>
<p>The scope of the bindings introduced by
<code class="sourceCode cpp"><span class="cf">let</span></code> are as
follows:</p>
<ul>
<li>If the <em>pattern</em> is left of
<code class="sourceCode cpp"><span class="op">=&gt;</span></code>, the
scope of the binding is the corresponding expression statement.</li>
<li>If the <em>pattern</em> is in <code class="sourceCode cpp"><em>expression</em> <span class="cf">match</span> <em>pattern</em> <em>guard<sub>opt</sub></em></code>,
the scope of the binding is the expression including the optional guard,
unless:</li>
<li>If the construct is the <em>condition</em> of an
<code class="sourceCode cpp"><span class="cf">if</span></code>
statement, the scope of the binding is the <em>then</em> substatement of
the <code class="sourceCode cpp"><span class="cf">if</span></code>
statement.</li>
<li>If the construct is the <em>condition</em> of a
<code class="sourceCode cpp"><span class="cf">for</span></code>, or
<code class="sourceCode cpp"><span class="cf">while</span></code>
statement, the scope of the binding is the substatement of
<code class="sourceCode cpp"><span class="cf">for</span></code> or
<code class="sourceCode cpp"><span class="cf">while</span></code>
statement.</li>
</ul>
<p>Example:</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> b1 <span class="op">=</span> e1 <span class="cf">match</span> <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> x<span class="op">]</span> <span class="cf">if</span> x <span class="op">&gt;</span> <span class="dv">1</span>;</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a><span class="co">// x not available here.</span></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> b2 <span class="op">=</span> e2 <span class="cf">match</span> <span class="op">[</span><span class="cf">let</span> x<span class="op">]</span>; <span class="co">// not a redeclaration</span></span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a><span class="co">// x not available here.</span></span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>e3 <span class="cf">match</span> <span class="op">(?</span> <span class="cf">let</span> elem<span class="op">))</span> <span class="op">{</span></span>
<span id="cb47-8"><a href="#cb47-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// elem available here</span></span>
<span id="cb47-9"><a href="#cb47-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb47-10"><a href="#cb47-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// elem not available here</span></span>
<span id="cb47-11"><a href="#cb47-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb47-12"><a href="#cb47-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-13"><a href="#cb47-13" aria-hidden="true" tabindex="-1"></a><span class="cf">while</span> <span class="op">(</span>queue<span class="op">.</span>next<span class="op">()</span> <span class="cf">match</span> <span class="op">(?</span> <span class="cf">let</span> elem<span class="op">))</span> <span class="op">{</span></span>
<span id="cb47-14"><a href="#cb47-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// elem available here</span></span>
<span id="cb47-15"><a href="#cb47-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.4" id="static-and-dynamic-conditions"><span class="header-section-number">5.4</span> Static and Dynamic Conditions<a href="#static-and-dynamic-conditions" class="self-link"></a></h2>
<p>Every <em>pattern</em> has a corresponding condition which is tested
against the <em>subject</em> to determine whether the <em>pattern</em>
matches the <em>subject</em>.</p>
<p>For example, the constant pattern
<code class="sourceCode cpp"><span class="dv">0</span></code> has a
condition that it matches if <code class="sourceCode cpp"><em>subject</em> <span class="op">==</span> <span class="dv">0</span></code>
is true. However, there are static and dynamic dimensions to which this
condition can be applied. These dimensions are defined here.</p>
<h3 data-number="5.4.1" id="static-conditions"><span class="header-section-number">5.4.1</span> Static Conditions<a href="#static-conditions" class="self-link"></a></h3>
<p>Static conditions are the static requirements of a pattern. The
patterns being introduced in this paper have dynamic behavior, and
therefore their static conditions are the validity of a
<em>pattern</em>’s match condition.</p>
<p>See <a href="#static-type-checking-with-constraint-pattern">Static
Type Checking with Constraint Pattern</a> for an example where this
isn’t the case.</p>
<p>The main question is, are these static requirements checked or
tested? Going back to the constant pattern
<code class="sourceCode cpp"><span class="dv">0</span></code>, its
static condition is whether <code class="sourceCode cpp"><em>subject</em> <span class="op">==</span> <span class="dv">0</span></code>
is a valid expression.</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f1<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this example, whether <code class="sourceCode cpp">x <span class="op">==</span> <span class="dv">0</span></code>
is a valid expression is checked at compile-time. If
<code class="sourceCode cpp">x</code> is a
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
for example, the program is ill-formed.</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f2<span class="op">(</span>std<span class="op">::</span>string x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ill-formed</span></span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This behavior is likely to be pretty obvious to folks. But what if
<code class="sourceCode cpp">x</code> were a templated parameter
instead?</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f3<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// fine here</span></span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a>f3<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="bu">s</span><span class="op">)</span>; <span class="co">// proposed: ill-formed</span></span></code></pre></div>
<p>This paper proposes that this example be ill-formed at the
instantiation site. While a model that treats
<code class="sourceCode cpp"><span class="dv">0</span></code> as a
no-match would be doable, I believe it’ll be better and safer as an
opt-in feature. For <code class="sourceCode cpp">f3<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span></code>
to have different type-checking behavior than
<code class="sourceCode cpp">f2</code> would be novel and likely lead to
subtle bugs.</p>
<p>This means that static conditions of patterns are always checked and
enforced at compile-time. See <a href="#more-on-static-conditions">More
on Static Conditions</a> for further design discussions, and <a href="#testing-the-static-conditions-with-match-requires">Testing the
Static Conditions with <code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code></a>
which suggests an extension to explicitly treat the static conditions as
compile-time tests rather than checks.</p>
<p>The semantics for this was not precisely defined in <span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span>, and <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span> proposes for <code class="sourceCode cpp">f3<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="bu">s</span><span class="op">)</span></code>
to be well-formed and
<code class="sourceCode cpp"><span class="dv">0</span></code> is a
no-match.</p>
<h3 data-number="5.4.2" id="dynamic-conditions"><span class="header-section-number">5.4.2</span> Dynamic Conditions<a href="#dynamic-conditions" class="self-link"></a></h3>
<p>Dynamic conditions are more obvious and straight-forward. The
constant pattern
<code class="sourceCode cpp"><span class="dv">0</span></code> matches if
<code class="sourceCode cpp"><em>subject</em> <span class="op">==</span> <span class="dv">0</span></code>
is true. But true when?</p>
<p>This paper proposes that
<code class="sourceCode cpp"><span class="cf">match</span></code> tests
the dynamic condition at runtime, (think
<code class="sourceCode cpp"><span class="cf">if</span></code>) and
<code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">constexpr</span></code>
tests it at compile-time (think <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span></code>).</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">constexpr</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span> I<span class="op">&gt;</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> get<span class="op">(</span><span class="kw">const</span> S<span class="op">&amp;</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> I <span class="cf">match</span> <span class="kw">constexpr</span> <span class="op">-&gt;</span> <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> s<span class="op">.</span>foo<span class="op">()</span>;</span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span> <span class="op">=&gt;</span> s<span class="op">.</span>bar<span class="op">()</span>;</span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="kw">static_assert</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span>;</span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="6" id="proposed-wording"><span class="header-section-number">6</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<h2 data-number="6.1" id="language"><span class="header-section-number">6.1</span> Language<a href="#language" class="self-link"></a></h2>
<h3 class="unnumbered unlisted" id="lex.name-identifiers"><span>5.10
<a href="https://wg21.link/lex.name">[lex.name]</a></span> Identifiers<a href="#lex.name-identifiers" class="self-link"></a></h3>
<p>Add to <span>5.10
<a href="https://wg21.link/lex.name">[lex.name]</a></span>/2, Table
4:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The identifiers in Table 4 have a special meaning when appearing in a
certain context. When referred to in the grammar, these identifiers are
used explicitly rather than using the <em>identifier</em> grammar
production. Unless otherwise specified, any ambiguity as to whether a
given <em>identifier</em> has a special meaning is resolved to interpret
the token as a regular <em>identifier</em>.</p>
<table>
<tbody>
<tr class="odd">
<td><code class="sourceCode cpp"><span class="kw">final</span></code></td>
<td><code class="sourceCode cpp"><span class="kw">import</span></code></td>
<td><code class="sourceCode cpp"><span class="kw">module</span></code></td>
<td><code class="sourceCode cpp"><span class="kw">override</span></code></td>
<td><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">match</code></span></ins></span></td>
<td><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">let</code></span></ins></span></td>
</tr>
</tbody>
</table>
</blockquote>
<h3 class="unnumbered unlisted" id="lex.operators-operators-and-punctuators"><span>5.12
<a href="https://wg21.link/lex.operators">[lex.operators]</a></span>
Operators and punctuators<a href="#lex.operators-operators-and-punctuators" class="self-link"></a></h3>
<p>Add to <span>5.12
<a href="https://wg21.link/lex.operators">[lex.operators]</a></span>/1:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The lexical representation of C++ programs includes a number of
preprocessing tokens that are used in the syntax of the preprocessor or
are converted into tokens for operators and punctuators:</p>
<div>
<div class="sourceCode" id="cb53"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a> <em>preprocessing-op-or-punc</em>:</span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>     <em>preprocessing-operator</em></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>     <em>operator-or-punctuator</em></span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a> <em>preprocessing-operator</em>: one of</span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>     #        ##       %:       %:%:</span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a> <em>operator-or-punctuator</em>: one of</span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>     {        }        [        ]        (        )</span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>     &lt;:       :&gt;       &lt;%       %&gt;       ;        :        ...</span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>     ?        ::       .        .*       -&gt;       -&gt;*      ~</span>
<span id="cb53-12"><a href="#cb53-12" aria-hidden="true" tabindex="-1"></a>     !        +        -        *        /        %        ^        &amp;        |</span>
<span id="cb53-13"><a href="#cb53-13" aria-hidden="true" tabindex="-1"></a>     =        +=       -=       *=       /=       %=       ^=       &amp;=       |=</span>
<span id="cb53-14"><a href="#cb53-14" aria-hidden="true" tabindex="-1"></a>     ==       !=       &lt;        &gt;        &lt;=       &gt;=       &lt;=&gt;      &amp;&amp;       ||</span>
<span id="cb53-15"><a href="#cb53-15" aria-hidden="true" tabindex="-1"></a>     &lt;&lt;       &gt;&gt;       &lt;&lt;=      &gt;&gt;=      ++       --       ,        <span class="add" style="color: #006e28"><ins>=&gt;</ins></span></span>
<span id="cb53-16"><a href="#cb53-16" aria-hidden="true" tabindex="-1"></a>     and      or       xor      not      bitand   bitor    compl</span>
<span id="cb53-17"><a href="#cb53-17" aria-hidden="true" tabindex="-1"></a>     and_eq   or_eq    xor_eq   not_eq</span></code></pre></div>
</div>
</blockquote>
<h3 class="unnumbered unlisted" id="expr.mul-multiplicative-operators"><span>7.6.5
<a href="https://wg21.link/expr.mul">[expr.mul]</a></span>
Multiplicative operators<a href="#expr.mul-multiplicative-operators" class="self-link"></a></h3>
<p>Change <span>7.6.5
<a href="https://wg21.link/expr.mul">[expr.mul]</a></span>/1:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The multiplicative operators
<code class="sourceCode cpp"><span class="op">*</span></code>,
<code class="sourceCode cpp"><span class="op">/</span></code>, and
<code class="sourceCode cpp"><span class="op">%</span></code> group
left-to-right.</p>
<div>
<div class="sourceCode" id="cb54"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a>  <em>multiplicative-expression</em>:</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a><span class="st">-     <em>pm-expression</em></span></span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-expression</em></span></span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a>      <em>multiplicative-expression</em> * <em>pm-expression</em></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>      <em>multiplicative-expression</em> / <em>pm-expression</em></span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>      <em>multiplicative-expression</em> % <em>pm-expression</em></span></code></pre></div>
</div>
</blockquote>
<p>Add a new section after <span>7.6.4
<a href="https://wg21.link/expr.mptr.oper">[expr.mptr.oper]</a></span>:</p>
<div class="add" style="color: #006e28">

<h3 class="unnumbered unlisted" id="pattern-matching-operator-expr.match">7.6.4+1 Pattern matching
operator [expr.match]<a href="#pattern-matching-operator-expr.match" class="self-link"></a></h3>
<p>The pattern matching operator groups left-to-right.</p>
</div>
<div>
<div class="sourceCode" id="cb55"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-expression</em>:</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>pm-expression</em></span></span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-test-expression</em></span></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-select-expression</em></span></span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-test-expression</em></span></span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-subject</em> match constexpr<em><sub>opt</sub></em>  <em>match-test-guard<sub>opt</sub></em></span></span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-subject</em> match constexpr<em><sub>opt</sub></em>  <em>match-test-guard<sub>opt</sub></em></span></span>
<span id="cb55-9"><a href="#cb55-9" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-10"><a href="#cb55-10" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-subject</em>:</span></span>
<span id="cb55-11"><a href="#cb55-11" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>pm-expression</em></span></span>
<span id="cb55-12"><a href="#cb55-12" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>braced-init-list</em></span></span>
<span id="cb55-13"><a href="#cb55-13" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-14"><a href="#cb55-14" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-test-pattern</em></span></span>
<span id="cb55-15"><a href="#cb55-15" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>let-pattern</em></span></span>
<span id="cb55-16"><a href="#cb55-16" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-test-matching-pattern</em> <em>let-pattern<sub>opt</sub></em></span></span>
<span id="cb55-17"><a href="#cb55-17" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-18"><a href="#cb55-18" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-test-matching-pattern</em>:</span></span>
<span id="cb55-19"><a href="#cb55-19" aria-hidden="true" tabindex="-1"></a><span class="va">+     _</span></span>
<span id="cb55-20"><a href="#cb55-20" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>pm-expression</em></span></span>
<span id="cb55-21"><a href="#cb55-21" aria-hidden="true" tabindex="-1"></a><span class="va">+     ( <em>match-case-pattern</em> )</span></span>
<span id="cb55-22"><a href="#cb55-22" aria-hidden="true" tabindex="-1"></a><span class="va">+     ? <em>match-test-pattern</em></span></span>
<span id="cb55-23"><a href="#cb55-23" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>discriminator</em> : <em>match-test-pattern</em></span></span>
<span id="cb55-24"><a href="#cb55-24" aria-hidden="true" tabindex="-1"></a><span class="va">+     [ <em>match-case-pattern-list</em> ]</span></span>
<span id="cb55-25"><a href="#cb55-25" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-26"><a href="#cb55-26" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>let-pattern</em>:</span></span>
<span id="cb55-27"><a href="#cb55-27" aria-hidden="true" tabindex="-1"></a><span class="va">+     let <em>binding-pattern</em></span></span>
<span id="cb55-28"><a href="#cb55-28" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-29"><a href="#cb55-29" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>binding-pattern</em>:</span></span>
<span id="cb55-30"><a href="#cb55-30" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>identifier</em></span></span>
<span id="cb55-31"><a href="#cb55-31" aria-hidden="true" tabindex="-1"></a><span class="va">+     [ <em>binding-pattern-list</em> ]</span></span>
<span id="cb55-32"><a href="#cb55-32" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-33"><a href="#cb55-33" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>binding-pattern-list</em>:</span></span>
<span id="cb55-34"><a href="#cb55-34" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>binding-pattern</em></span></span>
<span id="cb55-35"><a href="#cb55-35" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>binding-pattern-list</em> , <em>binding-pattern</em></span></span>
<span id="cb55-36"><a href="#cb55-36" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-37"><a href="#cb55-37" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-test-guard</em>:</span></span>
<span id="cb55-38"><a href="#cb55-38" aria-hidden="true" tabindex="-1"></a><span class="va">+     if <em>pm-expression</em></span></span>
<span id="cb55-39"><a href="#cb55-39" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-40"><a href="#cb55-40" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-select-expression</em></span></span>
<span id="cb55-41"><a href="#cb55-41" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-subject</em> match constexpr<em><sub>opt</sub></em> <em>trailing-return-type<sub>opt</sub></em> { <em>match-case-seq</em> }</span></span>
<span id="cb55-42"><a href="#cb55-42" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-43"><a href="#cb55-43" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case-seq</em>:</span></span>
<span id="cb55-44"><a href="#cb55-44" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case</em> <em>match-case-seq<sub>opt</sub></em></span></span>
<span id="cb55-45"><a href="#cb55-45" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-46"><a href="#cb55-46" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case</em>:</span></span>
<span id="cb55-47"><a href="#cb55-47" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case-pattern</em> <em>match-case-guard<sub>opt</sub></em> =&gt; <em>expr-or-braced-init-list</em> ;</span></span>
<span id="cb55-48"><a href="#cb55-48" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case-pattern</em> <em>match-case-guard<sub>opt</sub></em> =&gt; <em>escape-statement</em> ;</span></span>
<span id="cb55-49"><a href="#cb55-49" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-50"><a href="#cb55-50" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case-guard</em>:</span></span>
<span id="cb55-51"><a href="#cb55-51" aria-hidden="true" tabindex="-1"></a><span class="va">+     if <em>assignment-expression</em></span></span>
<span id="cb55-52"><a href="#cb55-52" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-53"><a href="#cb55-53" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case-pattern</em>:</span></span>
<span id="cb55-54"><a href="#cb55-54" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>let-pattern</em></span></span>
<span id="cb55-55"><a href="#cb55-55" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case-matching-pattern</em> <em>let-pattern<sub>opt</sub></em></span></span>
<span id="cb55-56"><a href="#cb55-56" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-57"><a href="#cb55-57" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case-matching-pattern</em>:</span></span>
<span id="cb55-58"><a href="#cb55-58" aria-hidden="true" tabindex="-1"></a><span class="va">+     _</span></span>
<span id="cb55-59"><a href="#cb55-59" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>constant-expression</em></span></span>
<span id="cb55-60"><a href="#cb55-60" aria-hidden="true" tabindex="-1"></a><span class="va">+     ( <em>match-case-pattern</em> )</span></span>
<span id="cb55-61"><a href="#cb55-61" aria-hidden="true" tabindex="-1"></a><span class="va">+     ? <em>match-case-pattern</em></span></span>
<span id="cb55-62"><a href="#cb55-62" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>discriminator</em> : <em>match-case-pattern</em></span></span>
<span id="cb55-63"><a href="#cb55-63" aria-hidden="true" tabindex="-1"></a><span class="va">+     [ <em>match-case-pattern-list</em> ]</span></span>
<span id="cb55-64"><a href="#cb55-64" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-65"><a href="#cb55-65" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>discriminator</em>:</span></span>
<span id="cb55-66"><a href="#cb55-66" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>type-id</em></span></span>
<span id="cb55-67"><a href="#cb55-67" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>type-constraint</em></span></span>
<span id="cb55-68"><a href="#cb55-68" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb55-69"><a href="#cb55-69" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>match-case-pattern-list</em>:</span></span>
<span id="cb55-70"><a href="#cb55-70" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case-pattern</em></span></span>
<span id="cb55-71"><a href="#cb55-71" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>match-case-pattern-list</em> , <em>match-case-pattern</em> </span></span></code></pre></div>
</div>
<h3 class="unnumbered unlisted" id="general-stmt.jump.general">8.7.1
General [stmt.jump.general]<a href="#general-stmt.jump.general" class="self-link"></a></h3>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
Jump statements unconditionally transfer control.</p>
</blockquote>
<div>
<div class="sourceCode" id="cb56"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>jump-statement:</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a><span class="st">-    break ;</span></span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a><span class="st">-    continue ;</span></span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a><span class="st">-    return <em>expr-or-braced-init-list</em><sub>opt</sub> ;</span></span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a><span class="st">-    <em>coroutine-return-statement</em></span></span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>escape-statement</em></span></span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>     goto <em>identifier</em> ;</span>
<span id="cb56-8"><a href="#cb56-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-9"><a href="#cb56-9" aria-hidden="true" tabindex="-1"></a><span class="va">+ escape-statement:</span></span>
<span id="cb56-10"><a href="#cb56-10" aria-hidden="true" tabindex="-1"></a><span class="va">+    break ;</span></span>
<span id="cb56-11"><a href="#cb56-11" aria-hidden="true" tabindex="-1"></a><span class="va">+    continue ;</span></span>
<span id="cb56-12"><a href="#cb56-12" aria-hidden="true" tabindex="-1"></a><span class="va">+    return <em>expr-or-braced-init-list</em><sub>opt</sub> ;</span></span>
<span id="cb56-13"><a href="#cb56-13" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>coroutine-return-statement</em></span></span></code></pre></div>
</div>
<h1 data-number="7" id="design-decisions-and-discussions"><span class="header-section-number">7</span> Design Decisions and
Discussions<a href="#design-decisions-and-discussions" class="self-link"></a></h1>
<h2 data-number="7.1" id="unified-match-expression"><span class="header-section-number">7.1</span> Unified
<code class="sourceCode cpp"><span class="cf">match</span></code>
Expression<a href="#unified-match-expression" class="self-link"></a></h2>
<p>The <code class="sourceCode cpp"><span class="cf">match</span></code>
expression presented in this paper unifies the syntax for a single
pattern match and a selection of pattern matches. Namely, <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <em>pattern</em></code>
and <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code>.</p>
<p>The single pattern match <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <em>pattern</em></code>
is very similar to <code class="sourceCode cpp"><em>expr</em> <span class="cf">is</span> <em>pattern</em></code>
introduced in <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span>.</p>
<p>Early attempts at pattern matching with
<code class="sourceCode cpp"><span class="cf">inspect</span></code> also
explored the idea of being a statement and an expression depending on
its context. In short, if it appears in an expression-only context
(e.g. <code class="sourceCode cpp"><span class="dt">int</span> x <span class="op">=</span> <span class="cf">inspect</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</code>)
then it’s an expression. If it appears in a context where a statement or
an expression can appear (e.g. <code class="sourceCode cpp"><span class="op">{</span> <span class="cf">inspect</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span> <span class="op">}</span></code>),
then it’s interpreted as a statement.</p>
<p>Having to differentiate between the statement-form and
expression-form was a novel situation with no other precedent in the
language. Additionally, whatever the keyword, it would’ve needed to be a
<em>full</em> keyword. Maybe
<code class="sourceCode cpp"><span class="cf">inspect</span></code>
would’ve been okay, but something like
<code class="sourceCode cpp"><span class="cf">match</span></code> was
not even a possibility.</p>
<p>With this approach,
<code class="sourceCode cpp"><span class="cf">match</span></code> is
feasible as a context-sensitive keyword, and and there is only an
expression-form, which simplifies the design.</p>
<h2 data-number="7.2" id="wildcard-pattern-syntax"><span class="header-section-number">7.2</span> Wildcard Pattern Syntax<a href="#wildcard-pattern-syntax" class="self-link"></a></h2>
<p>This paper proposes <code class="sourceCode cpp">_</code> as the
syntax for wildcard patterns. Note that this is different from bindings
that are introduced with the name
<code class="sourceCode cpp">_</code>.</p>
<p>For example,</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a>e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a><span class="co">//  ^ this is a wildcard</span></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <span class="op">[</span>_, _<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a><span class="co">//       ^  ^ these are bindings</span></span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>In the bindings case, the semantics are the same as <span class="citation" data-cites="P2169R4">[<a href="https://wg21.link/p2169r4" role="doc-biblioref">P2169R4</a>]</span>, which was accepted for C++26.
That is, a single declaration of <code class="sourceCode cpp">_</code>
is usable but a use after a redeclaration is ill-formed.</p>
<p>In the wildcard case, it is a special rule in that
<code class="sourceCode cpp">_</code> can be an existing variable. For
example,</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i <span class="op">=</span> <span class="dv">101</span>;</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> _ <span class="op">=</span> <span class="dv">202</span>;</span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>i <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// 101 != 202 but _ is a wildcard, so this matches.</span></span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The recommended workaround is to use a guard:</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i <span class="op">=</span> <span class="dv">101</span>;</span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> _ <span class="op">=</span> <span class="dv">202</span>;</span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a>i <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> x <span class="cf">if</span> x <span class="op">==</span> _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<ul>
<li><span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span> proposed
<code class="sourceCode cpp">__</code> which was also the syntax
recommended in <span class="citation" data-cites="P1110R0">[<a href="https://wg21.link/p1110r0" role="doc-biblioref">P1110R0</a>]</span>.</li>
<li><span class="citation" data-cites="P1469R0">[<a href="https://wg21.link/p1469r0" role="doc-biblioref">P1469R0</a>]</span> proposed disallowing use of
<code class="sourceCode cpp">_</code> as an identifier in the context of
structured bindings, but this was rejected by EWG. as it’s not referred
to, and was accepted for C++26.</li>
<li><span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span> proposed
<code class="sourceCode cpp">_</code> as well.</li>
</ul>
<p>This is a relatively small cost to get
<code class="sourceCode cpp">_</code> as the wildcard pattern, given the
prevalence and scope of adoption of
<code class="sourceCode cpp">_</code> across the industry. Languages
such as Python, Rust, Scala, Swift, C#, Erlang, Prolog, Haskell, OCaml
and many others already use <code class="sourceCode cpp">_</code>.
Pattern matching facilities across different languages do vary, but I’m
not aware of <em>any</em> language that disagree on
<code class="sourceCode cpp">_</code>.</p>
<h2 data-number="7.3" id="why-we-want-expressions-in-patterns"><span class="header-section-number">7.3</span> Why We Want Expressions in
Patterns<a href="#why-we-want-expressions-in-patterns" class="self-link"></a></h2>
<p>If expressions are not supported at all, this would mean we couldn’t
do some of the most simple operations that
<code class="sourceCode cpp"><span class="cf">switch</span></code> can
handle. We should be able to at the very least match integrals, strings,
and enums.</p>
<p>So we need to allow expressions at least in <em>some</em> capacity.
Let’s say for example we only allow literals. This would give us
matching for integral and string literals, but we wouldn’t be able to
match against
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
variables of integrals and strings.</p>
<p>It also doesn’t get us enums, since enum values are not literals. We
need unqualified names to be able to access
<code class="sourceCode cpp"><span class="kw">enum</span></code> values,
and qualified names to be able to access <code class="sourceCode cpp"><span class="kw">enum</span> <span class="kw">class</span></code>
values.</p>
<p>At this point, we already basically have <em>primary-expression</em>.
The question of how to handle referring to existing names vs introducing
new names have to be addressed. Only allowing
<em>primary-expression</em> rather than <em>constant-expression</em>
might still be useful or needed to avoid further grammar complications,
but the fundamental issue of existing vs new names I don’t think could
nor should be avoided.</p>
<h2 data-number="7.4" id="exploration-of-variable-declaration-syntax-for-alternative-pattern"><span class="header-section-number">7.4</span> Exploration of Variable
Declaration Syntax for Alternative Pattern<a href="#exploration-of-variable-declaration-syntax-for-alternative-pattern" class="self-link"></a></h2>
<p>The proposed syntax in this paper is</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><em>type-id</em> <span class="op">:</span> <em>pattern</em></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a><em>type-constraint</em> <span class="op">:</span> <em>pattern</em></span></code></pre></div>
<p>Here’s a simple example:</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">bool</span>, std<span class="op">::</span>string<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span><span class="op">:</span> <span class="cf">let</span> b <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string<span class="op">:</span> <span class="cf">let</span> s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This looks more like
<code class="sourceCode cpp"><span class="cf">case</span></code> labels
where the alternatives are listed and the appropriate one is chosen. The
correponding value is then matched with a nested pattern.</p>
<p>The absolute minimal syntax would be <code class="sourceCode cpp">std<span class="op">::</span>string s</code>,
which is rather appealing but ultimately not what is proposed.</p>
<p>An example using this syntax might be something like:</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">bool</span>, std<span class="op">::</span>string<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> b <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><strong>Question 1</strong>: What <strong>are</strong>
<code class="sourceCode cpp">i</code>,
<code class="sourceCode cpp">b</code>, and
<code class="sourceCode cpp">s</code>?</p>
<p>They certainly look like variable declarations, and I think it’ll be
too surprising for them to be anything else. So let’s for now assume
that they are variable declarations. In this case, they should probably
used as a general way to introduce new names within a pattern for
binding purposes. We want patterns to compose, so this applies to nested
patterns as well, but at the top-level this might look like:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_int<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>parse_int<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb63-6"><a href="#cb63-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> i <span class="op">=&gt;</span> <span class="co">// use `i` which is `int` returned by `parse_int`</span></span>
<span id="cb63-7"><a href="#cb63-7" aria-hidden="true" tabindex="-1"></a>            <span class="co">// not 0 or 1</span></span>
<span id="cb63-8"><a href="#cb63-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><strong>Question 2</strong>: How do you disambiguate
<code class="sourceCode cpp"><span class="kw">auto</span> x</code>
between <code class="sourceCode cpp">variant</code> itself vs the
alternative inside?</p>
<p><code class="sourceCode cpp">std<span class="op">::</span>variant</code>
is a very unique sum type, in that you are able to handle the
“catch-all” case where you can generically access the value inside of
it.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++23</strong>
</div></th>
<th><div style="text-align:center">
<strong>Variable Declaration Approach</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>  overload<span class="op">(</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>,</span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span>,</span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>  parse<span class="op">(</span>some_input<span class="op">))</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> x <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>But what is <code class="sourceCode cpp">x</code>? Is it the
unhandled alternatives of the variant, or is it the variant itself?</p>
<p>In the <code class="sourceCode cpp">parse_int</code> example from
above,
<code class="sourceCode cpp"><span class="kw">auto</span> i</code> was a
binding to the whole value!</p>
<p>Note that for polymorphic types we could actually make this work
since there’s no way to generically operate on the runtime value of a
polymorphic type anyway.</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Shape <span class="op">{</span> <span class="kw">virtual</span> <span class="op">~</span>Shape<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="op">}</span>;</span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Circle <span class="op">:</span> Shape <span class="op">{</span> <span class="dt">int</span> radius; <span class="op">}</span>;</span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Rectangle <span class="op">:</span> Shape <span class="op">{</span> <span class="dt">int</span> width, height; <span class="op">}</span>;</span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> Shape<span class="op">&amp;</span> get_shape<span class="op">()</span>;</span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-7"><a href="#cb66-7" aria-hidden="true" tabindex="-1"></a>get_shape<span class="op">()</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb66-8"><a href="#cb66-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> Circle<span class="op">&amp;</span> c <span class="op">=&gt;</span> <span class="co">// runtime downcast to `Circle`.</span></span>
<span id="cb66-9"><a href="#cb66-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> s <span class="op">=&gt;</span> <span class="co">// `s` can&#39;t generically be `Triangle` or `Rectangle` anyway.</span></span>
<span id="cb66-10"><a href="#cb66-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This is what C# does for example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c#"><code class="sourceCode cs"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>Shape <span class="fu">get_shape</span><span class="op">();</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="fu">get_shape</span><span class="op">()</span> <span class="kw">switch</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  Circle c <span class="op">=&gt;</span> <span class="co">// runtime downcast to `Circle`</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">var</span> s <span class="op">=&gt;</span> <span class="co">// `s` is the whole shape.</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>While this syntax would work for polymorphic types specifically,
there is a general desire to unify the handling of sum types like
<code class="sourceCode cpp">variant</code> and polymorphic types. For
example, <span class="citation" data-cites="P2411R0">[<a href="https://wg21.link/p2411r0" role="doc-biblioref">P2411R0</a>]</span> points out:</p>
<blockquote>
<p>The ‘is’-and-‘as’ notation [P2392] is cleaner and more general than
the [P1371] and successors notation. For example, it eliminates the need
to use the different notation styles for variant, optional, and any
access. Uniform notation is the backbone of generic programming.</p>
</blockquote>
<p><span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span> already had uniform notation at
least for <code class="sourceCode cpp">variant</code>,
<code class="sourceCode cpp">any</code> and polymorphic types, but
regardless, the point is that using syntax that works only for
polymophic types but not <code class="sourceCode cpp">variant</code> is
not desired.</p>
<p><strong>Question 3</strong>: Initialization? Conversions?
First-match? Best-match?</p>
<p>Going back to the first example:</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">bool</span>, std<span class="op">::</span>string<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb67-5"><a href="#cb67-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> b <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb67-6"><a href="#cb67-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb67-7"><a href="#cb67-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Are these variable declarations initialized by direct-initialization,
copy-initialization, list-initialization, something else? Having to
answer this question isn’t necessarily a blocker, but one needs to be
chosen.</p>
<p>Regardless of the answer though, there’s no initialization form that
disallows conversions in general. If these have first-match semantics
(the only form of matching that has been proposed so far),
<code class="sourceCode cpp"><span class="dt">int</span> i</code> would
match if the variant is in the
<code class="sourceCode cpp"><span class="dt">bool</span></code> state,
since all of these are valid:</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i1<span class="op">(</span><span class="kw">true</span><span class="op">)</span>; <span class="co">// direct</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i2 <span class="op">=</span> <span class="kw">true</span>; <span class="co">// copy</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i3<span class="op">{</span><span class="kw">true</span><span class="op">}</span>; <span class="co">// list</span></span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i4 <span class="op">=</span> <span class="op">{</span><span class="kw">true</span><span class="op">}</span>; <span class="co">// copy-list</span></span></code></pre></div>
<p>On the other hand, best-match semantics would introduce significant
complexity. Value-matching needs to consider becoming best-match, and
this would likely mean evaluating more than necessary in order to
compute a score to best-match with. If value-matching remained
first-match, then we would have best-match semantics weaved info
first-match semantics. This is likely very difficult for users.</p>
<p>Note that even with best-match semantics, allowing conversions makes
code like this difficult to diagnose missing cases:</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// maybe missing bool case? it is covered by `int` though...</span></span>
<span id="cb69-5"><a href="#cb69-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><strong>Question 4</strong>: How do we match against an existing
value?</p>
<p>Variable declaration syntax isn’t conducive to referring to an
existing value. Suppose there is a constexpr value
<code class="sourceCode cpp">batch_size</code> that we want to match
against. <code class="sourceCode cpp"><span class="dt">int</span> batch_size</code>
wouldn’t work since that would be introducing a new variable.
<code class="sourceCode cpp">batch_size</code> could be annotated
somehow, but annotating existing names rather than the new names has
already been attempted.</p>
<p>More generally, variable declaration syntax isn’t conducive to
composition.</p>
<hr />
<p>With this paper, the first example would be written as:</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">bool</span>, std<span class="op">::</span>string<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb70-4"><a href="#cb70-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb70-5"><a href="#cb70-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span><span class="op">:</span> <span class="cf">let</span> b <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb70-6"><a href="#cb70-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string<span class="op">:</span> <span class="cf">let</span> s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb70-7"><a href="#cb70-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<ol type="1">
<li><code class="sourceCode cpp">i</code>,
<code class="sourceCode cpp">b</code>, and
<code class="sourceCode cpp">s</code> are bindings, introduced by
<code class="sourceCode cpp"><span class="cf">let</span></code>.</li>
<li>How do you disambiguate
<code class="sourceCode cpp"><span class="kw">auto</span> x</code>
between <code class="sourceCode cpp">variant</code> itself vs the
alternative inside?</li>
</ol>
<p>With this paper,
<code class="sourceCode cpp"><span class="cf">let</span> x</code> binds
the whole value, whereas <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">:</span> <span class="cf">let</span> x</code>
binds to the value inside the variant. The following is an example of
<code class="sourceCode cpp"><span class="cf">let</span> x</code>
binding the whole value:</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_int<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">)</span>;</span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a>parse_int<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// use `i` which is `int` returned by `parse_int`</span></span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>           <span class="co">// not 0 or 1</span></span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The following is an example of <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">:</span> <span class="cf">let</span> x</code>
where we bind the alternative inside the variant.</p>
<table>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a>  overload<span class="op">(</span></span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>,</span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span>,</span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>  parse<span class="op">(</span>some_input<span class="op">))</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">:</span> <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// x is bool or string</span></span>
<span id="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<ol start="3" type="1">
<li>Initialization? Conversions? First-match? Best-match?</li>
</ol>
<p>Initialization and conversions are dictated by the rules and
principles of bindings as introduced by structured bindings.</p>
<p>The problem of first-match vs best-match is solved by requiring an
<strong>exact-match</strong> for alternative types. With exact-match,
first-match and best-match become equivalent.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Variable Declaration Approach</strong>
</div></th>
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb74-3"><a href="#cb74-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb74-4"><a href="#cb74-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// missing bool case, but covered by `int`.</span></span>
<span id="cb74-5"><a href="#cb74-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-1" aria-hidden="true" tabindex="-1"></a>parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string<span class="op">:</span> <span class="cf">let</span> s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb75-4"><a href="#cb75-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: missing bool case</span></span>
<span id="cb75-5"><a href="#cb75-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>To be precise, the type to the left of the
<code class="sourceCode cpp"><span class="op">:</span></code> is used to
match an alternative <strong>as declared</strong>. This is similar to
how <code class="sourceCode cpp">std<span class="op">::</span>get</code>
works. For example:</p>
<div class="sourceCode" id="cb76"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb76-1"><a href="#cb76-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a>  v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// `const int` is required here.</span></span>
<span id="cb76-4"><a href="#cb76-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>string<span class="op">:</span> <span class="cf">let</span> s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb76-5"><a href="#cb76-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb76-6"><a href="#cb76-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="7.5" id="discussion-on-variant-like-types"><span class="header-section-number">7.5</span> Discussion on Variant-like
Types<a href="#discussion-on-variant-like-types" class="self-link"></a></h2>
<p>We have a few variant-like facilities:
<code class="sourceCode cpp">optional</code>,
<code class="sourceCode cpp">expected</code>, and
<code class="sourceCode cpp">variant</code>. Type-based alternative
matching for
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
seems pretty obvious.</p>
<div class="sourceCode" id="cb77"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb77-1"><a href="#cb77-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a>  v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb77-3"><a href="#cb77-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb77-4"><a href="#cb77-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>string<span class="op">:</span> <span class="cf">let</span> s <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb77-5"><a href="#cb77-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb77-6"><a href="#cb77-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code class="sourceCode cpp"><span class="dt">int</span></code>
and <code class="sourceCode cpp">string</code> are the states that a
<code class="sourceCode cpp">variant<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span></code>
can be in, and facilities such as <code class="sourceCode cpp">holds_alternative<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
and <code class="sourceCode cpp">get<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
clearly provide type-based access to
<code class="sourceCode cpp">variant</code>.</p>
<p>Of course, in general there’s more to it. The
<code class="sourceCode cpp">variant</code> could be in a
valueless-by-exception state, or we can have <code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>.
Let’s table these for now.</p>
<p>The <code class="sourceCode cpp"><span class="op">?</span> <em>pattern</em></code>
specifically supports the pointer-like usage pattern, so we can
write:</p>
<div class="sourceCode" id="cb78"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb78-1"><a href="#cb78-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">*</span> p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-2"><a href="#cb78-2" aria-hidden="true" tabindex="-1"></a>  p <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb78-3"><a href="#cb78-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">?</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb78-4"><a href="#cb78-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">nullptr</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb78-5"><a href="#cb78-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb78-6"><a href="#cb78-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code class="sourceCode cpp">optional</code> and
<code class="sourceCode cpp">expected</code> are
“<code class="sourceCode cpp">variant</code>-like” in that they have
“one-of” states. However, their interfaces are not
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>-like
at all. They carry much more semantic implications. <code class="sourceCode cpp">optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
behaves more like <code class="sourceCode cpp">T</code> than <code class="sourceCode cpp">variant<span class="op">&lt;</span>std<span class="op">::</span>nullopt_t, T<span class="op">&gt;</span></code>
would. <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
behaves more like <code class="sourceCode cpp">T</code> than
<code class="sourceCode cpp">E</code>, and again, more like
<code class="sourceCode cpp">T</code> than <code class="sourceCode cpp">variant<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
would. Their interfaces are also pointer-like rather than
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>-like.</p>
<p>Given this, it seems natural enough to match on an
<code class="sourceCode cpp">optional</code> like this:</p>
<div class="sourceCode" id="cb79"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb79-1"><a href="#cb79-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>  o <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb79-3"><a href="#cb79-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">?</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb79-4"><a href="#cb79-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>nullopt <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb79-5"><a href="#cb79-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb79-6"><a href="#cb79-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>-like
approach would look like this:</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb80-1"><a href="#cb80-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a>  o <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb80-4"><a href="#cb80-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>nullopt_t<span class="op">:</span> _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb80-5"><a href="#cb80-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb80-6"><a href="#cb80-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Here, if we changed <code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
to say, a <code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;</span></code>
the <code class="sourceCode cpp"><span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i</code>
pattern would be ill-formed, whereas the
<code class="sourceCode cpp"><span class="op">?</span></code> would
continue to work. This is consistent with the usage of
<code class="sourceCode cpp">optional</code> today:</p>
<div class="sourceCode" id="cb81"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb81-1"><a href="#cb81-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb81-2"><a href="#cb81-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// no mention of `int` in the below usage.</span></span>
<span id="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb81-4"><a href="#cb81-4" aria-hidden="true" tabindex="-1"></a>    use<span class="op">(*</span>o<span class="op">)</span>;</span>
<span id="cb81-5"><a href="#cb81-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb81-6"><a href="#cb81-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb81-7"><a href="#cb81-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb81-8"><a href="#cb81-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><strong>Open Question</strong>: For exhaustiveness checking purposes,
matching with
<code class="sourceCode cpp"><span class="op">?</span></code> then
<code class="sourceCode cpp">_</code> will always be sufficient. But
this means <code class="sourceCode cpp"><span class="op">?</span></code>
will need to be matched first. For types like
<code class="sourceCode cpp">T<span class="op">*</span></code> and
<code class="sourceCode cpp">unique_ptr</code>, it should be possible to
say matching with
<code class="sourceCode cpp"><span class="op">?</span></code> and
<code class="sourceCode cpp"><span class="kw">nullptr</span></code> is
exhaustive, and
<code class="sourceCode cpp"><span class="kw">nullptr</span></code> can
be matched first as well. For
<code class="sourceCode cpp">optional</code> though, the null state is
<code class="sourceCode cpp">std<span class="op">::</span>nullopt</code>.
To use
<code class="sourceCode cpp"><span class="kw">nullptr</span></code> for
this seems wrong, given that
<code class="sourceCode cpp">optional</code> design explicitly
introduced <code class="sourceCode cpp">nullopt</code> over using
<code class="sourceCode cpp"><span class="kw">nullptr</span></code>
itself. The solution in <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span> is to introduce <code class="sourceCode cpp"><span class="cf">is</span> <span class="dt">void</span></code>,
but this seems problematic at least for <code class="sourceCode cpp">expected<span class="op">&lt;</span><span class="dt">void</span>, error<span class="op">&gt;</span></code>
where the question becomes ambiguous.</p>
<p>But <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
gets more tricky. The “no value” case is not just some sentinel
type/value, but is some type <code class="sourceCode cpp">E</code>
retrieved by <code class="sourceCode cpp"><span class="op">.</span>error<span class="op">()</span></code>.</p>
<div class="sourceCode" id="cb82"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb82-2"><a href="#cb82-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb82-3"><a href="#cb82-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">?</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb82-4"><a href="#cb82-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// How do we match and access `.error()` ?</span></span>
<span id="cb82-5"><a href="#cb82-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb82-6"><a href="#cb82-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So perhaps a <code class="sourceCode cpp">variant</code>-like
approach would be better here:</p>
<div class="sourceCode" id="cb83"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb83-1"><a href="#cb83-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb83-2"><a href="#cb83-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb83-3"><a href="#cb83-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb83-4"><a href="#cb83-4" aria-hidden="true" tabindex="-1"></a>    parse_error<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb83-5"><a href="#cb83-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb83-6"><a href="#cb83-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This seems simple and clean enough. Similar to
<code class="sourceCode cpp">variant</code> however, we can have <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>.
Unlike <code class="sourceCode cpp">variant</code> though, it actually
goes out of its way to store a <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as the error state to distinguish the two. It’s conceivable to use this
unexpected type to support <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>:</p>
<div class="sourceCode" id="cb84"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb84-1"><a href="#cb84-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb84-2"><a href="#cb84-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb84-3"><a href="#cb84-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb84-4"><a href="#cb84-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>unexpected<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// distinguish</span></span>
<span id="cb84-5"><a href="#cb84-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb84-6"><a href="#cb84-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But that would really hinder the by-far more common use cases:</p>
<div class="sourceCode" id="cb85"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb85-1"><a href="#cb85-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb85-3"><a href="#cb85-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb85-4"><a href="#cb85-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>unexpected<span class="op">&lt;</span>parse_error<span class="op">&gt;:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// yuck</span></span>
<span id="cb85-5"><a href="#cb85-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb85-6"><a href="#cb85-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It was considered to allow matching <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>
with <code class="sourceCode cpp">T</code> and <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
while matching <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
with <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">E</code>. But it’s a bit weird for <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>E<span class="op">&gt;</span></code>
to then not work at all, and also weird for
<code class="sourceCode cpp">err</code> in <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>E<span class="op">&gt;:</span> <span class="cf">let</span> err</code>
to not be a binding to a <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>E<span class="op">&gt;</span></code>,
but rather a binding to a <code class="sourceCode cpp">E</code>. A
reference to the underlying <code class="sourceCode cpp">std<span class="op">::</span>unexpected<span class="op">&lt;</span>E<span class="op">&gt;</span></code>
is also not an interface that <code class="sourceCode cpp">std<span class="op">::</span>expected</code>
exposes. Furthermore, this wouldn’t solve the problem of <code class="sourceCode cpp">variant<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>
in a consistent manner. At best it’d be a special case for <code class="sourceCode cpp">std<span class="op">::</span>expected</code>.</p>
<p>Ideally, <code class="sourceCode cpp">value</code> and
<code class="sourceCode cpp">error</code> would be
<strong>names</strong> associated to the <strong>types</strong>
<code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">E</code>, such that they can be used even
when <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">E</code> are the same, and are stable even
when <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">E</code> changes.</p>
<p>This is essentially how the
<code class="sourceCode cpp">Result</code> type in Rust is defined, as
well as many other languages that provide similar functionalities.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="dt">Result</span><span class="op">&lt;</span>T<span class="op">,</span> E<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="cn">Ok</span>(T)<span class="op">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="cn">Err</span>(E)<span class="op">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is matched like this:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="cf">match</span> parse(some_input) <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="cn">Ok</span>(v) <span class="op">=&gt;</span> <span class="co">// use `v`</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="cn">Err</span>(err) <span class="op">=&gt;</span> <span class="co">// use `err`</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A few approaches were considered to emulate this “name-based”
dispatch.</p>
<ol type="1">
<li>Introduce a parallel <code class="sourceCode cpp"><span class="kw">enum</span> <span class="kw">class</span></code>
with the desired names.</li>
</ol>
<div class="sourceCode" id="cb86"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb86-1"><a href="#cb86-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> expected_state <span class="op">{</span> value, error <span class="op">}</span>;</span>
<span id="cb86-2"><a href="#cb86-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-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="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> expected <span class="op">{</span></span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb86-6"><a href="#cb86-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-7"><a href="#cb86-7" aria-hidden="true" tabindex="-1"></a>  expected_state index<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb86-8"><a href="#cb86-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> has_value<span class="op">()</span> <span class="op">?</span> expected_state<span class="op">::</span>value <span class="op">:</span> expected_state<span class="op">::</span>error;</span>
<span id="cb86-9"><a href="#cb86-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb86-10"><a href="#cb86-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-11"><a href="#cb86-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>expected_state S<span class="op">&gt;</span></span>
<span id="cb86-12"><a href="#cb86-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">&amp;&amp;</span> get<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-13"><a href="#cb86-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>S <span class="op">==</span> expected_state<span class="op">::</span>value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-14"><a href="#cb86-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">*</span>std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>self<span class="op">)&gt;(</span>self<span class="op">)</span>;</span>
<span id="cb86-15"><a href="#cb86-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>S <span class="op">==</span> expected_state<span class="op">::</span>error<span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-16"><a href="#cb86-16" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>self<span class="op">)&gt;(</span>self<span class="op">).</span>error<span class="op">()</span>;</span>
<span id="cb86-17"><a href="#cb86-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb86-18"><a href="#cb86-18" aria-hidden="true" tabindex="-1"></a>      <span class="kw">static_assert</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span>;</span>
<span id="cb86-19"><a href="#cb86-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb86-20"><a href="#cb86-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb86-21"><a href="#cb86-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb86-22"><a href="#cb86-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-23"><a href="#cb86-23" aria-hidden="true" tabindex="-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="cb86-24"><a href="#cb86-24" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> variant_size<span class="op">&lt;</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span> <span class="op">:</span> std<span class="op">::</span>integral_constant<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="dv">2</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb86-25"><a href="#cb86-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-26"><a href="#cb86-26" aria-hidden="true" tabindex="-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="cb86-27"><a href="#cb86-27" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> variant_alternative<span class="op">&lt;(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>expected_state<span class="op">::</span>value, expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb86-28"><a href="#cb86-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb86-29"><a href="#cb86-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb86-30"><a href="#cb86-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-31"><a href="#cb86-31" aria-hidden="true" tabindex="-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="cb86-32"><a href="#cb86-32" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> variant_alternative<span class="op">&lt;(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>expected_state<span class="op">::</span>error, expected<span class="op">&lt;</span>T, E<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb86-33"><a href="#cb86-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> E;</span>
<span id="cb86-34"><a href="#cb86-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The usage would need to be something along the lines of:</p>
<div class="sourceCode" id="cb87"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb87-1"><a href="#cb87-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view sv<span class="op">)</span>;</span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb87-4"><a href="#cb87-4" aria-hidden="true" tabindex="-1"></a>  parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb87-5"><a href="#cb87-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <span class="kw">enum</span> std<span class="op">::</span>expected_state;</span>
<span id="cb87-6"><a href="#cb87-6" aria-hidden="true" tabindex="-1"></a>    value<span class="op">:</span> <span class="cf">let</span> v <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb87-7"><a href="#cb87-7" aria-hidden="true" tabindex="-1"></a>    error<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb87-8"><a href="#cb87-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb87-9"><a href="#cb87-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>While the introduction of <code class="sourceCode cpp">std<span class="op">::</span>expected_state</code>
seems a bit odd on first glance, it actually doesn’t seem any more odd
than other related helper types such as <code class="sourceCode cpp">std<span class="op">::</span>in_place_t</code>,
<code class="sourceCode cpp">std<span class="op">::</span>unexpect_t</code>,
<code class="sourceCode cpp">std<span class="op">::</span>unexpected</code>,
etc.</p>
<ol start="2" type="1">
<li>Use the existing tag types</li>
</ol>
<p>We already have tag types, and they roughly correspond with the
various states. For example, <code class="sourceCode cpp">std<span class="op">::</span>expected</code> uses
<code class="sourceCode cpp">std<span class="op">::</span>in_place_t</code>
and <code class="sourceCode cpp">std<span class="op">::</span>unexpect_t</code>.</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb88-1"><a href="#cb88-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb88-3"><a href="#cb88-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>in_place_t<span class="op">:</span> <span class="cf">let</span> v <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb88-4"><a href="#cb88-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>unexpect_t<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb88-5"><a href="#cb88-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb88-6"><a href="#cb88-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The names <code class="sourceCode cpp">std<span class="op">::</span>in_place_t</code>
and <code class="sourceCode cpp">std<span class="op">::</span>unexpect_t</code>
are terrible substitute for <code class="sourceCode cpp">value</code>
and <code class="sourceCode cpp">error</code>. We’d be better off with
just using the types directly, and not fully supporting the <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code>
case.</p>
<ol start="3" type="1">
<li>Use the reflection of the accessors as the tags</li>
</ol>
<p>This idea would be to come up with a new variant-like protocol using
reflection. If a type let’s say were to advertise its alternatives
through <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;</span></code>,
and we use those as the tags for dispatching…</p>
<div class="sourceCode" id="cb89"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb89-1"><a href="#cb89-1" aria-hidden="true" tabindex="-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="cb89-2"><a href="#cb89-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> expected <span class="op">{</span></span>
<span id="cb89-3"><a href="#cb89-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;</span> alternatives<span class="op">()</span> <span class="op">{</span></span>
<span id="cb89-4"><a href="#cb89-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{</span> <span class="op">^</span>value, <span class="op">^</span>error <span class="op">}</span>;</span>
<span id="cb89-5"><a href="#cb89-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb89-6"><a href="#cb89-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-7"><a href="#cb89-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb89-8"><a href="#cb89-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> E<span class="op">&amp;</span> error<span class="op">()</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="kw">noexcept</span>;</span>
<span id="cb89-9"><a href="#cb89-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// other qualified versions...</span></span>
<span id="cb89-10"><a href="#cb89-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>With this, perhaps we could pull off something like:</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb90-1"><a href="#cb90-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>    e<span class="op">.</span>value<span class="op">:</span> <span class="cf">let</span> v <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb90-4"><a href="#cb90-4" aria-hidden="true" tabindex="-1"></a>    e<span class="op">.</span>error<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb90-5"><a href="#cb90-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb90-6"><a href="#cb90-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I think this is a very interesting direction for both tuple-like and
variant-like protocols, but I haven’t been able to flesh out the
details. See <a href="#reflection-based-tuple-like-and-variant-like-customization-points">Reflection-based
Tuple-like and Variant-like Customization Points</a>.</p>
<p>In the end, the suggested path for now is:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">T<span class="op">*</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb91"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb91-1"><a href="#cb91-1" aria-hidden="true" tabindex="-1"></a>ptr <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">?</span> <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">nullptr</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb92"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb92-1"><a href="#cb92-1" aria-hidden="true" tabindex="-1"></a>opt <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">?</span> <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>nullopt <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb92-4"><a href="#cb92-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb93"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb93-1"><a href="#cb93-1" aria-hidden="true" tabindex="-1"></a>e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb93-2"><a href="#cb93-2" aria-hidden="true" tabindex="-1"></a>  T<span class="op">:</span> <span class="cf">let</span> v <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb93-3"><a href="#cb93-3" aria-hidden="true" tabindex="-1"></a>  E<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb93-4"><a href="#cb93-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb94"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb94-1"><a href="#cb94-1" aria-hidden="true" tabindex="-1"></a>v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a>  T<span class="op">:</span> <span class="cf">let</span> t <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb94-3"><a href="#cb94-3" aria-hidden="true" tabindex="-1"></a>  U<span class="op">:</span> <span class="cf">let</span> u <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb94-4"><a href="#cb94-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="7.6" id="reflection-based-tuple-like-and-variant-like-customization-points"><span class="header-section-number">7.6</span> Reflection-based Tuple-like and
Variant-like Customization Points<a href="#reflection-based-tuple-like-and-variant-like-customization-points" class="self-link"></a></h2>
<p>“Tuple-like” customization today involves specializing <code class="sourceCode cpp">std<span class="op">::</span>tuple_size</code>,
<code class="sourceCode cpp">std<span class="op">::</span>tuple_element</code>,
and implementing a <code class="sourceCode cpp">get<span class="op">&lt;</span>I<span class="op">&gt;</span></code>
function. Section 2.3.6 “Cleaner form for structured
bindings’”tuple-like” customization” from <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span> has a good summary of the
problem.</p>
<p>It also also says:</p>
<blockquote>
<p>If we want to go further, then as Bjarne Stroustrup points out, the
logical minimum is something like this, which can be viewed as a jump
table (similar to a vtbl) – the most general form, ideally provided by
the class author:</p>
<div class="sourceCode" id="cb95"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb95-1"><a href="#cb95-1" aria-hidden="true" tabindex="-1"></a>  structure_map <span class="op">(</span>EncapsulatedRect<span class="op">)</span> <span class="op">{</span> topLeft, width, height <span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>and as Bjarne Stroustup points out in <span class="citation" data-cites="P2411R0">[<a href="https://wg21.link/p2411r0" role="doc-biblioref">P2411R0</a>]</span>:</p>
<blockquote>
<p>The mapping from an encapsulating type to a set of values used by
pattern matching must be simple and declarative. The use of <code class="sourceCode cpp">get<span class="op">&lt;&gt;()</span></code> for
structured binding is an expert-only mess. Any code-based, as opposed to
declarative, mapping will have such problems in use and complicate
optimization. We can do much better.</p>
</blockquote>
<p>Perhaps this problem can be tackled with reflection.</p>
<div class="sourceCode" id="cb96"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb96-1"><a href="#cb96-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> EcapsulatedRect <span class="op">{</span></span>
<span id="cb96-2"><a href="#cb96-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;</span> elements<span class="op">()</span> <span class="op">{</span></span>
<span id="cb96-3"><a href="#cb96-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{</span> <span class="op">^</span>topLeft, <span class="op">^</span>width, <span class="op">^</span>height <span class="op">}</span>;</span>
<span id="cb96-4"><a href="#cb96-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb96-5"><a href="#cb96-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb96-6"><a href="#cb96-6" aria-hidden="true" tabindex="-1"></a>  Point topLeft<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb96-7"><a href="#cb96-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> width<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb96-8"><a href="#cb96-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> height<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb96-9"><a href="#cb96-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The advantage of this is that we can put data members as well as
member functions into <code class="sourceCode cpp">elements</code> as
opaque reflections and apply them when needed.</p>
<p>Similarly, it seems feasible for there to be a reflection-based
variant-like protocol as well.</p>
<div class="sourceCode" id="cb97"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb97-1"><a href="#cb97-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> variant <span class="op">{</span></span>
<span id="cb97-3"><a href="#cb97-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;</span> alternatives<span class="op">()</span> <span class="op">{</span></span>
<span id="cb97-4"><a href="#cb97-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{</span> <span class="op">^</span>Ts<span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb97-5"><a href="#cb97-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb97-6"><a href="#cb97-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-7"><a href="#cb97-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb97-8"><a href="#cb97-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Note that for tuple-like protocol, even if we were to come up with
something better, I think we’ll still have to continue supporting the
current protocol. There are types written that opted into that protocol
that use structured bindings and
<code class="sourceCode cpp">std<span class="op">::</span>apply</code>
and other things today.</p>
<p>Variant-like protocol is actually a different story. Unlike
tuple-like protocol, The variant helpers such as <code class="sourceCode cpp">std<span class="op">::</span>variant_size</code>,
<code class="sourceCode cpp">std<span class="op">::</span>variant_alternative</code>
are solely used by
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>.
<code class="sourceCode cpp">std<span class="op">::</span>visit</code>,
the only thing that might already be using a “variant-like protocol”
does not support
non-<code class="sourceCode cpp">std<span class="op">::</span>variant</code>s.
It does support types that directly inherit from
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
<span class="citation" data-cites="P2162R2">[<a href="https://wg21.link/p2162r2" role="doc-biblioref">P2162R2</a>]</span>, but they work by being
converted into
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
beforehand.</p>
<p>As such, there’s a bigger opportunity for variant-like protocol to
not bless the existing set of facilities but to come up with something
better.</p>
<p><strong>Update R2</strong>: This paper proposes to go with the
existing facilities for now. While this direction is interesting, it is
likely better to gain experience with reflection in C++26 before really
coming up with a solution to supersede the existing facilities.</p>
<h2 data-number="7.7" id="more-on-static-conditions"><span class="header-section-number">7.7</span> More on Static Conditions<a href="#more-on-static-conditions" class="self-link"></a></h2>
<p>This is an elaboration of the discussion from <a href="#static-conditions">Static Conditions</a>. The question is: how
are the requirements and validity of patterns handled? The proposed
solution in this paper is for the static conditions to always be
checked. For templates, this means the they are checked at
instantiation.</p>
<p>Another approach is for some patterns to allow to be invalid if the
<em>subject</em> is a dependent value. Since in this case, the pattern
<strong>can be</strong> valid under some instantiations.</p>
<p>This can be made to work, and would certainly useful. As the default
behavior however, it seems like it will likely cause subtle bugs.</p>
<p>Consider an example like this:</p>
<div class="sourceCode" id="cb98"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb98-1"><a href="#cb98-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Operator<span class="op">&gt;</span></span>
<span id="cb98-2"><a href="#cb98-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">const</span> Operator<span class="op">&amp;</span> op<span class="op">)</span> <span class="op">{</span></span>
<span id="cb98-3"><a href="#cb98-3" aria-hidden="true" tabindex="-1"></a>  op<span class="op">.</span>kind<span class="op">()</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb98-4"><a href="#cb98-4" aria-hidden="true" tabindex="-1"></a>    <span class="ch">&#39;+&#39;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb98-5"><a href="#cb98-5" aria-hidden="true" tabindex="-1"></a>    <span class="ch">&#39;-&#39;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb98-6"><a href="#cb98-6" aria-hidden="true" tabindex="-1"></a>    <span class="ch">&#39;*&#39;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb98-7"><a href="#cb98-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;/&quot;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb98-8"><a href="#cb98-8" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="cf">throw</span> UnknownOperator<span class="op">{}</span>;</span>
<span id="cb98-9"><a href="#cb98-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb98-10"><a href="#cb98-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s say <code class="sourceCode cpp">op<span class="op">.</span>kind<span class="op">()</span></code>
returns a
<code class="sourceCode cpp"><span class="dt">char</span></code>, but we
can’t be sure of that since <code class="sourceCode cpp">op</code> is
templated. With the approach in this proposal, the typo of <code class="sourceCode cpp"><span class="st">&quot;/&quot;</span></code>
(should be
<code class="sourceCode cpp"><span class="ch">&#39;/&#39;</span></code>!)
will be detected as a compile-time error. In a model where a pattern can
be invalid because the <em>subject</em> is dependent, this will likely
be well-formed, fallthrough to the <code class="sourceCode cpp">_</code>
case, and throw an exception at runtime.</p>
<p>It’s true that this function should probably be better constrained
using concepts, but the reality is that this kind of code is extremely
prevalent today. Note that just using
<code class="sourceCode cpp"><span class="cf">if</span></code>, we would
have been provided this safety:</p>
<div class="sourceCode" id="cb99"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb99-1"><a href="#cb99-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Operator<span class="op">&gt;</span></span>
<span id="cb99-2"><a href="#cb99-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">const</span> Operator<span class="op">&amp;</span> op<span class="op">)</span> <span class="op">{</span></span>
<span id="cb99-3"><a href="#cb99-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>op<span class="op">.</span>kind<span class="op">()</span> <span class="op">==</span> <span class="ch">&#39;+&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb99-4"><a href="#cb99-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb99-5"><a href="#cb99-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>op<span class="op">.</span>kind<span class="op">()</span> <span class="op">==</span> <span class="ch">&#39;-&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb99-6"><a href="#cb99-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb99-7"><a href="#cb99-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>op<span class="op">.</span>kind<span class="op">()</span> <span class="op">==</span> <span class="ch">&#39;*&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb99-8"><a href="#cb99-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb99-9"><a href="#cb99-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>op<span class="op">.</span>kind<span class="op">()</span> <span class="op">==</span> <span class="st">&quot;/&quot;</span><span class="op">)</span> <span class="op">{</span> <span class="co">// error: comparison between pointer and integer</span></span>
<span id="cb99-10"><a href="#cb99-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb99-11"><a href="#cb99-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb99-12"><a href="#cb99-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">throw</span> UnknownOperator<span class="op">{}</span>;</span>
<span id="cb99-13"><a href="#cb99-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb99-14"><a href="#cb99-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="#testing-the-static-conditions-with-match-requires">Testing
the Static Conditions with <code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code></a>
is described as a future extension where users can explicitly opt in to
relax this requirement on <em>static conditions</em>.</p>
<h2 data-number="7.8" id="operator-precedence-of-match"><span class="header-section-number">7.8</span> Operator Precedence of
<code class="sourceCode cpp"><span class="cf">match</span></code><a href="#operator-precedence-of-match" class="self-link"></a></h2>
<h3 data-number="7.8.1" id="proposed-solution-between-pointer-to-member-and-multiplicative-operator"><span class="header-section-number">7.8.1</span> Proposed Solution: Between
Pointer-to-member and Multiplicative Operator<a href="#proposed-solution-between-pointer-to-member-and-multiplicative-operator" class="self-link"></a></h3>
<p>The proposed solution in this paper is for
<code class="sourceCode cpp"><span class="cf">match</span></code> to
have a precedence between pointer-to-member operators <span>7.6.4
<a href="https://wg21.link/expr.mptr.oper">[expr.mptr.oper]</a></span>
and multiplicative operators <span>7.6.5
<a href="https://wg21.link/expr.mul">[expr.mul]</a></span>. This is
consistent with the approach proposed for the
<code class="sourceCode cpp"><span class="cf">is</span></code> operator
in <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span>, and similar to the precedence
of C# <code class="sourceCode cpp"><span class="cf">switch</span></code>
expression.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb100"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb100-1"><a href="#cb100-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><em>a</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-2"><a href="#cb100-2" aria-hidden="true" tabindex="-1"></a><em>a</em><span class="op">.*</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-3"><a href="#cb100-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-4"><a href="#cb100-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-5"><a href="#cb100-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-6"><a href="#cb100-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-7"><a href="#cb100-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-8"><a href="#cb100-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-9"><a href="#cb100-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb100-10"><a href="#cb100-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb101"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb101-1"><a href="#cb101-1" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span><em>a</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb101-2"><a href="#cb101-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em><span class="op">.*</span><em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb101-3"><a href="#cb101-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-4"><a href="#cb101-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-5"><a href="#cb101-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-6"><a href="#cb101-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-7"><a href="#cb101-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-8"><a href="#cb101-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-9"><a href="#cb101-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb101-10"><a href="#cb101-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb102"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb102-1"><a href="#cb102-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><em>a</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-2"><a href="#cb102-2" aria-hidden="true" tabindex="-1"></a><em>a</em><span class="op">.*</span><em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-3"><a href="#cb102-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-4"><a href="#cb102-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-5"><a href="#cb102-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-6"><a href="#cb102-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-7"><a href="#cb102-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-8"><a href="#cb102-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-9"><a href="#cb102-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb102-10"><a href="#cb102-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb103"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb103-1"><a href="#cb103-1" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span><em>a</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb103-2"><a href="#cb103-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em><span class="op">.*</span><em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb103-3"><a href="#cb103-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-4"><a href="#cb103-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-5"><a href="#cb103-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-6"><a href="#cb103-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-7"><a href="#cb103-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-8"><a href="#cb103-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-9"><a href="#cb103-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb103-10"><a href="#cb103-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The main advantage of this approach is that the model is quite
simple. The main idea is
“<code class="sourceCode cpp"><span class="cf">match</span></code> binds
tighter than any binary operator except pointer-to-member.”
Pointer-to-member operators are excluded since many folks expect it to
bind tighter than they actually do.</p>
<p>There are a couple of other advantages worth mentioning. One is that
this approach still reads as expected with parentheses. Consider the
following example:</p>
<div class="sourceCode" id="cb104"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb104-1"><a href="#cb104-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <span class="op">(</span><em>b</em> <span class="op">+</span> <em>c</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb104-2"><a href="#cb104-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb104-3"><a href="#cb104-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb104-4"><a href="#cb104-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb104-5"><a href="#cb104-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Here, I’d argue that <code class="sourceCode cpp"><span class="op">(</span><em>b</em> <span class="op">+</span> <em>c</em><span class="op">)</span></code>
looks like the match subject, and with this precedence it is indeed the
match subject.</p>
<p>Another advantage is that (though perhaps silly) it’s typically work
to add parentheses around the subject rather than around the whole
<code class="sourceCode cpp"><span class="cf">match</span></code>.</p>
<p>For example, given:</p>
<div class="sourceCode" id="cb105"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb105-1"><a href="#cb105-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb105-2"><a href="#cb105-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb105-3"><a href="#cb105-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb105-4"><a href="#cb105-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb105-5"><a href="#cb105-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Parenthesizing the subject is typically less work:</p>
<div class="sourceCode" id="cb106"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb106-1"><a href="#cb106-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb106-2"><a href="#cb106-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb106-3"><a href="#cb106-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb106-4"><a href="#cb106-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb106-5"><a href="#cb106-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Compared to having to add them around the whole
<code class="sourceCode cpp"><span class="cf">match</span></code> like
this:</p>
<div class="sourceCode" id="cb107"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb107-1"><a href="#cb107-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb107-2"><a href="#cb107-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb107-3"><a href="#cb107-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb107-4"><a href="#cb107-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb107-5"><a href="#cb107-5" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>
<p>The disadvantages of this approach is basically that if the desired
semantics are to match against the result of <code class="sourceCode cpp"><em>a</em> <span class="op">+</span> <em>b</em></code>,
parentheses are required.</p>
<div class="sourceCode" id="cb108"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb108-1"><a href="#cb108-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb108-2"><a href="#cb108-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb108-3"><a href="#cb108-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb108-4"><a href="#cb108-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb108-5"><a href="#cb108-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Similarly, another use case is to match against the result of
<code class="sourceCode cpp"><span class="op">&lt;=&gt;</span></code>,
which also need parentheses:</p>
<div class="sourceCode" id="cb109"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb109-1"><a href="#cb109-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb109-2"><a href="#cb109-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>equal <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb109-3"><a href="#cb109-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>less <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb109-4"><a href="#cb109-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>greater <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb109-5"><a href="#cb109-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Another disadvantage is the deviation from
<code class="sourceCode cpp"><span class="op">==</span></code> in the
<code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <em>expr</em></code>
form:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb110"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb110-1"><a href="#cb110-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="op">==</span> <em>c</em></span>
<span id="cb110-2"><a href="#cb110-2" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <em>c</em></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb111"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb111-1"><a href="#cb111-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="op">==</span> <em>c</em></span>
<span id="cb111-2"><a href="#cb111-2" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>Despite the disadvantages, this paper proposes the simplified model,
and users are expected to “parenthesize binary expressions”.</p>
<h3 data-number="7.8.2" id="alternative-considered-between-spaceship-and-relational-operator"><span class="header-section-number">7.8.2</span> Alternative Considered:
Between Spaceship and Relational Operator<a href="#alternative-considered-between-spaceship-and-relational-operator" class="self-link"></a></h3>
<p>This approach is to have the
<code class="sourceCode cpp"><span class="cf">match</span></code>
precedence between the three-way comparison operator <span>7.6.8
<a href="https://wg21.link/expr.spaceship">[expr.spaceship]</a></span>
and relational operators <span>7.6.9
<a href="https://wg21.link/expr.rel">[expr.rel]</a></span>.</p>
<p>The main idea here is that
<code class="sourceCode cpp"><span class="op">&lt;=&gt;</span></code>
and above,
e.g. <code class="sourceCode cpp"><span class="op">*</span></code>,
<code class="sourceCode cpp"><span class="op">+</span></code>, etc yield
interesting values to match, whereas
<code class="sourceCode cpp"><span class="op">&lt;</span></code> and
below,
e.g. <code class="sourceCode cpp"><span class="op">==</span></code>,
<code class="sourceCode cpp"><span class="op">&amp;</span></code>, etc
yield a boolean values which are typically less interesting.</p>
<p>This addresses some of the disadvantages mentioned in the previous
section.</p>
<div class="sourceCode" id="cb112"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb112-1"><a href="#cb112-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb112-2"><a href="#cb112-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb112-3"><a href="#cb112-3" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb112-4"><a href="#cb112-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb112-5"><a href="#cb112-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb113"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb113-1"><a href="#cb113-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb113-2"><a href="#cb113-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>equal <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb113-3"><a href="#cb113-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>less <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb113-4"><a href="#cb113-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strong_ordering<span class="op">::</span>greater <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb113-5"><a href="#cb113-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The disadvantage here is that the above examples may give a “false
sense of security”. If one wants to match on the result of say, <code class="sourceCode cpp"><em>a</em> <span class="op">&lt;</span> <em>b</em></code>,
parentheses are still required:</p>
<div class="sourceCode" id="cb114"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb114-1"><a href="#cb114-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb114-2"><a href="#cb114-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">true</span> <span class="op">=&gt;</span> <span class="op">...</span></span>
<span id="cb114-3"><a href="#cb114-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">false</span> <span class="op">=&gt;</span> <span class="op">...</span></span>
<span id="cb114-4"><a href="#cb114-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>However, these use cases are likely to be less common than the above
cases. Furthermore, we do not want to go much lower than this. Examples
such as <code class="sourceCode cpp"><em>a</em> <span class="op">==</span> <em>b</em> <span class="op">&amp;&amp;</span> <em>x</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></code>
are relatively common, and the desired parsing is <code class="sourceCode cpp"><span class="op">(</span><em>a</em> <span class="op">==</span> <em>b</em><span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>x</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></code>.
Especially for the <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <em>expr</em></code>
form, given <code class="sourceCode cpp"><em>a</em> <span class="op">&amp;&amp;</span> <em>b</em> <span class="cf">match</span> <em>c</em></code>
it’s more likely we want <code class="sourceCode cpp"><em>a</em> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></code>.</p>
<p>As mentioned in the previous section, this approach could cause some
confusion in the face of parenthesized expressions. For example,</p>
<div class="sourceCode" id="cb115"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb115-1"><a href="#cb115-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <span class="op">(</span><em>b</em> <span class="op">+</span> <em>c</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb115-2"><a href="#cb115-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb115-3"><a href="#cb115-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This would parse as</p>
<div class="sourceCode" id="cb116"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb116-1"><a href="#cb116-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">*</span> <span class="op">(</span><em>b</em> <span class="op">+</span> <em>c</em><span class="op">))</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb116-2"><a href="#cb116-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb116-3"><a href="#cb116-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>which could be surprising.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb117"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb117-1"><a href="#cb117-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><em>a</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-2"><a href="#cb117-2" aria-hidden="true" tabindex="-1"></a><em>a</em><span class="op">.*</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-3"><a href="#cb117-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-4"><a href="#cb117-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-5"><a href="#cb117-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-6"><a href="#cb117-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-7"><a href="#cb117-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-8"><a href="#cb117-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-9"><a href="#cb117-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb117-10"><a href="#cb117-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb118"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb118-1"><a href="#cb118-1" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span><em>a</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-2"><a href="#cb118-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em><span class="op">.*</span><em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-3"><a href="#cb118-3" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">*</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-4"><a href="#cb118-4" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-5"><a href="#cb118-5" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-6"><a href="#cb118-6" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb118-7"><a href="#cb118-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb118-8"><a href="#cb118-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb118-9"><a href="#cb118-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span>
<span id="cb118-10"><a href="#cb118-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">})</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb119"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb119-1"><a href="#cb119-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><em>a</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-2"><a href="#cb119-2" aria-hidden="true" tabindex="-1"></a><em>a</em><span class="op">.*</span><em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-3"><a href="#cb119-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">*</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-4"><a href="#cb119-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-5"><a href="#cb119-5" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-6"><a href="#cb119-6" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-7"><a href="#cb119-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-8"><a href="#cb119-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-9"><a href="#cb119-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb119-10"><a href="#cb119-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb120"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb120-1"><a href="#cb120-1" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span><em>a</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-2"><a href="#cb120-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em><span class="op">.*</span><em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-3"><a href="#cb120-3" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">*</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-4"><a href="#cb120-4" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-5"><a href="#cb120-5" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;&lt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-6"><a href="#cb120-6" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;=&gt;</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb120-7"><a href="#cb120-7" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb120-8"><a href="#cb120-8" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">==</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb120-9"><a href="#cb120-9" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span>
<span id="cb120-10"><a href="#cb120-10" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&amp;&amp;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>While this makes
<code class="sourceCode cpp"><span class="cf">match</span></code> more
consistent with
<code class="sourceCode cpp"><span class="op">==</span></code>, e.g. for
<code class="sourceCode cpp"><span class="op">+</span></code>, but there
remain deviations.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Input</strong>
</div></th>
<th><div style="text-align:center">
<strong>Parsed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb121"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb121-1"><a href="#cb121-1" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="op">==</span> <em>c</em></span>
<span id="cb121-2"><a href="#cb121-2" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">+</span> <em>b</em> <span class="cf">match</span> <em>c</em></span>
<span id="cb121-3"><a href="#cb121-3" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="op">==</span> <em>c</em></span>
<span id="cb121-4"><a href="#cb121-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <em>b</em> <span class="cf">match</span> <em>c</em></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb122"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb122-1"><a href="#cb122-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="op">==</span> <em>c</em></span>
<span id="cb122-2"><a href="#cb122-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">+</span> <em>b</em><span class="op">)</span> <span class="cf">match</span> <em>c</em></span>
<span id="cb122-3"><a href="#cb122-3" aria-hidden="true" tabindex="-1"></a><span class="op">(</span><em>a</em> <span class="op">&lt;</span> <em>b</em><span class="op">)</span> <span class="op">==</span> <em>c</em></span>
<span id="cb122-4"><a href="#cb122-4" aria-hidden="true" tabindex="-1"></a><em>a</em> <span class="op">&lt;</span> <span class="op">(</span><em>b</em> <span class="cf">match</span> <em>c</em><span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="8" id="future-extension-exploration"><span class="header-section-number">8</span> Future Extension Exploration<a href="#future-extension-exploration" class="self-link"></a></h1>
<p>The following lists patterns and features excluded from this paper,
but could still be useful future extensions.</p>
<h2 data-number="8.1" id="static-type-checking-with-constraint-pattern"><span class="header-section-number">8.1</span> Static Type Checking with
Constraint Pattern<a href="#static-type-checking-with-constraint-pattern" class="self-link"></a></h2>
<p>A constraint pattern could be used to perform static type checks.</p>
<blockquote>
<p><em>type-constraint</em></p>
</blockquote>
<p>The static condition of a constraint pattern would be that <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><em>subject</em><span class="op">)</span></code>
satisfies the <em>type-constraint</em>.</p>
<p>For example,</p>
<div class="sourceCode" id="cb123"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb123-1"><a href="#cb123-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb123-2"><a href="#cb123-2" aria-hidden="true" tabindex="-1"></a>  p <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb123-3"><a href="#cb123-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">[</span>std<span class="op">::</span>convertible_to<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>, <span class="dv">0</span><span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// statically check that first elem converts to int.</span></span>
<span id="cb123-4"><a href="#cb123-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb123-5"><a href="#cb123-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb123-6"><a href="#cb123-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If used with structured bindings, this becomes very similar to the
static type checking proposed in <span class="citation" data-cites="P0480R1">[<a href="https://wg21.link/p0480r1" role="doc-biblioref">P0480R1</a>]</span>.</p>
<div class="sourceCode" id="cb124"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb124-1"><a href="#cb124-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="op">[</span>std<span class="op">::</span>same_as<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> a, std<span class="op">::</span>same_as<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> b<span class="op">]</span> <span class="op">=</span> f<span class="op">()</span>;</span></code></pre></div>
<p>The syntax changes would be:</p>
<div>
<div class="sourceCode" id="cb125"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb125-1"><a href="#cb125-1" aria-hidden="true" tabindex="-1"></a>  <em>match-pattern</em></span>
<span id="cb125-2"><a href="#cb125-2" aria-hidden="true" tabindex="-1"></a>      // ...</span>
<span id="cb125-3"><a href="#cb125-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>type-constraint</em></span></span></code></pre></div>
</div>
<div>
<div class="sourceCode" id="cb126"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb126-1"><a href="#cb126-1" aria-hidden="true" tabindex="-1"></a>  <em>binding-pattern</em></span>
<span id="cb126-2"><a href="#cb126-2" aria-hidden="true" tabindex="-1"></a>      // ...</span>
<span id="cb126-3"><a href="#cb126-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>type-constraint</em> <em>identifier</em></span></span></code></pre></div>
</div>
<h2 data-number="8.2" id="testing-the-static-conditions-with-match-requires"><span class="header-section-number">8.2</span> Testing the Static Conditions
with <code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code><a href="#testing-the-static-conditions-with-match-requires" class="self-link"></a></h2>
<p>The sections <a href="#static-conditions">Static Conditions</a> and
<a href="#more-on-static-conditions">More on Static Conditions</a>
described what static conditions are. They also described why by
default,
<code class="sourceCode cpp"><span class="cf">match</span></code> and
<code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">constexpr</span></code>
should both always check the static conditions.</p>
<p><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code>
(or some other spelling) would offer a way to test the static conditions
instead.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> <span class="op">...</span> <span class="op">})</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb127"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb127-1"><a href="#cb127-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb127-2"><a href="#cb127-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="kw">requires</span> <span class="op">{</span> <span class="co">// not proposed</span></span>
<span id="cb127-3"><a href="#cb127-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb127-4"><a href="#cb127-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;hello&quot;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb127-5"><a href="#cb127-5" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb127-6"><a href="#cb127-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb127-7"><a href="#cb127-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb127-8"><a href="#cb127-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb127-9"><a href="#cb127-9" aria-hidden="true" tabindex="-1"></a>f<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="bu">s</span><span class="op">)</span>; <span class="co">// fine, skips 0</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb128"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb128-1"><a href="#cb128-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb128-2"><a href="#cb128-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> x <span class="op">==</span> <span class="dv">0</span>; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb128-3"><a href="#cb128-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb128-4"><a href="#cb128-4" aria-hidden="true" tabindex="-1"></a>      <span class="co">// ...</span></span>
<span id="cb128-5"><a href="#cb128-5" aria-hidden="true" tabindex="-1"></a>      <span class="cf">goto</span> done;</span>
<span id="cb128-6"><a href="#cb128-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb128-7"><a href="#cb128-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb128-8"><a href="#cb128-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> x <span class="op">==</span> <span class="st">&quot;hello&quot;</span>; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb128-9"><a href="#cb128-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> <span class="st">&quot;hello&quot;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb128-10"><a href="#cb128-10" aria-hidden="true" tabindex="-1"></a>      <span class="co">// ...</span></span>
<span id="cb128-11"><a href="#cb128-11" aria-hidden="true" tabindex="-1"></a>      <span class="cf">goto</span> done;</span>
<span id="cb128-12"><a href="#cb128-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb128-13"><a href="#cb128-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb128-14"><a href="#cb128-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb128-15"><a href="#cb128-15" aria-hidden="true" tabindex="-1"></a>  done<span class="op">:</span>;</span>
<span id="cb128-16"><a href="#cb128-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>Using the constraint pattern from <a href="#static-type-checking-with-constraint-pattern">Static Type
Checking with Constraint Pattern</a>, we can perform a sequence of
static type tests.</p>
<div class="sourceCode" id="cb129"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb129-1"><a href="#cb129-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb129-2"><a href="#cb129-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="kw">requires</span> <span class="op">{</span> <span class="co">// not proposed</span></span>
<span id="cb129-3"><a href="#cb129-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>same_as<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb129-4"><a href="#cb129-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>integral <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb129-5"><a href="#cb129-5" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>same_as<span class="op">&lt;</span>std<span class="op">::</span>string_view<span class="op">&gt;</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb129-6"><a href="#cb129-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>range <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb129-7"><a href="#cb129-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb129-8"><a href="#cb129-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Using the
<code class="sourceCode cpp"><span class="cf">let</span></code> pattern,
we can even bind names to each of these:</p>
<div class="sourceCode" id="cb130"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb130-1"><a href="#cb130-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb130-2"><a href="#cb130-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="kw">requires</span> <span class="op">{</span> <span class="co">// not proposed</span></span>
<span id="cb130-3"><a href="#cb130-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>same_as<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span> <span class="cf">let</span> b <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb130-4"><a href="#cb130-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>integral <span class="cf">let</span> i <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb130-5"><a href="#cb130-5" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>same_as<span class="op">&lt;</span>std<span class="op">::</span>string_view<span class="op">&gt;</span> <span class="cf">let</span> sv <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb130-6"><a href="#cb130-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>range <span class="cf">let</span> r <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb130-7"><a href="#cb130-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb130-8"><a href="#cb130-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Another example with structured bindings patterns:</p>
<div class="sourceCode" id="cb131"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb131-1"><a href="#cb131-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb131-2"><a href="#cb131-2" aria-hidden="true" tabindex="-1"></a>  x <span class="cf">match</span> <span class="kw">requires</span> <span class="op">{</span> <span class="co">// not proposed</span></span>
<span id="cb131-3"><a href="#cb131-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <span class="op">[</span>x<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb131-4"><a href="#cb131-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb131-5"><a href="#cb131-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <span class="op">[</span>x, y, z<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb131-6"><a href="#cb131-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">let</span> <span class="op">[...</span>xs<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb131-7"><a href="#cb131-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb131-8"><a href="#cb131-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Rather than the static condition (matching size requirement) of
structured bindings pattern being checked, they are <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span></code>
tested instead.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">constexpr</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb132"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb132-1"><a href="#cb132-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb132-2"><a href="#cb132-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb132-3"><a href="#cb132-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb133"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb133-1"><a href="#cb133-1" aria-hidden="true" tabindex="-1"></a><span class="co">// match constexpr</span></span>
<span id="cb133-2"><a href="#cb133-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb133-3"><a href="#cb133-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb133-4"><a href="#cb133-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span></code>
(not proposed)</strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="cf">match</span> <span class="kw">requires</span> <span class="kw">constexpr</span></code>
(not proposed)</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb134"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb134-1"><a href="#cb134-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> <em>condition</em> ; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb134-2"><a href="#cb134-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb134-3"><a href="#cb134-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb134-4"><a href="#cb134-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb134-5"><a href="#cb134-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb135"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb135-1"><a href="#cb135-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> <em>condition</em> ; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb135-2"><a href="#cb135-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb135-3"><a href="#cb135-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb135-4"><a href="#cb135-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb135-5"><a href="#cb135-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="8.3" id="pattern-combinators"><span class="header-section-number">8.3</span> Pattern Combinators<a href="#pattern-combinators" class="self-link"></a></h2>
<p>Pattern combinators provide a way to succinctly combine multiple
patterns.</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">or</span> <span class="op">(</span> <em>pattern-<code class="sourceCode default">0</code></em> , … , <em>pattern-<code class="sourceCode cpp">N</code></em> <span class="op">)</span></code><br />
<code class="sourceCode cpp"><span class="kw">and</span> <span class="op">(</span> <em>pattern-<code class="sourceCode default">0</code></em> , … , <em>pattern-<code class="sourceCode cpp">N</code></em> <span class="op">)</span></code></div>
</blockquote>
<p>Example:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>This Paper</strong>
</div></th>
<th><div style="text-align:center">
<strong>With
<code class="sourceCode cpp"><span class="kw">or</span></code>:</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb136"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb136-1"><a href="#cb136-1" aria-hidden="true" tabindex="-1"></a>direction <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb136-2"><a href="#cb136-2" aria-hidden="true" tabindex="-1"></a>  <span class="ch">&#39;N&#39;</span> <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb136-3"><a href="#cb136-3" aria-hidden="true" tabindex="-1"></a>  <span class="ch">&#39;E&#39;</span> <span class="op">=&gt;</span> g<span class="op">()</span>;</span>
<span id="cb136-4"><a href="#cb136-4" aria-hidden="true" tabindex="-1"></a>  <span class="ch">&#39;S&#39;</span> <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb136-5"><a href="#cb136-5" aria-hidden="true" tabindex="-1"></a>  <span class="ch">&#39;W&#39;</span> <span class="op">=&gt;</span> g<span class="op">()</span>;</span>
<span id="cb136-6"><a href="#cb136-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb137"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb137-1"><a href="#cb137-1" aria-hidden="true" tabindex="-1"></a>direction <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb137-2"><a href="#cb137-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">or</span><span class="op">(</span><span class="ch">&#39;N&#39;</span>, <span class="ch">&#39;S&#39;</span><span class="op">)</span> <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb137-3"><a href="#cb137-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">or</span><span class="op">(</span><span class="ch">&#39;E&#39;</span>, <span class="ch">&#39;W&#39;</span><span class="op">)</span> <span class="op">=&gt;</span> g<span class="op">()</span>;</span>
<span id="cb137-4"><a href="#cb137-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb138"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb138-1"><a href="#cb138-1" aria-hidden="true" tabindex="-1"></a>e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb138-2"><a href="#cb138-2" aria-hidden="true" tabindex="-1"></a>  A<span class="op">:</span> <span class="cf">let</span> a <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb138-3"><a href="#cb138-3" aria-hidden="true" tabindex="-1"></a>  B<span class="op">:</span> <span class="cf">let</span> b <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb138-4"><a href="#cb138-4" aria-hidden="true" tabindex="-1"></a>  C<span class="op">:</span> <span class="cf">let</span> c <span class="op">=&gt;</span> g<span class="op">()</span>;</span>
<span id="cb138-5"><a href="#cb138-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb139"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb139-1"><a href="#cb139-1" aria-hidden="true" tabindex="-1"></a>e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb139-2"><a href="#cb139-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">or</span><span class="op">(</span></span>
<span id="cb139-3"><a href="#cb139-3" aria-hidden="true" tabindex="-1"></a>    A<span class="op">:</span> <span class="cf">let</span> a,</span>
<span id="cb139-4"><a href="#cb139-4" aria-hidden="true" tabindex="-1"></a>    B<span class="op">:</span> <span class="cf">let</span> b</span>
<span id="cb139-5"><a href="#cb139-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">)</span> <span class="op">=&gt;</span> f<span class="op">()</span>;</span>
<span id="cb139-6"><a href="#cb139-6" aria-hidden="true" tabindex="-1"></a>  C<span class="op">:</span> <span class="cf">let</span> c <span class="op">=&gt;</span> g<span class="op">()</span>;</span>
<span id="cb139-7"><a href="#cb139-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h2 data-number="8.4" id="designator-support-for-structured-bindings"><span class="header-section-number">8.4</span> Designator Support for
Structured Bindings<a href="#designator-support-for-structured-bindings" class="self-link"></a></h2>
<p>This would extend structured bindings to allow designators
(i.e. <code class="sourceCode cpp"><span class="op">.</span>field_name</code>)
to match on that field.</p>
<div>
<div class="sourceCode" id="cb140"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb140-1"><a href="#cb140-1" aria-hidden="true" tabindex="-1"></a>  <em>match-pattern</em></span>
<span id="cb140-2"><a href="#cb140-2" aria-hidden="true" tabindex="-1"></a>      // ...</span>
<span id="cb140-3"><a href="#cb140-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     [ <em>designator-<code class="sourceCode default">0</code></em> : <em>pattern-<code class="sourceCode default">0</code></em> , … , <em>designator-<code class="sourceCode cpp">N</code></em> : <em>pattern-<code class="sourceCode cpp">N</code></em> ]</span></span></code></pre></div>
</div>
<div>
<div class="sourceCode" id="cb141"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb141-1"><a href="#cb141-1" aria-hidden="true" tabindex="-1"></a>  <em>binding-pattern</em></span>
<span id="cb141-2"><a href="#cb141-2" aria-hidden="true" tabindex="-1"></a>      // ...</span>
<span id="cb141-3"><a href="#cb141-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     [ <em>designator-<code class="sourceCode default">0</code></em> : <em>binding-pattern-<code class="sourceCode default">0</code></em> , … <em>designator-<code class="sourceCode cpp">N</code></em> : <em>binding-pattern-N</em> ]</span></span></code></pre></div>
</div>
<p>Example:</p>
<div class="sourceCode" id="cb142"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb142-1"><a href="#cb142-1" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> scope <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb142-2"><a href="#cb142-2" aria-hidden="true" tabindex="-1"></a>    GlobalScope<span class="op">:</span> _ <span class="op">=&gt;</span> Cxx<span class="op">::</span>Scope<span class="op">::</span>global_<span class="op">()</span>;</span>
<span id="cb142-3"><a href="#cb142-3" aria-hidden="true" tabindex="-1"></a>    NamespaceScope<span class="op">:</span> <span class="op">[.</span>fact<span class="op">:</span> <span class="cf">let</span> f<span class="op">]</span> <span class="op">=&gt;</span> Cxx<span class="op">::</span>Scope<span class="op">::</span>namespace_<span class="op">(</span>f<span class="op">)</span>;</span>
<span id="cb142-4"><a href="#cb142-4" aria-hidden="true" tabindex="-1"></a>    ClassScope<span class="op">:</span> <span class="op">[.</span>fact<span class="op">:</span> <span class="cf">let</span> f<span class="op">]</span> <span class="op">=&gt;</span> Cxx<span class="op">::</span>Scope<span class="op">::</span>recordWithAccess<span class="op">(</span>f, access<span class="op">(</span>acs<span class="op">))</span>;</span>
<span id="cb142-5"><a href="#cb142-5" aria-hidden="true" tabindex="-1"></a>    LocalScope<span class="op">:</span> <span class="op">[.</span>fact<span class="op">:</span> <span class="cf">let</span> f<span class="op">]</span> <span class="op">=&gt;</span> Cxx<span class="op">::</span>Scope<span class="op">::</span>local<span class="op">(</span>f<span class="op">)</span>;</span>
<span id="cb142-6"><a href="#cb142-6" aria-hidden="true" tabindex="-1"></a><span class="co">//              ^^^^^^^^^^^^^^</span></span>
<span id="cb142-7"><a href="#cb142-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span></code></pre></div>
<h2 data-number="8.5" id="value-based-discriminators"><span class="header-section-number">8.5</span> Value-based discriminators<a href="#value-based-discriminators" class="self-link"></a></h2>
<p>This would extend the alternative pattern to allow value-based
discriminators.</p>
<div>
<div class="sourceCode" id="cb143"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb143-1"><a href="#cb143-1" aria-hidden="true" tabindex="-1"></a>  <em>discriminator</em>:</span>
<span id="cb143-2"><a href="#cb143-2" aria-hidden="true" tabindex="-1"></a>      <em>type-id</em></span>
<span id="cb143-3"><a href="#cb143-3" aria-hidden="true" tabindex="-1"></a>      <em>type-constraint</em></span>
<span id="cb143-4"><a href="#cb143-4" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>constant-expression</em></span></span></code></pre></div>
</div>
<p>From <a href="#discussion-on-variant-like-types">Discussion on
Variant-like Types</a>, the example of
<code class="sourceCode cpp"><span class="kw">enum</span></code> values
<code class="sourceCode cpp">value</code> and
<code class="sourceCode cpp">error</code>:</p>
<div class="sourceCode" id="cb144"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb144-1"><a href="#cb144-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> expected_state <span class="op">{</span> value, error <span class="op">}</span>;</span>
<span id="cb144-2"><a href="#cb144-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb144-3"><a href="#cb144-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>expected<span class="op">&lt;</span><span class="dt">int</span>, parse_error<span class="op">&gt;</span> parse<span class="op">(</span>std<span class="op">::</span>string_view sv<span class="op">)</span>;</span>
<span id="cb144-4"><a href="#cb144-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb144-5"><a href="#cb144-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb144-6"><a href="#cb144-6" aria-hidden="true" tabindex="-1"></a>  parse<span class="op">(</span>some_input<span class="op">)</span> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb144-7"><a href="#cb144-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <span class="kw">enum</span> std<span class="op">::</span>expected_state;</span>
<span id="cb144-8"><a href="#cb144-8" aria-hidden="true" tabindex="-1"></a>    value<span class="op">:</span> <span class="cf">let</span> v <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb144-9"><a href="#cb144-9" aria-hidden="true" tabindex="-1"></a>    error<span class="op">:</span> <span class="cf">let</span> err <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb144-10"><a href="#cb144-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb144-11"><a href="#cb144-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">variant<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">expected<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb145"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb145-1"><a href="#cb145-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb145-2"><a href="#cb145-2" aria-hidden="true" tabindex="-1"></a>  v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb145-3"><a href="#cb145-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">:</span> <span class="cf">let</span> first <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb145-4"><a href="#cb145-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span><span class="op">:</span> <span class="cf">let</span> second <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb145-5"><a href="#cb145-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb145-6"><a href="#cb145-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb146"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb146-1"><a href="#cb146-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>expected<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb146-2"><a href="#cb146-2" aria-hidden="true" tabindex="-1"></a>  e <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb146-3"><a href="#cb146-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span><span class="op">:</span> <span class="cf">let</span> value <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb146-4"><a href="#cb146-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span><span class="op">:</span> <span class="cf">let</span> error <span class="op">=&gt;</span> <span class="co">// ...</span></span>
<span id="cb146-5"><a href="#cb146-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb146-6"><a href="#cb146-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="9" id="implementation-experience"><span class="header-section-number">9</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>A Clang-based implementation is available at <a href="https://github.com/mpark/llvm-project/tree/p2688-pattern-matching" class="uri">https://github.com/mpark/llvm-project/tree/p2688-pattern-matching</a>
(with option <code class="sourceCode cpp"><span class="op">-</span>fpattern<span class="op">-</span>matching</code>)
and available on <a href="https://godbolt.org">Compiler Explorer</a>
under <code class="sourceCode default">x86-64 clang (pattern matching - P2688)</code>.</p>
<p>The following is a rough overview of the current status:</p>
<ul>
<li><strong>Lexing</strong>
<ul>
<li><code class="sourceCode cpp"><span class="op">=&gt;</span></code> is
added as a new token</li>
<li><code class="sourceCode cpp"><span class="cf">match</span></code>,
<code class="sourceCode cpp"><span class="cf">let</span></code>, and
<code class="sourceCode cpp">_</code> added as context-sensitive
keywords</li>
</ul></li>
<li><strong>Parsing</strong>
<ul>
<li>Structure
<ul>
<li>Match test: <code class="sourceCode cpp">pm<span class="op">-</span>expression <span class="cf">match</span> pattern</code></li>
<li>Match selection: <code class="sourceCode cpp">pm<span class="op">-</span>expression <span class="cf">match</span> <span class="op">{</span> pattern <span class="op">=&gt;</span> expr; <span class="op">...</span> <span class="op">}</span></code></li>
<li><code class="sourceCode cpp"><span class="kw">constexpr</span></code>:
<code class="sourceCode cpp">expr <span class="cf">match</span> <span class="kw">constexpr</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code></li>
<li>Trailing return type: <code class="sourceCode cpp">expr <span class="cf">match</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code></li>
<li>Match cases: <code class="sourceCode cpp">pattern <span class="op">=&gt;</span> expr;</code>,
<code class="sourceCode cpp">pattern <span class="op">=&gt;</span> jump<span class="op">-</span>stmt;</code>,
<code class="sourceCode cpp">pattern <span class="op">=&gt;</span> <span class="op">{</span>a, b<span class="op">}</span>;</code></li>
<li>Match case guards: <code class="sourceCode cpp">pattern <span class="cf">if</span> condition <span class="op">=&gt;</span> expr;</code></li>
<li>Match test guards: <code class="sourceCode cpp">pair <span class="cf">match</span> <span class="cf">let</span> <span class="op">[</span>x, y<span class="op">]</span> <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> y<span class="op">)</span></code></li>
<li><em>Missing</em>: Matching against <em>braced-init-list</em> <code class="sourceCode cpp"><span class="op">{</span> a, b <span class="op">}</span> <span class="cf">match</span> pattern</code></li>
</ul></li>
<li>Patterns
<ul>
<li>All of the proposed patterns: Wildcard, Constant, Parenthesized,
Optional, Alternative, and Structured Bindings.</li>
<li><em>Missing</em>: “match-and-bind” (e.g. <code class="sourceCode cpp"><span class="op">[</span><span class="dv">0</span>, <span class="dv">1</span><span class="op">]</span> <span class="cf">let</span> whole</code>)</li>
<li><em>Missing</em>: For alternative pattern, <code class="sourceCode cpp"><em>type-id</em><span class="op">:</span> pattern</code>
is implemented but <code class="sourceCode cpp"><em>type-constraint</em><span class="op">:</span> pattern</code>
is not yet.</li>
</ul></li>
</ul></li>
<li><strong>Semantic Anaylsis</strong>
<ul>
<li>Type deduction: <code class="sourceCode cpp"><span class="kw">auto</span> f<span class="op">(</span><span class="dt">char</span> c<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> c <span class="cf">match</span> <span class="op">{</span> <span class="ch">&#39;a&#39;</span> <span class="op">=&gt;</span> <span class="dv">0</span>; <span class="ch">&#39;b&#39;</span> <span class="op">=&gt;</span> <span class="dv">1</span>; <span class="op">}</span>; <span class="op">}</span></code></li>
<li>AST Construction</li>
<li>Type checking</li>
<li><em>Missing</em>: Handling of templates</li>
<li><em>Missing</em>: Inject bindings into the enclosing control
statement. e.g. <code class="sourceCode cpp"><span class="cf">if</span> <span class="op">(</span>expr <span class="cf">match</span> <span class="op">[</span><span class="dv">0</span>, <span class="cf">let</span> x<span class="op">])</span> <span class="op">{</span> <span class="co">/* x available here */</span> <span class="op">}</span></code></li>
<li><em>Missing</em>: More work needs to be done for jump-statement
handlers
(<code class="sourceCode cpp"><span class="cf">break</span></code>,
<code class="sourceCode cpp"><span class="cf">continue</span></code>,
etc), scope management, object lifetimes, etc. Similar concerns as
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions: <span class="citation" data-cites="P2806R2">[<a href="https://wg21.link/p2806r2" role="doc-biblioref">P2806R2</a>]</span>.</li>
</ul></li>
<li><strong>Code Gen</strong>
<ul>
<li>Most of constant evaluation has been implemented.
<ul>
<li><em>Missing</em>: Handling jump-statements, injecting a stack where
necessary (template arguments, default arguments, etc)</li>
<li><em>Missing</em>: For alternative pattern, <code class="sourceCode cpp"><em>type-id</em><span class="op">:</span> pattern</code>,
currently it only implements polymorphic types using
<code class="sourceCode cpp"><span class="kw">dynamic_cast</span></code>
under the hood.</li>
</ul></li>
<li><em>Missing</em>: Emitting actual code gen</li>
</ul></li>
</ul>
<h2 data-number="9.1" id="parsing-the-match-operator"><span class="header-section-number">9.1</span> Parsing the
<code class="sourceCode cpp"><span class="cf">match</span></code>
operator<a href="#parsing-the-match-operator" class="self-link"></a></h2>
<p>Broadly speaking, in Clang, expressions are first parsed as a
<em>cast-expression</em> with
<code class="sourceCode cpp">ParseCastExpression</code>, then
<code class="sourceCode cpp">ParseRHSOfBinaryExpression</code> looks
ahead to see if there is an infix operator. If it finds an operator, it
folds a sequence of RHS into LHS based on the associativity and
precedence of the found operator.</p>
<p>The implementation first adds a
<code class="sourceCode cpp">prec<span class="op">::</span>Match</code>
into the operator precedence table, then there are changes made to
<code class="sourceCode cpp">ParseRHSOfBinaryExpression</code> to detect
the upcoming
<code class="sourceCode cpp"><span class="cf">match</span></code> token.
After we encounter a
<code class="sourceCode cpp"><span class="cf">match</span></code> token,
if we have a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>,
<code class="sourceCode cpp"><span class="op">-&gt;</span></code> or a
<code class="sourceCode cpp"><span class="op">{</span></code> token, we
have a match select expression <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code>,
otherwise we assume match test expression <code class="sourceCode cpp"><em>expr</em> <span class="cf">match</span> <em>pattern</em></code>.</p>
<p>In the case of a match test expression, care is taken such that if
<code class="sourceCode cpp"><em>pattern</em></code> turns out to be an
expression, we correctly parse it as <em>pm-expression</em>. This mostly
just falls out of correct placement of
<code class="sourceCode cpp">prec<span class="op">::</span>Match</code>
in the operator precedence table.</p>
<h2 data-number="9.2" id="parsing-the-parenthesized-pattern"><span class="header-section-number">9.2</span> Parsing the Parenthesized
Pattern<a href="#parsing-the-parenthesized-pattern" class="self-link"></a></h2>
<p>For other patterns, the proposed solution is such that a leading
pattern token takes us into pattern parsing. For example,
<code class="sourceCode cpp">_</code> is a the wildcard pattern, and it
is so even if there is a variable named
<code class="sourceCode cpp">_</code> in scope. On the other hand,
<code class="sourceCode cpp"><span class="op">*</span>_</code> is an
expression that dereferences a variable
<code class="sourceCode cpp">_</code>, because
<code class="sourceCode cpp"><span class="op">*</span></code> takes us
into expression parsing. Finally, <code class="sourceCode cpp">_ <span class="op">+</span> <span class="dv">1</span></code>
produces an error along the lines of <code class="sourceCode cpp"><span class="st">&quot;expected &#39;=&gt;&#39; after wildcard pattern&quot;</span></code>.
The leading <code class="sourceCode cpp">_</code> takes us into pattern
parsing, even though <code class="sourceCode cpp">_ <span class="op">+</span> <span class="dv">1</span></code>
could be a valid expression.</p>
<div class="sourceCode" id="cb147"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb147-1"><a href="#cb147-1" aria-hidden="true" tabindex="-1"></a>expr <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb147-2"><a href="#cb147-2" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// wildcard pattern</span></span>
<span id="cb147-3"><a href="#cb147-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>_ <span class="op">=&gt;</span> <span class="co">// dereference</span></span>
<span id="cb147-4"><a href="#cb147-4" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">+</span> <span class="dv">1</span> <span class="op">=&gt;</span> <span class="co">// error: expected &#39;=&gt;&#39; after wildcard pattern</span></span>
<span id="cb147-5"><a href="#cb147-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> <span class="op">=&gt;</span> <span class="co">// error: expected identifier or &#39;[&#39; after &#39;let&#39;</span></span>
<span id="cb147-6"><a href="#cb147-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> x <span class="op">=&gt;</span> <span class="co">// let pattern</span></span>
<span id="cb147-7"><a href="#cb147-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">let</span> <span class="op">[</span>x<span class="op">]</span> <span class="op">=&gt;</span> <span class="co">// SB pattern</span></span>
<span id="cb147-8"><a href="#cb147-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now, without parenthesized pattern, a
<code class="sourceCode cpp"><span class="op">(</span></code> would take
us into expression parsing. It was considered to drop the parenthesized
pattern for this simplicity. However, it’s difficult to ignore that
there is virtually no language that provide pattern matching without
parenthesized patterns. Having them now I believe will also be better
down the road in evolving the set of available patterns.</p>
<p>It turns out, the difficulty of parsing parenthesized pattern turns
out is not much harder than the difficulty of parsing parenthesized
expressions. We already have parenthesized expressions of the form <code class="sourceCode cpp"><span class="op">(</span> <em>expression</em> <span class="op">)</span></code>,
but this is a bit of a simplification as we also have cast expressions
such as <code class="sourceCode cpp"><span class="op">(</span><span class="dt">int</span><span class="op">)</span>x</code>.
We already can’t just recurse into a
<code class="sourceCode cpp">ParseExpression</code> upon seeing a
<code class="sourceCode cpp"><span class="op">(</span></code>.</p>
<p>Even worse, the expression parsing today requires looking
<em>past</em> the
<code class="sourceCode cpp"><span class="op">)</span></code> to
determine how to parse the expression. Given <code class="sourceCode cpp"><span class="op">(</span>T<span class="op">())</span></code>,
we don’t yet know whether the
<code class="sourceCode cpp">T<span class="op">()</span></code> is a
function type or a constructor call. In fact it changes based on what
comes next.</p>
<div class="sourceCode" id="cb148"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb148-1"><a href="#cb148-1" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>T<span class="op">())</span> <span class="op">*</span> x  <span class="co">// T() is a function type.    Cast of *x to T()</span></span>
<span id="cb148-2"><a href="#cb148-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>T<span class="op">())</span> <span class="op">/</span> x  <span class="co">// T() is a constructor call. Same as T() / x</span></span></code></pre></div>
<p>This involves blindly storing everything until the
<code class="sourceCode cpp"><span class="op">)</span></code>,
tentatively parsing what follows as a cast expression, then deciding
what the <code class="sourceCode cpp">T<span class="op">()</span></code>
means based on whether the cast expression parsing attempt succeeded or
not. <code class="sourceCode cpp"><span class="op">*</span> x</code> is
a cast expression, so
<code class="sourceCode cpp">T<span class="op">()</span></code> is a
type, <code class="sourceCode cpp"><span class="op">/</span> x</code> is
not a cast expression, so
<code class="sourceCode cpp">T<span class="op">()</span></code> is an
expression.</p>
<p>Equipped with that monstrosity, Clang basically tries to parse an
expression that starts with
<code class="sourceCode cpp"><span class="op">(</span></code> such as
cast expression and fold expression, along with extensions such as
statement expressions and compound literals. If that fails, it proceeds
to parse <code class="sourceCode cpp"><span class="op">(</span> <em>expression</em> <span class="op">)</span></code>.</p>
<p>For parenthesized patterns, the steps are similar:</p>
<ol type="1">
<li>If the token after the
<code class="sourceCode cpp"><span class="op">(</span></code> is a
<code class="sourceCode cpp">_</code>,
<code class="sourceCode cpp"><span class="op">?</span></code>,
<code class="sourceCode cpp"><span class="cf">let</span></code>, or
<code class="sourceCode cpp"><span class="op">[</span></code>, parse it
a a pattern.</li>
<li>Otherwise, try parsing it as expression that starts with
<code class="sourceCode cpp"><span class="op">(</span></code>.</li>
<li>Otherwise, parse it as <code class="sourceCode cpp"><span class="op">(</span> <em>pattern</em> <span class="op">)</span></code>.</li>
<li>If the resulting pattern inside of the parenthesized pattern is an
expression, convert it into an parenthesized expression and proceed
parsing. (i.e. postfix, then RHS of binary operator) This handles
situations like <code class="sourceCode cpp"><span class="op">(</span>x<span class="op">)</span> <span class="op">+</span> y <span class="op">=&gt;</span> <span class="co">// ...</span></code>
so that we can proceed to parse the
<code class="sourceCode cpp"><span class="op">+</span> y</code> with a
parenthesized expression of <code class="sourceCode cpp"><span class="op">(</span>x<span class="op">)</span></code>.</li>
</ol>
<h1 data-number="10" id="acknowledgements"><span class="header-section-number">10</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Thank you to all of the following folks</p>
<ul>
<li>Jens Maurer, for the time, effort, and guidance for wording
work.</li>
<li>Bruno Cardoso Lopes, specifically for his contributions to the
implementation work.</li>
<li>Bjarne Stroustrup for authoring <span class="citation" data-cites="P3332R0">[<a href="https://wg21.link/p3332r0" role="doc-biblioref">P3332R0</a>]</span> and email discussions regarding
it.</li>
<li>Zach Laine, Barry Revzin, and Bruno Cardoso Lopes for the
encouragement and long discussions over much of what is proposed and
discussed in this paper.</li>
<li>David Sankel, Sergei Murzin, Bruno Cardoso Lopes, Dan Sarginson, and
Bjarne Stroustrup for our prior work on <span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span>.</li>
<li>Herb Sutter for valuable feedback and the work done in <span class="citation" data-cites="P2392R2">[<a href="https://wg21.link/p2392r2" role="doc-biblioref">P2392R2</a>]</span>.</li>
<li>David Sankel, Sergei Murzin, Alex Chow, Yedidya Feldblum, and Jason
Lucas for recent discussions.</li>
<li>Everyone else who have had discussions about pattern matching and
provided feedback in prior meetings and telecons!</li>
</ul>
<h1 data-number="11" id="bibliography"><span class="header-section-number">11</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-P0144R2" class="csl-entry" role="doc-biblioentry">
[P0144R2] Herb Sutter. 2016-03-16. Structured Bindings. <a href="https://wg21.link/p0144r2"><div class="csl-block">https://wg21.link/p0144r2</div></a>
</div>
<div id="ref-P0480R1" class="csl-entry" role="doc-biblioentry">
[P0480R1] Ville Voutilainen. 2018-10-08. Structured bindings with
explicit types. <a href="https://wg21.link/p0480r1"><div class="csl-block">https://wg21.link/p0480r1</div></a>
</div>
<div id="ref-P1110R0" class="csl-entry" role="doc-biblioentry">
[P1110R0] Jeffrey Yasskin, JF Bastien. 2018-06-07. A placeholder with no
name. <a href="https://wg21.link/p1110r0"><div class="csl-block">https://wg21.link/p1110r0</div></a>
</div>
<div id="ref-P1371R3" class="csl-entry" role="doc-biblioentry">
[P1371R3] Michael Park, Bruno Cardoso Lopes, Sergei Murzin, David
Sankel, Dan Sarginson, Bjarne Stroustrup. 2020-09-15. Pattern Matching.
<a href="https://wg21.link/p1371r3"><div class="csl-block">https://wg21.link/p1371r3</div></a>
</div>
<div id="ref-P1469R0" class="csl-entry" role="doc-biblioentry">
[P1469R0] Sergei Murzin, Michael Park, David Sankel, Dan Sarginson.
2019-01-21. Disallow _ Usage in C++20 for Pattern Matching in C++23. <a href="https://wg21.link/p1469r0"><div class="csl-block">https://wg21.link/p1469r0</div></a>
</div>
<div id="ref-P2162R2" class="csl-entry" role="doc-biblioentry">
[P2162R2] Barry Revzin. 2021-02-18. Inheriting from std::variant
(resolving LWG3052). <a href="https://wg21.link/p2162r2"><div class="csl-block">https://wg21.link/p2162r2</div></a>
</div>
<div id="ref-P2169R4" class="csl-entry" role="doc-biblioentry">
[P2169R4] Corentin Jabot, Michael Park. 2023-06-16. A Nice Placeholder
With No Name. <a href="https://wg21.link/p2169r4"><div class="csl-block">https://wg21.link/p2169r4</div></a>
</div>
<div id="ref-P2392R2" class="csl-entry" role="doc-biblioentry">
[P2392R2] Herb Sutter. 2022-09-25. Pattern matching using is and as. <a href="https://wg21.link/p2392r2"><div class="csl-block">https://wg21.link/p2392r2</div></a>
</div>
<div id="ref-P2411R0" class="csl-entry" role="doc-biblioentry">
[P2411R0] Bjarne Stroustrup. 2021-07-22. Thoughts on pattern matching.
<a href="https://wg21.link/p2411r0"><div class="csl-block">https://wg21.link/p2411r0</div></a>
</div>
<div id="ref-P2688R0" class="csl-entry" role="doc-biblioentry">
[P2688R0] Michael Park. 2022-10-16. Pattern Matching Discussion for Kona
2022. <a href="https://wg21.link/p2688r0"><div class="csl-block">https://wg21.link/p2688r0</div></a>
</div>
<div id="ref-P2806R2" class="csl-entry" role="doc-biblioentry">
[P2806R2] Barry Revzin, Bruno Cardoso Lopez, Zach Laine, Michael Park.
2023-11-16. do expressions. <a href="https://wg21.link/p2806r2"><div class="csl-block">https://wg21.link/p2806r2</div></a>
</div>
<div id="ref-P2927R0" class="csl-entry" role="doc-biblioentry">
[P2927R0] Gor Nishanov. 2023-10-15. Observing exceptions stored in
exception_ptr. <a href="https://wg21.link/p2927r0"><div class="csl-block">https://wg21.link/p2927r0</div></a>
</div>
<div id="ref-P3332R0" class="csl-entry" role="doc-biblioentry">
[P3332R0] Bjarne Stroustrup. 2024-06-18. A simpler notation for PM. <a href="https://wg21.link/p3332r0"><div class="csl-block">https://wg21.link/p3332r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
