<!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-12-17" />
  <title>Pattern Matching: Customization Point for Open Sum
Types</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:
Customization Point for Open Sum Types</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3521R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-12-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>
      Library Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Michael Park<br>&lt;<a href="mailto:mcypark@gmail.com" class="email">mcypark@gmail.com</a>&gt;<br>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#motivation-and-scope" id="toc-motivation-and-scope"><span class="toc-section-number">2</span> Motivation and
Scope<span></span></a>
<ul>
<li><a href="#sum-types" id="toc-sum-types"><span class="toc-section-number">2.1</span> Sum Types<span></span></a></li>
<li><a href="#implications-for-pattern-matching" id="toc-implications-for-pattern-matching"><span class="toc-section-number">2.2</span> Implications for Pattern
Matching<span></span></a></li>
</ul></li>
<li><a href="#design-overview" id="toc-design-overview"><span class="toc-section-number">3</span> Design Overview<span></span></a>
<ul>
<li><a href="#how-does-pattern-matching-actually-use-this" id="toc-how-does-pattern-matching-actually-use-this"><span class="toc-section-number">3.1</span> How does pattern matching actually
use this?<span></span></a></li>
</ul></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">4</span> Proposed
Wording<span></span></a></li>
<li><a href="#design-alternatives" id="toc-design-alternatives"><span class="toc-section-number">5</span> Design Alternatives<span></span></a>
<ul>
<li><a href="#overload-any_cast" id="toc-overload-any_cast"><span class="toc-section-number">5.1</span> Overload
<code class="sourceCode cpp">any_cast</code><span></span></a></li>
<li><a href="#parameters-as-pointers" id="toc-parameters-as-pointers"><span class="toc-section-number">5.2</span> Parameters as
Pointers<span></span></a></li>
<li><a href="#use-a-stdhash-like-approach" id="toc-use-a-stdhash-like-approach"><span class="toc-section-number">5.3</span> Use a
<code class="sourceCode cpp">std<span class="op">::</span>hash</code>-like
Approach<span></span></a></li>
<li><a href="#create-a-try_cast-cpo" id="toc-create-a-try_cast-cpo"><span class="toc-section-number">5.4</span> Create a
<code class="sourceCode cpp">try_cast</code> CPO<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This is an accompanying paper for <span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span> with respect to customization
points in the library. At the Wrocław meeting in November 2024, the
following poll was taken in EWG:</p>
<blockquote>
<p>Poll: <span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span> — Pattern Matching:
<code class="sourceCode cpp"><span class="cf">match</span></code>
Expression, we encourage more work on the language-only paper towards
C++26 in the next meeting (note: voting against this poll does not
exclude getting pattern matching in C++29)</p>
</blockquote>
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>F</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>N</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>A</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">17</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">6</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">9</td>
</tr>
</tbody>
</table>
<p>The “language-only paper” still relies on library facilities, the
same way that structured bindings is a “language-only” feature that
relies on library facilities as a hook for customization.</p>
<p>A <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2688r3.html#reflection-based-tuple-like-and-variant-like-customization-points">Reflection-based
Tuple-like and Variant-like Customization Points</a> has been explored,
but the design decision for <span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span> targeting C++26 is to use the
existing facilities.</p>
<p>This makes it such that even a “language-only paper” is plenty useful
without any library changes. However, there is one customization point
that is currently missing: the ability for user-defined types to opt-in
as an open sum type.</p>
<p>This paper proposes to add that customization point.</p>
<h1 data-number="2" id="motivation-and-scope"><span class="header-section-number">2</span> Motivation and Scope<a href="#motivation-and-scope" class="self-link"></a></h1>
<h2 data-number="2.1" id="sum-types"><span class="header-section-number">2.1</span> Sum Types<a href="#sum-types" class="self-link"></a></h2>
<p>First, definitions. A “sum type”
<code class="sourceCode cpp">SUM</code> is a type that represents one of
several types in the set <code class="sourceCode cpp">S</code> =
{<code class="sourceCode cpp">T0</code>,
<code class="sourceCode cpp">T1</code>, …
<code class="sourceCode cpp">TN</code>}. Which
<code class="sourceCode cpp">Ti</code>
<code class="sourceCode cpp">SUM</code> represents is a runtime
property.</p>
<p>The set of types <code class="sourceCode cpp">S</code> is part of the
definition of <code class="sourceCode cpp">SUM</code>, but the exact
elements of <code class="sourceCode cpp">S</code> might not be known at
the time <code class="sourceCode cpp">SUM</code> is defined. For
instance: for <code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">&gt;</span></code>,
<code class="sourceCode cpp">S</code> = <code class="sourceCode cpp"><span class="op">{</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">}</span></code>;
however, for
<code class="sourceCode cpp">std<span class="op">::</span>any</code>,
<code class="sourceCode cpp">S</code> = <code class="sourceCode cpp"><span class="op">{</span>x <span class="op">|</span> x <span class="cf">is</span> a copyable C<span class="op">++</span> type<span class="op">}</span></code>.
Though we know that
<code class="sourceCode cpp">std<span class="op">::</span>any</code> can
hold any copyable type, we don’t know all the copyable types that might
exist in a program.</p>
<p>If all the elements <code class="sourceCode cpp">S</code> are known
at the time that <code class="sourceCode cpp">SUM</code> is defined, we
say that <code class="sourceCode cpp">SUM</code> is a “closed” sum type
(e.g. <code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">&gt;</span></code>).
If the members of the set are <em>not</em> known at the time
<code class="sourceCode cpp">SUM</code> is defined, we say that
<code class="sourceCode cpp">SUM</code> is an “open” sum type
(e.g. <code class="sourceCode cpp">std<span class="op">::</span>any</code>).</p>
<h2 data-number="2.2" id="implications-for-pattern-matching"><span class="header-section-number">2.2</span> Implications for Pattern
Matching<a href="#implications-for-pattern-matching" class="self-link"></a></h2>
<p><span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span> proposes an alternative pattern
which has syntax like the following:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>variant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">&gt;&amp;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> v <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">:</span> <span class="cf">let</span> i <span class="op">=&gt;</span> i;</span>
<span id="cb1-4"><a href="#cb1-4" 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 class="dt">int</span><span class="op">(</span>d<span class="op">)</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</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>This uses the “variant-like” protocol which uses the existing set of
variant helpers: <code class="sourceCode cpp">variant_size</code>,
<code class="sourceCode cpp">variant_alternative</code>,
<code class="sourceCode cpp">get</code>, and
<code class="sourceCode cpp">index</code>.</p>
<p>However, for open sum types, there is no such existing facility.
<code class="sourceCode cpp">std<span class="op">::</span>any</code> and
<code class="sourceCode cpp">std<span class="op">::</span>exception_ptr</code>
are examples of such types.</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>P2688 with This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<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="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span><span class="kw">auto</span><span class="op">*</span> i <span class="op">=</span> std<span class="op">::</span>any_cast<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(&amp;</span>a<span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">*</span>i;</span>
<span id="cb2-4"><a href="#cb2-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><span class="kw">auto</span><span class="op">*</span> d <span class="op">=</span> std<span class="op">::</span>any_cast<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;(&amp;</span>a<span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">*</span>d;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">-</span><span class="dv">1</span>;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<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="dt">int</span> f<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="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> a <span class="cf">match</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-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> i;</span>
<span id="cb3-4"><a href="#cb3-4" 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> d;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="op">-</span><span class="dv">1</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p><span class="citation" data-cites="P2927R2">[<a href="https://wg21.link/p2927r2" role="doc-biblioref">P2927R2</a>]</span> mentions a desired pattern
matching use case for <code class="sourceCode cpp">std<span class="op">::</span>exception_ptr</code>.
The example is written with <span class="citation" data-cites="P1371R3">[<a href="https://wg21.link/p1371r3" role="doc-biblioref">P1371R3</a>]</span>, but the following is what it
would look like with <span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span>:</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>P2688 with This Paper</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<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="dt">void</span> f<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>exception_ptr<span class="op">&amp;</span> eptr<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="cf">if</span> <span class="op">(</span><span class="kw">auto</span><span class="op">*</span> e <span class="op">=</span> std<span class="op">::</span>exception_ptr_cast<span class="op">&lt;</span>logic_error<span class="op">&gt;(</span>eptr<span class="op">))</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// use `*e`</span></span>
<span id="cb4-4"><a href="#cb4-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><span class="kw">auto</span><span class="op">*</span> e <span class="op">=</span> std<span class="op">::</span>exception_ptr_cast<span class="op">&lt;</span>exception<span class="op">&gt;(</span>eptr<span class="op">))</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// use `*e`</span></span>
<span id="cb4-6"><a href="#cb4-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>ep <span class="op">==</span> <span class="kw">nullptr</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;no exception&quot;</span><span class="op">)</span>;</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;some other exception&quot;</span><span class="op">)</span>;</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<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="dt">void</span> f<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>exception_ptr<span class="op">&amp;</span> eptr<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  eptr <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    logic_error<span class="op">:</span> <span class="cf">let</span> e <span class="op">=&gt;</span> <span class="co">// use `e`</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    exception<span class="op">:</span> <span class="cf">let</span> e <span class="op">=&gt;</span> <span class="co">// use `e`</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">nullptr</span> <span class="op">=&gt;</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;no exception&quot;</span><span class="op">)</span>;</span>
<span id="cb5-6"><a href="#cb5-6" 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;some other exception&quot;</span><span class="op">)</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>This paper proposes <code class="sourceCode cpp">try_cast</code> as
the customization point that pattern matching invokes to test and
extract the state of open sum types.</p>
<h1 data-number="3" id="design-overview"><span class="header-section-number">3</span> Design Overview<a href="#design-overview" class="self-link"></a></h1>
<p>The <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2688r3.html#alternative-pattern">Alternative
Pattern</a> as proposed in <span class="citation" data-cites="P2688R3">[<a href="https://wg21.link/p2688r3" role="doc-biblioref">P2688R3</a>]</span> considers the following 3 cases
in order:</p>
<ol type="1">
<li>Variant-like</li>
<li>Casts</li>
<li>Polymorphic types</li>
</ol>
<p>This is modeled similarly to structured bindings protocol, which
considers the following 3 cases:</p>
<ol type="1">
<li>Array</li>
<li>Tuple-like</li>
<li>Aggregate types</li>
</ol>
<p>The cast protocol is the only one that needs library support for
<code class="sourceCode cpp">std</code> entities to benefit from it.</p>
<p>The proposal is to add <code class="sourceCode cpp">try_cast</code>
overloads that handle casts of
<code class="sourceCode cpp">std<span class="op">::</span>any</code>
using <code class="sourceCode cpp">std<span class="op">::</span>any_cast</code>, and
casts of <code class="sourceCode cpp">std<span class="op">::</span>exception_ptr</code>
using <code class="sourceCode cpp">std<span class="op">::</span>exception_ptr_cast</code>
from P2927R2.</p>
<p>This works because the language feature itself uses
<code class="sourceCode cpp">try_cast</code> if available. Casts of
user-defined types using calls to
<code class="sourceCode cpp">try_cast</code> found via ADL, will also
work, such as:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> ns <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Widget <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-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="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> T<span class="op">*</span> try_cast<span class="op">(</span><span class="kw">const</span> Widget<span class="op">&amp;</span> w<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="co">// ...</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="3.1" id="how-does-pattern-matching-actually-use-this"><span class="header-section-number">3.1</span> How does pattern matching
actually use this?<a href="#how-does-pattern-matching-actually-use-this" class="self-link"></a></h2>
<p>Given an example like:</p>
<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><em>subject</em> <span class="cf">match</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <em>type</em><span class="op">:</span> <em>subpattern</em> <span class="op">=&gt;</span> <span class="co">// ...;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="co">// ...;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Conceptually: <code class="sourceCode cpp">try_cast<span class="op">&lt;</span><em>type</em><span class="op">&gt;(</span><em>subject</em><span class="op">)</span></code>
is invoked, which returns an optional result that can be tested and
dereferenced to match the <em>subpattern</em>.</p>
<p>More precisely: Let <code class="sourceCode cpp">E</code> be <code class="sourceCode cpp">try_cast<span class="op">&lt;</span><em>type</em><span class="op">&gt;(</span><em>subject</em><span class="op">)</span></code>.
The call to <code class="sourceCode cpp">try_cast</code> is done using
ADL-only lookup, just as is done with calls to
<code class="sourceCode cpp">get</code> for structured bindings (see
<span>9.6
<a href="https://wg21.link/dcl.struct.bind">[dcl.struct.bind]</a></span>).</p>
<p>The match is well-formed if and only if:</p>
<ul>
<li><code class="sourceCode cpp">E</code> is well-formed;</li>
<li><code class="sourceCode cpp">E</code> is contextually convertible to
<code class="sourceCode cpp"><span class="dt">bool</span></code>;
and</li>
<li><code class="sourceCode cpp">E</code> is dereferencable.</li>
</ul>
<p>A well-formed match succeeds if and only if
<code class="sourceCode cpp">E</code> contextually converts to
<code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp"><span class="op">*</span>E</code> matches
<em>subpattern</em>.</p>
<h1 data-number="4" id="proposed-wording"><span class="header-section-number">4</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<h3 class="unnumbered unlisted" id="any.synop-header-any-synopsis"><span>22.7.2
<a href="https://wg21.link/any.synop">[any.synop]</a></span> Header
<code class="sourceCode cpp"><span class="op">&lt;</span>any<span class="op">&gt;</span></code>
synopsis<a href="#any.synop-header-any-synopsis" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb8"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    T any_cast(const any&amp; operand);</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    T any_cast(any&amp; operand);</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    T any_cast(any&amp;&amp; operand);</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    const T* any_cast(const any* operand) noexcept;</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    T* any_cast(any* operand) noexcept;</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="va">+   const T* try_cast(const Any&amp; operand) noexcept;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a><span class="va">+   T* try_cast(Any&amp; operand) noexcept;</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a><span class="va">+   T* try_cast(Any&amp;&amp; operand) noexcept;</span></span></code></pre></div>
</div>
<h3 class="unnumbered unlisted" id="any.nonmembers-non-member-functions"><span>22.7.5
<a href="https://wg21.link/any.nonmembers">[any.nonmembers]</a></span>
Non-member functions<a href="#any.nonmembers-non-member-functions" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb9"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   const T* try_cast(const Any&amp; operand) noexcept;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="va">+   T* try_cast(Any&amp; operand) noexcept;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class T, same_as&lt;any&gt; Any&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="va">+   T* try_cast(Any&amp;&amp; operand) noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Mandates</em>:
<code class="sourceCode default">is_void_v&lt;T&gt;</code> is
<code class="sourceCode default">false</code>.</p>
<p><em>Returns</em>:
<code class="sourceCode default">any_cast&lt;T&gt;(&amp;operand)</code></p>
</blockquote>

</div>
<h3 class="unnumbered unlisted" id="exception.syn-header-exception-synopsis"><span>17.9.2
<a href="https://wg21.link/exception.syn">[exception.syn]</a></span>
Header <code class="sourceCode cpp"><span class="op">&lt;</span>exception<span class="op">&gt;</span></code>
synopsis<a href="#exception.syn-header-exception-synopsis" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb10"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>  exception_ptr current_exception() noexcept;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  [[noreturn]] void rethrow_exception(exception_ptr p);</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  template &lt;class E&gt;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    const E* exception_ptr_cast(const exception_ptr&amp; p) noexcept;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  template &lt;class T&gt; [[noreturn]] void throw_with_nested(T&amp;&amp; t);</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class E&gt;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   const E* try_cast(const exception_ptr&amp; p) noexcept;</span></span></code></pre></div>
</div>
<h3 class="unnumbered unlisted" id="propagation-exception-propagation"><span>17.9.7
<a href="https://wg21.link/propagation">[propagation]</a></span>
Exception propagation<a href="#propagation-exception-propagation" class="self-link"></a></h3>
<div>
<div class="sourceCode" id="cb11"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;class E&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   const E* try_cast(const exception_ptr&amp; p) noexcept;</span></span></code></pre></div>
</div>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Mandates</em>: <code class="sourceCode default">E</code> is a
<em>cv</em>-unqualified complete object type.
<code class="sourceCode default">E</code> is not an array type.
<code class="sourceCode default">E</code> is not a pointer or
pointer-to-member type.</p>
<p><em>Returns</em>:
<code class="sourceCode default">exception_ptr_cast&lt;E&gt;(p)</code></p>
</blockquote>

</div>
<h1 data-number="5" id="design-alternatives"><span class="header-section-number">5</span> Design Alternatives<a href="#design-alternatives" class="self-link"></a></h1>
<h2 data-number="5.1" id="overload-any_cast"><span class="header-section-number">5.1</span> Overload
<code class="sourceCode cpp">any_cast</code><a href="#overload-any_cast" class="self-link"></a></h2>
<p>Adding new overloads of <code class="sourceCode cpp">any_cast</code>
was considered as a way to opt-in as an any-like type. Effectively
designating variant-like as the closed sum type opt-in, and any-like as
the open sum type opt-in.</p>
<p>The reason this approach is not taken is purely technical. The
current overloads of <code class="sourceCode cpp">any_cast</code>
include versions that takes <code class="sourceCode cpp">any</code> by
reference. Since <code class="sourceCode cpp">any</code> is implicitly
constructible from anything, testing the validity of
<code class="sourceCode cpp">any_cast</code> is virtually always
true.</p>
<h2 data-number="5.2" id="parameters-as-pointers"><span class="header-section-number">5.2</span> Parameters as Pointers<a href="#parameters-as-pointers" class="self-link"></a></h2>
<p>It was considered to take the parameters by pointer instead to avoid
the implicit construction of <code class="sourceCode cpp">any</code>
from anything problem:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" 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="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> T<span class="op">*</span> try_cast<span class="op">(</span><span class="kw">const</span> any<span class="op">*</span> a<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> any_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>a<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" 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="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> try_cast<span class="op">(</span>any<span class="op">*</span> a<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> any_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>a<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" 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="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> T<span class="op">*</span> try_cast<span class="op">(</span><span class="kw">const</span> exception_ptr<span class="op">*</span> p<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>p<span class="op">)</span> <span class="cf">return</span> <span class="kw">nullptr</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> exception_ptr_cast<span class="op">&lt;</span>T<span class="op">&gt;(*</span>p<span class="op">)</span>; <span class="co">// P2927R2</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This solves the problem of having to specify <code class="sourceCode cpp">same_as<span class="op">&lt;</span>any<span class="op">&gt;</span></code>
constraint, but it makes the rest of the overloads less obvious and
familiar.</p>
<h2 data-number="5.3" id="use-a-stdhash-like-approach"><span class="header-section-number">5.3</span> Use a
<code class="sourceCode cpp">std<span class="op">::</span>hash</code>-like
Approach<a href="#use-a-stdhash-like-approach" class="self-link"></a></h2>
<p>This approach is to make <code class="sourceCode cpp">try_cast</code>
be a class template that users specialize, rather than an overload
set.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> try_cast; <span class="co">// undefined</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;&gt;</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> try_cast<span class="op">&lt;</span>std<span class="op">::</span>any<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" 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="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">const</span> T<span class="op">*</span> to<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="cb13-9"><a href="#cb13-9" 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="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-12"><a href="#cb13-12" 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="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> T<span class="op">*</span> to<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="cb13-14"><a href="#cb13-14" 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="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;&gt;</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> try_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="cb13-20"><a href="#cb13-20" 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="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">const</span> T<span class="op">*</span> to<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="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>exception_ptr_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>p<span class="op">)</span>; <span class="co">// P2927R2</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This allows the parameters to become references again. There are two
downsides of this approach:</p>
<ol type="1">
<li>The user-defined type needs to re-open the
<code class="sourceCode cpp">std</code> namespace in order to provide
the specialization.</li>
<li>The API becomes <code class="sourceCode cpp">std<span class="op">::</span>try_cast<span class="op">&lt;</span>From<span class="op">&gt;::</span>to<span class="op">&lt;</span>To<span class="op">&gt;(</span>from<span class="op">)</span></code>,
compared to the proposed API which would be simply <code class="sourceCode cpp">try_cast<span class="op">&lt;</span>To<span class="op">&gt;(</span>from<span class="op">)</span></code>.</li>
</ol>
<h2 data-number="5.4" id="create-a-try_cast-cpo"><span class="header-section-number">5.4</span> Create a
<code class="sourceCode cpp">try_cast</code> CPO<a href="#create-a-try_cast-cpo" class="self-link"></a></h2>
<p>This approach was seriously considered by the authors, but discarded.
We wrote wording for it and everything. While it may be useful for users
in general, it is a terrible fit for use by a language feature. The CPO
would have to live in a particular header. That header would then need
to be included wherever a
<code class="sourceCode cpp">type<span class="op">:</span></code>
pattern was applied to an open sum type.</p>
<p>In the general case, the user would have no obvious way of noticing
that this requirement was not met. They would just get a diagnostic
telling them to
<code class="sourceCode cpp"><span class="pp">#include</span></code> the
right header. Users already have to deal with this occasionally when the
compiler informs them that they forgot to include <code class="sourceCode cpp"><span class="op">&lt;</span>initializer_list<span class="op">&gt;</span></code>.</p>
<p>Note that the tuple protocol uses direct calls to the overloads that
it requires for producing structured bindings, and this decision is in
line with that. In any case, the decision not to use a CPO is already
made; it’s part of the language feature.</p>
<h1 data-number="6" id="bibliography"><span class="header-section-number">6</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-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-P2688R3" class="csl-entry" role="doc-biblioentry">
[P2688R3] Michael Park. 2024-10-16. Pattern Matching: `match`
Expression. <a href="https://wg21.link/p2688r3"><div class="csl-block">https://wg21.link/p2688r3</div></a>
</div>
<div id="ref-P2927R2" class="csl-entry" role="doc-biblioentry">
[P2927R2] Gor Nishanov, Arthur O’Dwyer. 2024-04-16. Observing exceptions
stored in exception_ptr. <a href="https://wg21.link/p2927r2"><div class="csl-block">https://wg21.link/p2927r2</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
