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

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.addu td pre { background-color: inherit; }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
div.std blockquote { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
div.std.ins blockquote {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.ins > div.example {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.std div.sourceCode { background-color: inherit; margin-left: 1em; }
div.rm li {
text-decoration: line-through;
color: #000000;
}
div.std blockquote del, div.rm {
text-decoration: line-through;
color: #000000;
background-color: var(--diff-del);
border: none;
}
code del { border: 1px solid #ECB3C7; }
span.orange {
background-color: #ffa500;
}
span.yellow {
background-color: #ffff00;
}</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">Reflection for C++26</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2996R12 <a href="https://wg21.link/P2996">[Latest]</a> <a href="https://wg21.link/P2996/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-05-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>
      CWG, EWG, LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Wyatt Childers<br>&lt;<a href="mailto:wcc@edg.com" class="email">wcc@edg.com</a>&gt;<br>
      Peter Dimov<br>&lt;<a href="mailto:pdimov@gmail.com" class="email">pdimov@gmail.com</a>&gt;<br>
      Dan Katz<br>&lt;<a href="mailto:dkatz85@bloomberg.net" class="email">dkatz85@bloomberg.net</a>&gt;<br>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
      Andrew Sutton<br>&lt;<a href="mailto:andrew.n.sutton@gmail.com" class="email">andrew.n.sutton@gmail.com</a>&gt;<br>
      Faisal Vali<br>&lt;<a href="mailto:faisalv@gmail.com" class="email">faisalv@gmail.com</a>&gt;<br>
      Daveed Vandevoorde<br>&lt;<a href="mailto:daveed@edg.com" class="email">daveed@edg.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">1</span> Revision
History<span></span></a></li>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">2</span> Introduction<span></span></a>
<ul>
<li><a href="#notable-additions-to-p1240" id="toc-notable-additions-to-p1240"><span class="toc-section-number">2.1</span> Notable Additions to
P1240<span></span></a></li>
<li><a href="#why-a-single-opaque-reflection-type" id="toc-why-a-single-opaque-reflection-type"><span class="toc-section-number">2.2</span> Why a single opaque reflection
type?<span></span></a></li>
<li><a href="#implementation-status" id="toc-implementation-status"><span class="toc-section-number">2.3</span> Implementation
Status<span></span></a></li>
</ul></li>
<li><a href="#examples" id="toc-examples"><span class="toc-section-number">3</span> Examples<span></span></a>
<ul>
<li><a href="#back-and-forth" id="toc-back-and-forth"><span class="toc-section-number">3.1</span>
Back-And-Forth<span></span></a></li>
<li><a href="#selecting-members" id="toc-selecting-members"><span class="toc-section-number">3.2</span> Selecting
Members<span></span></a></li>
<li><a href="#list-of-types-to-list-of-sizes" id="toc-list-of-types-to-list-of-sizes"><span class="toc-section-number">3.3</span> List of Types to List of
Sizes<span></span></a></li>
<li><a href="#implementing-make_integer_sequence" id="toc-implementing-make_integer_sequence"><span class="toc-section-number">3.4</span> Implementing
<code class="sourceCode cpp">make_integer_sequence</code><span></span></a></li>
<li><a href="#getting-class-layout" id="toc-getting-class-layout"><span class="toc-section-number">3.5</span> Getting Class
Layout<span></span></a></li>
<li><a href="#enum-to-string" id="toc-enum-to-string"><span class="toc-section-number">3.6</span> Enum to
String<span></span></a></li>
<li><a href="#parsing-command-line-options" id="toc-parsing-command-line-options"><span class="toc-section-number">3.7</span> Parsing Command-Line
Options<span></span></a></li>
<li><a href="#a-simple-tuple-type" id="toc-a-simple-tuple-type"><span class="toc-section-number">3.8</span> A Simple Tuple
Type<span></span></a></li>
<li><a href="#a-simple-variant-type" id="toc-a-simple-variant-type"><span class="toc-section-number">3.9</span> A Simple Variant
Type<span></span></a></li>
<li><a href="#struct-to-struct-of-arrays" id="toc-struct-to-struct-of-arrays"><span class="toc-section-number">3.10</span> Struct to Struct of
Arrays<span></span></a></li>
<li><a href="#parsing-command-line-options-ii" id="toc-parsing-command-line-options-ii"><span class="toc-section-number">3.11</span> Parsing Command-Line Options
II<span></span></a></li>
<li><a href="#a-universal-formatter" id="toc-a-universal-formatter"><span class="toc-section-number">3.12</span> A Universal
Formatter<span></span></a></li>
<li><a href="#implementing-member-wise-hash_append" id="toc-implementing-member-wise-hash_append"><span class="toc-section-number">3.13</span> Implementing member-wise
<code class="sourceCode cpp">hash_append</code><span></span></a></li>
<li><a href="#converting-a-struct-to-a-tuple" id="toc-converting-a-struct-to-a-tuple"><span class="toc-section-number">3.14</span> Converting a Struct to a
Tuple<span></span></a></li>
<li><a href="#implementing-tuple_cat" id="toc-implementing-tuple_cat"><span class="toc-section-number">3.15</span> Implementing
<code class="sourceCode cpp">tuple_cat</code><span></span></a></li>
<li><a href="#named-tuple" id="toc-named-tuple"><span class="toc-section-number">3.16</span> Named Tuple<span></span></a></li>
<li><a href="#compile-time-ticket-counter" id="toc-compile-time-ticket-counter"><span class="toc-section-number">3.17</span> Compile-Time Ticket
Counter<span></span></a></li>
</ul></li>
<li><a href="#proposed-features" id="toc-proposed-features"><span class="toc-section-number">4</span> Proposed Features<span></span></a>
<ul>
<li><a href="#the-reflection-operator" id="toc-the-reflection-operator"><span class="toc-section-number">4.1</span> The Reflection Operator
(<code class="sourceCode cpp"><span class="op">^^</span></code>)<span></span></a>
<ul>
<li><a href="#syntax-discussion" id="toc-syntax-discussion"><span class="toc-section-number">4.1.1</span> Syntax
discussion<span></span></a></li>
</ul></li>
<li><a href="#splicers" id="toc-splicers"><span class="toc-section-number">4.2</span> Splicers
(<code class="sourceCode cpp"><span class="op">[:</span></code>…<code class="sourceCode cpp"><span class="op">:]</span></code>)<span></span></a>
<ul>
<li><a href="#addressed-splicing" id="toc-addressed-splicing"><span class="toc-section-number">4.2.1</span> Addressed
Splicing<span></span></a></li>
<li><a href="#limitations" id="toc-limitations"><span class="toc-section-number">4.2.2</span> Limitations<span></span></a>
<ul>
<li><a href="#splicing-reflections-of-constructors" id="toc-splicing-reflections-of-constructors"><span class="toc-section-number">4.2.2.1</span> Splicing reflections of
constructors<span></span></a></li>
<li><a href="#splicing-namespaces-in-namespace-definitions" id="toc-splicing-namespaces-in-namespace-definitions"><span class="toc-section-number">4.2.2.2</span> Splicing namespaces in
namespace definitions<span></span></a></li>
<li><a href="#splicing-namespaces-in-using-directives-and-using-enum-declarators" id="toc-splicing-namespaces-in-using-directives-and-using-enum-declarators"><span class="toc-section-number">4.2.2.3</span> Splicing namespaces in
using-directives and using-enum-declarators<span></span></a></li>
<li><a href="#splicing-concepts-in-declarations-of-template-parameters" id="toc-splicing-concepts-in-declarations-of-template-parameters"><span class="toc-section-number">4.2.2.4</span> Splicing concepts in
declarations of template parameters<span></span></a></li>
<li><a href="#splicing-class-members-as-designators-in-designated-initializer-lists" id="toc-splicing-class-members-as-designators-in-designated-initializer-lists"><span class="toc-section-number">4.2.2.5</span> Splicing class members as
designators in designated-initializer-lists<span></span></a></li>
</ul></li>
<li><a href="#range-splicers" id="toc-range-splicers"><span class="toc-section-number">4.2.3</span> Range
Splicers<span></span></a></li>
<li><a href="#syntax-discussion-1" id="toc-syntax-discussion-1"><span class="toc-section-number">4.2.4</span> Syntax
discussion<span></span></a></li>
</ul></li>
<li><a href="#stdmetainfo" id="toc-stdmetainfo"><span class="toc-section-number">4.3</span> <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code><span></span></a>
<ul>
<li><a href="#comparing-reflections" id="toc-comparing-reflections"><span class="toc-section-number">4.3.1</span> Comparing
reflections<span></span></a></li>
<li><a href="#the-associated-stdmeta-namespace" id="toc-the-associated-stdmeta-namespace"><span class="toc-section-number">4.3.2</span> The associated
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
namespace<span></span></a></li>
<li><a href="#consteval-only" id="toc-consteval-only"><span class="toc-section-number">4.3.3</span>
Consteval-only<span></span></a></li>
</ul></li>
<li><a href="#metafunctions" id="toc-metafunctions"><span class="toc-section-number">4.4</span> Metafunctions<span></span></a>
<ul>
<li><a href="#constant-evaluation-order" id="toc-constant-evaluation-order"><span class="toc-section-number">4.4.1</span> Constant evaluation
order<span></span></a></li>
<li><a href="#error-handling-in-reflection" id="toc-error-handling-in-reflection"><span class="toc-section-number">4.4.2</span> Error-Handling in
Reflection<span></span></a></li>
<li><a href="#range-based-metafunctions" id="toc-range-based-metafunctions"><span class="toc-section-number">4.4.3</span> Range-Based
Metafunctions<span></span></a></li>
<li><a href="#handling-aliases" id="toc-handling-aliases"><span class="toc-section-number">4.4.4</span> Handling
Aliases<span></span></a></li>
<li><a href="#reflecting-source-text" id="toc-reflecting-source-text"><span class="toc-section-number">4.4.5</span> Reflecting source
text<span></span></a></li>
<li><a href="#reflecting-names" id="toc-reflecting-names"><span class="toc-section-number">4.4.6</span> Reflecting
names<span></span></a></li>
<li><a href="#reachability-and-injected-declarations" id="toc-reachability-and-injected-declarations"><span class="toc-section-number">4.4.7</span> Reachability and injected
declarations<span></span></a></li>
<li><a href="#restrictions-on-injected-declarations" id="toc-restrictions-on-injected-declarations"><span class="toc-section-number">4.4.8</span> Restrictions on injected
declarations<span></span></a></li>
<li><a href="#freestanding-implementations" id="toc-freestanding-implementations"><span class="toc-section-number">4.4.9</span> Freestanding
implementations<span></span></a></li>
<li><a href="#synopsis" id="toc-synopsis"><span class="toc-section-number">4.4.10</span> Synopsis<span></span></a></li>
<li><a href="#name-loc" id="toc-name-loc"><span class="toc-section-number">4.4.11</span>
<code class="sourceCode cpp">identifier_of</code>,
<code class="sourceCode cpp">display_string_of</code>,
<code class="sourceCode cpp">source_location_of</code><span></span></a></li>
<li><a href="#type_of-parent_of-dealias" id="toc-type_of-parent_of-dealias"><span class="toc-section-number">4.4.12</span>
<code class="sourceCode cpp">type_of</code>,
<code class="sourceCode cpp">parent_of</code>,
<code class="sourceCode cpp">dealias</code><span></span></a></li>
<li><a href="#object_of-constant_of" id="toc-object_of-constant_of"><span class="toc-section-number">4.4.13</span>
<code class="sourceCode cpp">object_of</code>,
<code class="sourceCode cpp">constant_of</code><span></span></a></li>
<li><a href="#template_of-template_arguments_of" id="toc-template_of-template_arguments_of"><span class="toc-section-number">4.4.14</span>
<code class="sourceCode cpp">template_of</code>,
<code class="sourceCode cpp">template_arguments_of</code><span></span></a></li>
<li><a href="#member-queries" id="toc-member-queries"><span class="toc-section-number">4.4.15</span>
<code class="sourceCode cpp">members_of</code>,
<code class="sourceCode cpp">static_data_members_of</code>,
<code class="sourceCode cpp">nonstatic_data_members_of</code>,
<code class="sourceCode cpp">bases_of</code>,
<code class="sourceCode cpp">enumerators_of</code><span></span></a></li>
<li><a href="#substitute" id="toc-substitute"><span class="toc-section-number">4.4.16</span>
<code class="sourceCode cpp">substitute</code><span></span></a></li>
<li><a href="#reflect-expression-results" id="toc-reflect-expression-results"><span class="toc-section-number">4.4.17</span>
<code class="sourceCode cpp">reflect_constant</code>,
<code class="sourceCode cpp">reflect_object</code>,
<code class="sourceCode cpp">reflect_function</code><span></span></a></li>
<li><a href="#extractt" id="toc-extractt"><span class="toc-section-number">4.4.18</span> <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span></span></a></li>
<li><a href="#data_member_spec-define_aggregate" id="toc-data_member_spec-define_aggregate"><span class="toc-section-number">4.4.19</span>
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_aggregate</code><span></span></a></li>
<li><a href="#data-layout-reflection" id="toc-data-layout-reflection"><span class="toc-section-number">4.4.20</span> Data Layout
Reflection<span></span></a></li>
<li><a href="#other-type-traits" id="toc-other-type-traits"><span class="toc-section-number">4.4.21</span> Other Type
Traits<span></span></a></li>
</ul></li>
<li><a href="#odr-concerns" id="toc-odr-concerns"><span class="toc-section-number">4.5</span> ODR Concerns<span></span></a></li>
</ul></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">5</span> Proposed Wording<span></span></a>
<ul>
<li><a href="#language" id="toc-language"><span class="toc-section-number">5.1</span> Language<span></span></a>
<ul>
<li><a href="#intro.defs-terms-and-definitions" id="toc-intro.defs-terms-and-definitions"><span>3
<span>[intro.defs]</span></span> Terms and
definitions<span></span></a></li>
<li><a href="#lex.phases-phases-of-translation" id="toc-lex.phases-phases-of-translation"><span>5.2
<span>[lex.phases]</span></span> Phases of
translation<span></span></a></li>
<li><a href="#lex.pptoken-preprocessing-tokens" id="toc-lex.pptoken-preprocessing-tokens"><span>5.5
<span>[lex.pptoken]</span></span> Preprocessing
tokens<span></span></a></li>
<li><a href="#lex.operators-operators-and-punctuators" id="toc-lex.operators-operators-and-punctuators"><span>5.8
<span>[lex.operators]</span></span> Operators and
punctuators<span></span></a></li>
<li><a href="#basic.pre-preamble" id="toc-basic.pre-preamble"><span>6.1
<span>[basic.pre]</span></span> Preamble<span></span></a></li>
<li><a href="#basic.def-declarations-and-definitions" id="toc-basic.def-declarations-and-definitions"><span>6.2
<span>[basic.def]</span></span> Declarations and
definitions<span></span></a></li>
<li><a href="#basic.def.odr-one-definition-rule" id="toc-basic.def.odr-one-definition-rule"><span>6.3
<span>[basic.def.odr]</span></span> One-definition
rule<span></span></a></li>
<li><a href="#basic.scope.scope-general" id="toc-basic.scope.scope-general"><span>6.4.1
<span>[basic.scope.scope]</span></span> General<span></span></a></li>
<li><a href="#basic.lookup.general-general" id="toc-basic.lookup.general-general"><span>6.5.1
<span>[basic.lookup.general]</span></span> General<span></span></a></li>
<li><a href="#basic.lookup.argdep-argument-dependent-name-lookup" id="toc-basic.lookup.argdep-argument-dependent-name-lookup"><span>6.5.4
<span>[basic.lookup.argdep]</span></span> Argument-dependent name
lookup<span></span></a></li>
<li><a href="#basic.lookup.qual.general-general" id="toc-basic.lookup.qual.general-general"><span>6.5.5.1
<span>[basic.lookup.qual.general]</span></span>
General<span></span></a></li>
<li><a href="#basic.splice-splice-specifiers" id="toc-basic.splice-splice-specifiers">6.5+ [basic.splice] Splice
specifiers<span></span></a></li>
<li><a href="#basic.link-program-and-linkage" id="toc-basic.link-program-and-linkage"><span>6.6
<span>[basic.link]</span></span> Program and
Linkage<span></span></a></li>
<li><a href="#basic.types.general-general" id="toc-basic.types.general-general"><span>6.8.1
<span>[basic.types.general]</span></span> General<span></span></a></li>
<li><a href="#basic.fundamental-fundamental-types" id="toc-basic.fundamental-fundamental-types"><span>6.8.2
<span>[basic.fundamental]</span></span> Fundamental
types<span></span></a></li>
<li><a href="#intro.execution-sequential-execution" id="toc-intro.execution-sequential-execution"><span>6.9.1
<span>[intro.execution]</span></span> Sequential
execution<span></span></a></li>
<li><a href="#basic.lval-value-category" id="toc-basic.lval-value-category"><span>7.2.1
<span>[basic.lval]</span></span> Value category<span></span></a></li>
<li><a href="#expr.context-context-dependence" id="toc-expr.context-context-dependence"><span>7.2.3
<span>[expr.context]</span></span> Context
dependence<span></span></a></li>
<li><a href="#expr.prim-primary-expressions" id="toc-expr.prim-primary-expressions"><span>7.5
<span>[expr.prim]</span></span> Primary
expressions<span></span></a></li>
<li><a href="#expr.prim.id.general-general" id="toc-expr.prim.id.general-general"><span>7.5.5.1
<span>[expr.prim.id.general]</span></span> General<span></span></a></li>
<li><a href="#expr.prim.id.unqual-unqualified-names" id="toc-expr.prim.id.unqual-unqualified-names"><span>7.5.5.2
<span>[expr.prim.id.unqual]</span></span> Unqualified
names<span></span></a></li>
<li><a href="#expr.prim.id.qual-qualified-names" id="toc-expr.prim.id.qual-qualified-names"><span>7.5.5.3
<span>[expr.prim.id.qual]</span></span> Qualified
names<span></span></a></li>
<li><a href="#expr.prim.lambda.closure-closure-types" id="toc-expr.prim.lambda.closure-closure-types"><span>7.5.6.2
<span>[expr.prim.lambda.closure]</span></span> Closure
types<span></span></a></li>
<li><a href="#expr.prim.req.type-type-requirements" id="toc-expr.prim.req.type-type-requirements"><span>7.5.8.3
<span>[expr.prim.req.type]</span></span> Type
requirements<span></span></a></li>
<li><a href="#expr.prim.splice-expression-splicing" id="toc-expr.prim.splice-expression-splicing">7.5.8* [expr.prim.splice]
Expression splicing<span></span></a></li>
<li><a href="#expr.post.general-general" id="toc-expr.post.general-general"><span>7.6.1.1
<span>[expr.post.general]</span></span> General<span></span></a></li>
<li><a href="#expr.ref-class-member-access" id="toc-expr.ref-class-member-access"><span>7.6.1.5
<span>[expr.ref]</span></span> Class member access<span></span></a></li>
<li><a href="#expr.unary.general-general" id="toc-expr.unary.general-general"><span>7.6.2.1
<span>[expr.unary.general]</span></span> General<span></span></a></li>
<li><a href="#expr.unary.op-unary-operators" id="toc-expr.unary.op-unary-operators"><span>7.6.2.2
<span>[expr.unary.op]</span></span> Unary
operators<span></span></a></li>
<li><a href="#expr.reflect-the-reflection-operator" id="toc-expr.reflect-the-reflection-operator">7.6.2.10* [expr.reflect]
The reflection operator<span></span></a></li>
<li><a href="#expr.eq-equality-operators" id="toc-expr.eq-equality-operators"><span>7.6.10
<span>[expr.eq]</span></span> Equality Operators<span></span></a></li>
<li><a href="#expr.const-constant-expressions" id="toc-expr.const-constant-expressions"><span>7.7
<span>[expr.const]</span></span> Constant
Expressions<span></span></a></li>
<li><a href="#dcl.pre-preamble" id="toc-dcl.pre-preamble"><span>9.1
<span>[dcl.pre]</span></span> Preamble<span></span></a></li>
<li><a href="#dcl.typedef-the-typedef-specifier" id="toc-dcl.typedef-the-typedef-specifier"><span>9.2.4
<span>[dcl.typedef]</span></span> The
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier<span></span></a></li>
<li><a href="#dcl.type.simple-simple-type-specifiers" id="toc-dcl.type.simple-simple-type-specifiers"><span>9.2.9.3
<span>[dcl.type.simple]</span></span> Simple type
specifiers<span></span></a></li>
<li><a href="#dcl.type.decltype-decltype-specifiers" id="toc-dcl.type.decltype-decltype-specifiers"><span>9.2.9.6
<span>[dcl.type.decltype]</span></span> Decltype
specifiers<span></span></a></li>
<li><a href="#dcl.spec.auto.general-placeholder-type-specifiers" id="toc-dcl.spec.auto.general-placeholder-type-specifiers"><span>9.2.9.7.1
<span>[dcl.spec.auto.general]</span></span> Placeholder type
specifiers<span></span></a></li>
<li><a href="#dcl.type.splice-type-splicing" id="toc-dcl.type.splice-type-splicing">9.2.9.8+ [dcl.type.splice] Type
splicing<span></span></a></li>
<li><a href="#dcl.array-arrays" id="toc-dcl.array-arrays"><span>9.3.4.5
<span>[dcl.array]</span></span> Arrays<span></span></a></li>
<li><a href="#dcl.fct-functions" id="toc-dcl.fct-functions"><span>9.3.4.6 <span>[dcl.fct]</span></span>
Functions<span></span></a></li>
<li><a href="#dcl.fct.default-default-arguments" id="toc-dcl.fct.default-default-arguments"><span>9.3.4.7
<span>[dcl.fct.default]</span></span> Default
arguments<span></span></a></li>
<li><a href="#dcl.init.general-initializers-general" id="toc-dcl.init.general-initializers-general"><span>9.5.1
<span>[dcl.init.general]</span></span> Initializers
(General)<span></span></a></li>
<li><a href="#dcl.fct.def.general-function-definitions" id="toc-dcl.fct.def.general-function-definitions"><span>9.6.1
<span>[dcl.fct.def.general]</span></span> Function
definitions<span></span></a></li>
<li><a href="#dcl.fct.def.delete-deleted-definitions" id="toc-dcl.fct.def.delete-deleted-definitions"><span>9.6.3
<span>[dcl.fct.def.delete]</span></span> Deleted
definitions<span></span></a></li>
<li><a href="#enum.udecl-the-using-enum-declaration" id="toc-enum.udecl-the-using-enum-declaration"><span>9.8.2
<span>[enum.udecl]</span></span> The <code class="sourceCode cpp"><span class="kw">using</span> <span class="kw">enum</span></code>
declaration<span></span></a></li>
<li><a href="#namespace.alias-namespace-alias" id="toc-namespace.alias-namespace-alias"><span>9.9.3
<span>[namespace.alias]</span></span> Namespace
alias<span></span></a></li>
<li><a href="#namespace.udir-using-namespace-directive" id="toc-namespace.udir-using-namespace-directive"><span>9.9.4
<span>[namespace.udir]</span></span> Using namespace
directive<span></span></a></li>
<li><a href="#dcl.attr.grammar-attribute-syntax-and-semantics" id="toc-dcl.attr.grammar-attribute-syntax-and-semantics"><span>9.13.1
<span>[dcl.attr.grammar]</span></span> Attribute syntax and
semantics<span></span></a></li>
<li><a href="#dcl.attr.deprecated-deprecated-attribute" id="toc-dcl.attr.deprecated-deprecated-attribute"><span>9.13.4
<span>[dcl.attr.deprecated]</span></span> Deprecated
attribute<span></span></a></li>
<li><a href="#dcl.attr.unused-maybe-unused-attribute" id="toc-dcl.attr.unused-maybe-unused-attribute"><span>9.13.8
<span>[dcl.attr.unused]</span></span> Maybe unused
attribute<span></span></a></li>
<li><a href="#module.global.frag-global-module-fragment" id="toc-module.global.frag-global-module-fragment"><span>10.4
<span>[module.global.frag]</span></span> Global module
fragment<span></span></a></li>
<li><a href="#module.context-instantiation-context" id="toc-module.context-instantiation-context"><span>10.6
<span>[module.context]</span></span> Instantiation
context<span></span></a></li>
<li><a href="#module.reach-reachability" id="toc-module.reach-reachability"><span>10.7
<span>[module.reach]</span></span> Reachability<span></span></a></li>
<li><a href="#class.mem.general-general" id="toc-class.mem.general-general"><span>11.4.1
<span>[class.mem.general]</span></span> General<span></span></a></li>
<li><a href="#class.union.anon-anonymous-unions" id="toc-class.union.anon-anonymous-unions"><span>11.5.2
<span>[class.union.anon]</span></span> Anonymous
unions<span></span></a></li>
<li><a href="#class.derived.general-general" id="toc-class.derived.general-general"><span>11.7.1
<span>[class.derived.general]</span></span>
General<span></span></a></li>
<li><a href="#class.access.general-general" id="toc-class.access.general-general"><span>11.8.1
<span>[class.access.general]</span></span> General<span></span></a></li>
<li><a href="#class.access.base-accessibility-of-base-classes-and-base-class-members" id="toc-class.access.base-accessibility-of-base-classes-and-base-class-members"><span>11.8.3
<span>[class.access.base]</span></span> Accessibility of base classes
and base class members<span></span></a></li>
<li><a href="#over.pre-preamble" id="toc-over.pre-preamble"><span>12.1
<span>[over.pre]</span></span> Preamble<span></span></a></li>
<li><a href="#over.call.func-call-to-named-function" id="toc-over.call.func-call-to-named-function"><span>12.2.2.2.2
<span>[over.call.func]</span></span> Call to named
function<span></span></a></li>
<li><a href="#over.match.class.deduct-class-template-argument-deduction" id="toc-over.match.class.deduct-class-template-argument-deduction"><span>12.2.2.9
<span>[over.match.class.deduct]</span></span> Class template argument
deduction<span></span></a></li>
<li><a href="#over.match.viable-viable-functions" id="toc-over.match.viable-viable-functions"><span>12.2.3
<span>[over.match.viable]</span></span> Viable
functions<span></span></a></li>
<li><a href="#over.match.best.general-general" id="toc-over.match.best.general-general"><span>12.2.4.1
<span>[over.match.best.general]</span></span>
General<span></span></a></li>
<li><a href="#over.over-address-of-an-overload-set" id="toc-over.over-address-of-an-overload-set"><span>12.3
<span>[over.over]</span></span> Address of an overload
set<span></span></a></li>
<li><a href="#over.built-built-in-operators" id="toc-over.built-built-in-operators"><span>12.5
<span>[over.built]</span></span> Built-in
operators<span></span></a></li>
<li><a href="#temp.param-template-parameters" id="toc-temp.param-template-parameters"><span>13.2
<span>[temp.param]</span></span> Template
parameters<span></span></a></li>
<li><a href="#temp.names-names-of-template-specializations" id="toc-temp.names-names-of-template-specializations"><span>13.3
<span>[temp.names]</span></span> Names of template
specializations<span></span></a></li>
<li><a href="#temp.arg.general-general" id="toc-temp.arg.general-general"><span>13.4.1
<span>[temp.arg.general]</span></span> General<span></span></a></li>
<li><a href="#temp.arg.type-template-type-arguments" id="toc-temp.arg.type-template-type-arguments"><span>13.4.2
<span>[temp.arg.type]</span></span> Template type
arguments<span></span></a></li>
<li><a href="#temp.arg.nontype-constant-template-arguments" id="toc-temp.arg.nontype-constant-template-arguments"><span>13.4.3
<span>[temp.arg.nontype]</span></span> Constant template
arguments<span></span></a></li>
<li><a href="#temp.arg.template-template-template-arguments" id="toc-temp.arg.template-template-template-arguments"><span>13.4.4
<span>[temp.arg.template]</span></span> Template template
arguments<span></span></a></li>
<li><a href="#temp.type-type-equivalence" id="toc-temp.type-type-equivalence"><span>13.6
<span>[temp.type]</span></span> Type equivalence<span></span></a></li>
<li><a href="#temp.deduct.guide-deduction-guides" id="toc-temp.deduct.guide-deduction-guides"><span>13.7.2.3
<span>[temp.deduct.guide]</span></span> Deduction
guides<span></span></a></li>
<li><a href="#temp.mem-member-templates" id="toc-temp.mem-member-templates"><span>13.7.3
<span>[temp.mem]</span></span> Member templates<span></span></a></li>
<li><a href="#temp.alias-alias-templates" id="toc-temp.alias-alias-templates"><span>13.7.8
<span>[temp.alias]</span></span> Alias templates<span></span></a></li>
<li><a href="#temp.res.general-general" id="toc-temp.res.general-general"><span>13.8.1
<span>[temp.res.general]</span></span> General<span></span></a></li>
<li><a href="#temp.dep.type-dependent-types" id="toc-temp.dep.type-dependent-types"><span>13.8.3.2
<span>[temp.dep.type]</span></span> Dependent
types<span></span></a></li>
<li><a href="#temp.dep.expr-type-dependent-expressions" id="toc-temp.dep.expr-type-dependent-expressions"><span>13.8.3.3
<span>[temp.dep.expr]</span></span> Type-dependent
expressions<span></span></a></li>
<li><a href="#temp.dep.constexpr-value-dependent-expressions" id="toc-temp.dep.constexpr-value-dependent-expressions"><span>13.8.3.4
<span>[temp.dep.constexpr]</span></span> Value-dependent
expressions<span></span></a></li>
<li><a href="#temp.dep.splice-dependent-splice-specifiers" id="toc-temp.dep.splice-dependent-splice-specifiers">13.8.3.4+
[temp.dep.splice] Dependent splice specifiers<span></span></a></li>
<li><a href="#temp.dep.temp-dependent-template-arguments" id="toc-temp.dep.temp-dependent-template-arguments"><span>13.8.3.5
<span>[temp.dep.temp]</span></span> Dependent template
arguments<span></span></a></li>
<li><a href="#temp.dep.namespace-dependent-namespaces" id="toc-temp.dep.namespace-dependent-namespaces">13.8.3.6
[temp.dep.namespace] Dependent namespaces<span></span></a></li>
<li><a href="#temp.expl.spec-explicit-specialization" id="toc-temp.expl.spec-explicit-specialization"><span>13.9.4
<span>[temp.expl.spec]</span></span> Explicit
specialization<span></span></a></li>
<li><a href="#temp.deduct.general-general" id="toc-temp.deduct.general-general"><span>13.10.3.1
<span>[temp.deduct.general]</span></span> General<span></span></a></li>
<li><a href="#temp.deduct.call-deducing-template-arguments-from-a-function-call" id="toc-temp.deduct.call-deducing-template-arguments-from-a-function-call"><span>13.10.3.2
<span>[temp.deduct.call]</span></span> Deducing template arguments from
a function call<span></span></a></li>
<li><a href="#temp.deduct.type-deducing-template-arguments-from-a-type" id="toc-temp.deduct.type-deducing-template-arguments-from-a-type"><span>13.10.3.6
<span>[temp.deduct.type]</span></span> Deducing template arguments from
a type<span></span></a></li>
<li><a href="#cpp.cond-conditional-inclusion" id="toc-cpp.cond-conditional-inclusion"><span>15.2
<span>[cpp.cond]</span></span> Conditional
inclusion<span></span></a></li>
</ul></li>
<li><a href="#library" id="toc-library"><span class="toc-section-number">5.2</span> Library<span></span></a>
<ul>
<li><a href="#structure.specifications-detailed-specifications" id="toc-structure.specifications-detailed-specifications"><span>16.3.2.4
<span>[structure.specifications]</span></span> Detailed
specifications<span></span></a></li>
<li><a href="#headers-headers" id="toc-headers-headers"><span>16.4.2.3
<span>[headers]</span></span> Headers<span></span></a></li>
<li><a href="#namespace.std-namespace-std" id="toc-namespace.std-namespace-std"><span>16.4.5.2.1
<span>[namespace.std]</span></span> Namespace std<span></span></a></li>
<li><a href="#meta.type.synop-header-type_traits-synopsis" id="toc-meta.type.synop-header-type_traits-synopsis"><span>21.3.3
<span>[meta.type.synop]</span></span> Header <code class="sourceCode cpp"><span class="op">&lt;</span>type_traits<span class="op">&gt;</span></code>
synopsis<span></span></a></li>
<li><a href="#meta.unary.cat-primary-type-categories" id="toc-meta.unary.cat-primary-type-categories"><span>21.3.5.2
<span>[meta.unary.cat]</span></span> Primary type
categories<span></span></a></li>
<li><a href="#meta.unary.prop-type-properties" id="toc-meta.unary.prop-type-properties"><span>21.3.5.4
<span>[meta.unary.prop]</span></span> Type
properties<span></span></a></li>
<li><a href="#meta.reflection.synop-header-meta-synopsis" id="toc-meta.reflection.synop-header-meta-synopsis">[meta.reflection.synop]
Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis<span></span></a></li>
<li><a href="#meta.reflection.operators-operator-representations" id="toc-meta.reflection.operators-operator-representations">[meta.reflection.operators]
Operator representations<span></span></a></li>
<li><a href="#meta.reflection.names-reflection-names-and-locations" id="toc-meta.reflection.names-reflection-names-and-locations">[meta.reflection.names]
Reflection names and locations<span></span></a></li>
<li><a href="#meta.reflection.queries-reflection-queries" id="toc-meta.reflection.queries-reflection-queries">[meta.reflection.queries]
Reflection queries<span></span></a></li>
<li><a href="#meta.reflection.access.context-access-control-context" id="toc-meta.reflection.access.context-access-control-context">[meta.reflection.access.context]
Access control context<span></span></a></li>
<li><a href="#meta.reflection.access.queries-member-accessibility-queries" id="toc-meta.reflection.access.queries-member-accessibility-queries">[meta.reflection.access.queries]
Member accessibility queries<span></span></a></li>
<li><a href="#meta.reflection.member.queries-reflection-member-queries" id="toc-meta.reflection.member.queries-reflection-member-queries">[meta.reflection.member.queries]
Reflection member queries<span></span></a></li>
<li><a href="#meta.reflection.layout-reflection-layout-queries" id="toc-meta.reflection.layout-reflection-layout-queries">[meta.reflection.layout]
Reflection layout queries<span></span></a></li>
<li><a href="#meta.reflection.extract-value-extraction" id="toc-meta.reflection.extract-value-extraction">[meta.reflection.extract]
Value extraction<span></span></a></li>
<li><a href="#meta.reflection.substitute-reflection-substitution" id="toc-meta.reflection.substitute-reflection-substitution">[meta.reflection.substitute]
Reflection substitution<span></span></a></li>
<li><a href="#meta.reflection.result-expression-result-reflection" id="toc-meta.reflection.result-expression-result-reflection">[meta.reflection.result]
Expression result reflection<span></span></a></li>
<li><a href="#meta.reflection.define.aggregate-reflection-class-definition-generation" id="toc-meta.reflection.define.aggregate-reflection-class-definition-generation">[meta.reflection.define.aggregate]
Reflection class definition generation<span></span></a></li>
<li><a href="#meta.reflection.traits-reflection-type-traits" id="toc-meta.reflection.traits-reflection-type-traits">[meta.reflection.traits]
Reflection type traits<span></span></a></li>
<li><a href="#bit.cast-function-template-bit_cast" id="toc-bit.cast-function-template-bit_cast"><span>22.11.3
<span>[bit.cast]</span></span> Function template
<code class="sourceCode cpp">bit_cast</code><span></span></a></li>
<li><a href="#diff.cpp23-annex-c-informative-compatibility" id="toc-diff.cpp23-annex-c-informative-compatibility"><span>C.1
<span>[diff.cpp23]</span></span> Annex C (informative)
Compatibility<span></span></a></li>
</ul></li>
<li><a href="#feature-test-macro" id="toc-feature-test-macro"><span class="toc-section-number">5.3</span> Feature-Test
Macro<span></span></a></li>
</ul></li>
<li><a href="#appendix-design-changes-approved-in-hagenberg" id="toc-appendix-design-changes-approved-in-hagenberg"><span class="toc-section-number">6</span> Appendix: Design changes approved in
Hagenberg<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">7</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span>
Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>Since <span class="citation" data-cites="P2996R11"><a href="https://wg21.link/p2996r11" role="doc-biblioref">[P2996R11]</a></span>:</p>
<ul>
<li>core wording updates
<ul>
<li>better specify interaction between spliced function calls and
overload resolution; integrate fix to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span></li>
<li>disallow reflection of local parameters introduced by
<code class="sourceCode cpp"><em>requires-expression</em></code>s</li>
<li>change “naming class” to “designating class” and define for
<code class="sourceCode cpp"><em>splice-expression</em></code>s</li>
<li>replaced <code class="sourceCode cpp">reflect_value</code> and
<code class="sourceCode cpp">value_of</code> with
<code class="sourceCode cpp">reflect_constant</code> and
<code class="sourceCode cpp">constant_of</code>.</li>
</ul></li>
<li>library wording updates
<ul>
<li>improve specification of <code class="sourceCode cpp">access_context<span class="op">::</span>current<span class="op">()</span></code>
(including examples)</li>
<li><code class="sourceCode cpp">size_of<span class="op">(</span>r<span class="op">)</span></code>
is no longer constant if <code class="sourceCode cpp">r</code> is a
bit-field</li>
<li>allowing <code class="sourceCode cpp">extract</code> to pull a
pointer from an array</li>
</ul></li>
</ul>
<p>Since <span class="citation" data-cites="P2996R10"><a href="https://wg21.link/p2996r10" role="doc-biblioref">[P2996R10]</a></span>:</p>
<ul>
<li>replaced <code class="sourceCode cpp">has_complete_definition</code>
function with more narrow
<code class="sourceCode cpp">is_enumerable_type</code></li>
<li>core wording updates
<ul>
<li>disallow splicing constructors and destructors (inadvertently
removed between R7 and R8)</li>
<li>prevent dependent
<code class="sourceCode cpp"><em>splice-specifier</em></code>s from
appearing in CTAD (following CWG3003)</li>
<li>fixed parsing rules for a
<code class="sourceCode cpp"><em>reflect-expression</em></code> followed
by <code class="sourceCode cpp"><span class="op">&lt;</span></code></li>
<li>iterate on wording for overload resolution for
<code class="sourceCode cpp"><em>splice-expression</em></code> function
calls</li>
<li>disallow default arguments for splices ([over.match.viable])</li>
<li>added more core examples</li>
<li>rebase onto latest working draft (as of 2025-04-09)</li>
</ul></li>
<li>library wording updates
<ul>
<li>functions whose types contain placeholder types are not
<em>members-of-representable</em></li>
<li>fixed wording for <code class="sourceCode cpp">extract</code> and
<code class="sourceCode cpp">object_of</code> to ensure that both
functions can be used with reflections of local variables declared in
immediate functions</li>
<li>specified <code class="sourceCode cpp">type_of</code> for
enumerators called from within the containing
<code class="sourceCode cpp"><em>enum-specifier</em></code></li>
<li>minor editing and phrasing updates to address CWG feedback</li>
<li>added type traits from <span class="title"><span class="citation" data-cites="P2786R13"><a href="https://wg21.link/p2786r13" role="doc-biblioref">[P2786R13] (Trivial Relocatability For
C++26)</a></span></span></li>
<li>in response to CWG feedback: added
<code class="sourceCode cpp">has_c_language_linkage</code>,
<code class="sourceCode cpp">has_parent</code>,
<code class="sourceCode cpp">is_consteval_only</code></li>
<li>added
<code class="sourceCode cpp">scope<span class="op">()</span></code> and
<code class="sourceCode cpp">naming_class<span class="op">()</span></code>
members to <code class="sourceCode cpp">access_context</code></li>
<li>improve wording for <code class="sourceCode cpp">access_context<span class="op">::</span>current<span class="op">()</span></code>,
<code class="sourceCode cpp">is_accessible</code>,
<code class="sourceCode cpp">members_of</code></li>
</ul></li>
</ul>
<p>Since <span class="citation" data-cites="P2996R9"><a href="https://wg21.link/p2996r9" role="doc-biblioref">[P2996R9]</a></span>:</p>
<ul>
<li>core wording updates
<ul>
<li>merge <span class="title"><span class="citation" data-cites="P3289R1"><a href="https://wg21.link/p3289r1" role="doc-biblioref">[P3289R1] (Consteval blocks)</a></span></span> into
P2996. Replace the category of “plainly constant-evaluated expressions”
with consteval blocks.</li>
<li>make the [expr.const] “scope rule” for injected declarations more
rigorous; disallow escape from function parameter scopes</li>
<li>revise [expr.reflect] grammar according to CWG feedback</li>
<li>handle concept splicing in type constraints with template
arguments</li>
<li>bring notes and examples into line with current definitions</li>
<li>rebase [expr.const] onto latest from working draft (in particular,
integrate changes from <span class="citation" data-cites="P2686R5"><a href="https://wg21.link/p2686r5" role="doc-biblioref">[P2686R5]</a></span>)</li>
<li>prefer “core constant expressions” to “manifestly constant-evaluated
expression” in several places</li>
<li>producing an injected declaration from a non-plainly
constant-evaluated context is prohibited for core constant expressions,
rather than rendering the program ill-formed</li>
<li>do not specify <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code></li>
<li>removed concept splicers</li>
</ul></li>
<li>library wording updates
<ul>
<li>add <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
to [headers]</li>
<li>fix definition of “Constant When” (use “constant subexpression” in
lieu of “core constant expression”)</li>
<li>avoid referring to “permitted results of constant expressions” in
wording for <code class="sourceCode cpp">reflect_value</code> and
<code class="sourceCode cpp">reflect_object</code> (term was retired by
<span class="citation" data-cites="P2686R5"><a href="https://wg21.link/p2686r5" role="doc-biblioref">[P2686R5]</a></span>)</li>
<li>template specializations and non-static data members of closure
types are not <em>members-of-representable</em></li>
<li>integrated <span class="title"><span class="citation" data-cites="P3547R1"><a href="https://wg21.link/p3547r1" role="doc-biblioref">[P3547R1] (Modeling Access Control With
Reflection)</a></span></span> following its approval in (L)EWG.</li>
</ul></li>
</ul>
<p>Since <span class="citation" data-cites="P2996R8"><a href="https://wg21.link/p2996r8" role="doc-biblioref">[P2996R8]</a></span>:</p>
<ul>
<li>ensure <code class="sourceCode cpp">value_of</code> and
<code class="sourceCode cpp">extract</code> are usable with reflections
of local variables in consteval functions</li>
<li>specifically state that
<code class="sourceCode cpp">define_aggregate</code> cannot be used for
a class currently being defined</li>
<li><code class="sourceCode cpp">members_of<span class="op">(</span><em>closure-type</em><span class="op">)</span></code>
returns an unspecified sequence of reflections</li>
<li>introduced a strong ordering on evaluations during constant
evaluation</li>
<li>assertions of
<code class="sourceCode cpp"><em>static_assert-declaration</em></code>s
are not plainly constant-evaluated</li>
<li>core wording changes
<ul>
<li>classify the injection of a declaration as a side effect
([intro.execution]); remove the related IFNDR condition from
[expr.const].</li>
<li>rework [lex.phases]: refactor out the “semantically follows”
relation introduced in R7: define when a plainly constant-evaluated
expression is evaluated in terms of side effects and reachability.
Inline the “semantically sequenced” relation into the [expr.const]
conditions that render an injected declaration ill-formed.</li>
<li>improved [expr.const] examples demonstrating injected declaration
rules</li>
</ul></li>
<li>library wording changes
<ul>
<li>minor wording improvements to:
<code class="sourceCode cpp">type_of</code>,
<code class="sourceCode cpp">alignment_of</code>,
<code class="sourceCode cpp">bit_size_of</code>,
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_aggregate</code>, type traits</li>
<li>fix wording bug that prevents application of
<code class="sourceCode cpp">value_of</code> to a reflection of a local
variable in a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
function</li>
<li>clarify in note for <code class="sourceCode cpp">substitute</code>
that instantiation may be triggered if needed to deduce a placeholder
type</li>
<li>clarify which members of closure types are
<em>members-of-representable</em></li>
<li>fix wording bug in <em>members-of-reachable</em> related to
complete-class contexts; rename to “<em>members-of-precedes</em>”</li>
<li>remove idempotency from
<code class="sourceCode cpp">define_aggregate</code></li>
</ul></li>
<li>fleshed out revision history for R8</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R7"><a href="https://wg21.link/p2996r7" role="doc-biblioref">[P2996R7]</a></span>:</p>
<ul>
<li>changed reflection operator from
<code class="sourceCode cpp"><span class="op">^</span></code> to
<code class="sourceCode cpp"><span class="op">^^</span></code> following
adoption of <span class="citation" data-cites="P3381R0"><a href="https://wg21.link/p3381r0" role="doc-biblioref">[P3381R0]</a></span></li>
<li>renamed <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>operator_symbol_of</code>
to <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>symbol_of</code></li>
<li>renamed some <code class="sourceCode cpp">operators</code>
(<code class="sourceCode cpp">exclaim</code> -&gt;
<code class="sourceCode cpp">exclamation_mark</code>,
<code class="sourceCode cpp">three_way_comparison</code> -&gt;
<code class="sourceCode cpp">spaceship</code>, and
<code class="sourceCode cpp">ampersand_and</code> -&gt;
<code class="sourceCode cpp">ampersand_ampersand</code>)</li>
<li>renamed <code class="sourceCode cpp">define_class</code> to
<code class="sourceCode cpp">define_aggregate</code></li>
<li>removed <code class="sourceCode cpp">define_static_array</code>,
<code class="sourceCode cpp">define_static_string</code>, and
<code class="sourceCode cpp">reflect_invoke</code></li>
<li>clarified that <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span> <span class="op">==</span></code>sizeof(void
*)`</li>
<li>rename <code class="sourceCode cpp">data_member_options_t</code> to
<code class="sourceCode cpp">data_member_options</code>, as per LEWG
feedback</li>
<li>clarified that
<code class="sourceCode cpp">data_member_options</code> and
<code class="sourceCode cpp">name_type</code> are non-structural
consteval-only types</li>
<li>clarified that everything in
<code class="sourceCode cpp">std<span class="op">::</span>meta</code> is
addressable</li>
<li>renaming <code class="sourceCode cpp">member_offsets</code> to
<code class="sourceCode cpp">member_offset</code> and changing
<code class="sourceCode cpp">member_offset</code> members to be
<code class="sourceCode cpp"><span class="dt">ptrdiff_t</span></code>
instead of
<code class="sourceCode cpp"><span class="dt">size_t</span></code>, to
allow for future use with negative offsets</li>
<li>renamed the type traits from all being named
<code class="sourceCode cpp">type_meow</code> to a more bespoke naming
scheme.</li>
<li>changing signature of
<code class="sourceCode cpp">reflect_value</code> to take a <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
instead of a <code class="sourceCode cpp">T</code>.</li>
<li>added an <a href="#restrictions-on-injected-declarations">informal
section</a> explaining restrictions on injected declarations</li>
<li>removed <code class="sourceCode cpp">is_trivial_type</code>, since
the corresponding type trait was deprecated.</li>
<li>core wording changes
<ul>
<li>as per CWG feedback, merge phases 7 and 8 of [lex.phases]; get rid
of “instantiation units”. introduce “semantically sequenced” and
“semantically follows” relations to specify ordering of plainly
constant-evaluated expressions.</li>
<li>give type aliases and namespace aliases status as entities (note:
incurs many changes throughout wording); introduce the notion of an
“underlying entity”</li>
<li>audit for places where
<code class="sourceCode cpp"><em>id-expression</em></code> is specially
handled for which
<code class="sourceCode cpp"><em>splice-expression</em></code> should be
handled similarly</li>
<li>move splice specifiers into [basic.splice]; re-word all
splicers</li>
<li>lift template splicers out from
<code class="sourceCode cpp"><em>template-name</em></code> (i.e.,
introduce a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
parallel to
<code class="sourceCode cpp"><em>simple-template-id</em></code>)</li>
<li>add examples of the reflection operator to [basic.fundamental]</li>
<li>clarify that overload resolution is performed on splices of
functions</li>
<li>clarify parsing and semantic rules for [expr.reflect]</li>
<li>define special rules for consteval-only types in [expr.const]</li>
<li>restrict _plainly constant-evaluated expression_s to only
constexpr/constinit initializers and static-assert declarations</li>
<li>introduce an IFNDR condition to [expr.const] when injected
declarations are unsequenced or indeterminaly sequenced (note: removed
in R9)</li>
<li>NTTPs and pack-index-expressions cannot appear as operands of the
reflection operator</li>
<li>properly handle type splicers in CTAD and placeholder types</li>
<li>add a new [dcl.type.splice] section for type splicers</li>
<li>introduce notions of <em>data member description</em> and <em>direct
base class relationship</em> to assist with specification of
<code class="sourceCode cpp">data_member_spec</code> and
<code class="sourceCode cpp">bases_of</code></li>
<li>flesh out handling of
<code class="sourceCode cpp"><em>splice-template-argument</em></code>s
in [temp.arg.general]</li>
</ul></li>
</ul>
<p>Since <span class="citation" data-cites="P2996R6"><a href="https://wg21.link/p2996r6" role="doc-biblioref">[P2996R6]</a></span>:</p>
<ul>
<li>removed the <code class="sourceCode cpp">accessible_members</code>
family of functions</li>
<li>added the <code class="sourceCode cpp">get_public</code> family of
functions</li>
<li>added missing <code class="sourceCode cpp">tuple</code> and
<code class="sourceCode cpp">variant</code> traits</li>
<li>added missing <code class="sourceCode cpp">is_mutable_member</code>
function</li>
<li>added <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>operator_symbol_of</code>
functions, tweaked enumerator names in <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>operators</code></li>
<li>stronger guarantees on order reflections returned by
<code class="sourceCode cpp">members_of</code></li>
<li>several core wording fixes</li>
<li>added <code class="sourceCode cpp">is_user_declared</code> for
completeness with
<code class="sourceCode cpp">is_user_provided</code></li>
</ul>
<p>Since <span class="citation" data-cites="P2996R5"><a href="https://wg21.link/p2996r5" role="doc-biblioref">[P2996R5]</a></span>:</p>
<ul>
<li>fixed broken “Emulating typeful reflection” example.</li>
<li>removed linkage restrictions on objects of consteval-only type that
were introduced in St. Louis.</li>
<li>make friends with modules: define <em>injected declarations</em> and
<em>injected points</em>, as well as the <em>evaluation context</em>;
modify <em>TU-local</em> and related definitions, clarify behavior of
<code class="sourceCode cpp">members_of</code> and
<code class="sourceCode cpp">define_class</code>. An informal
elaboration on this is included in a new section on “Reachability and
injected declarations”.</li>
<li><code class="sourceCode cpp">type_of</code> no longer returns
reflections of
<code class="sourceCode cpp"><em>typedef-names</em></code>; added
elaboration of reasoning to the <a href="#handling-aliases">“Handling
Aliases”</a> section.</li>
<li>added <code class="sourceCode cpp">define_static_array</code>,
<code class="sourceCode cpp">has_complete_definition</code>.</li>
<li>removed <code class="sourceCode cpp">subobjects_of</code> and
<code class="sourceCode cpp">accessible_subobjects_of</code> (will be
reintroduced by <span class="citation" data-cites="P3293R1"><a href="https://wg21.link/p3293r1" role="doc-biblioref">[P3293R1]</a></span>).</li>
<li>specified constraints for
<code class="sourceCode cpp">enumerators_of</code> in terms of
<code class="sourceCode cpp">has_complete_definition</code>.</li>
<li>constraints on type template parameter of <code class="sourceCode cpp">reflect_<span class="op">{</span>value, object, function<span class="op">}</span></code>
are expressed as mandates.</li>
<li>changed <code class="sourceCode cpp">is_special_member</code> to
<code class="sourceCode cpp">is_special_member_function</code> to align
with core language terminology.</li>
<li>revised wording for several metafunctions (<code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>identifier_of</code>,
<code class="sourceCode cpp">has_identifier</code>,
<code class="sourceCode cpp">extract</code>,
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_class</code>,
<code class="sourceCode cpp">reflect_invoke</code>,
<code class="sourceCode cpp">source_location_of</code>).</li>
<li>more changes and additions to core language wording.</li>
<li>minor edits: “representing” instead of “reflecting”; “ordinary
<del>string</del> literal encoding”; prefer
“<code class="sourceCode cpp"><em>typedef-name</em></code>” over “alias
of a type” in formal wording.</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R4"><a href="https://wg21.link/p2996r4" role="doc-biblioref">[P2996R4]</a></span>:</p>
<ul>
<li>removed filters from query functions</li>
<li>cleaned up accessibility interface, removed
<code class="sourceCode cpp">access_pair</code> type, and redid API to
be based on an <code class="sourceCode cpp">access_context</code></li>
<li>reduced specification of
<code class="sourceCode cpp">is_noexcept</code></li>
<li>changed <code class="sourceCode cpp">span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;</span></code>
to <code class="sourceCode cpp">initializer_list<span class="op">&lt;</span>info<span class="op">&gt;</span></code></li>
<li>removed <code class="sourceCode cpp">test_trait</code></li>
<li>removed <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>name_of</code>
and <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>qualified_name_of</code>;
added <code class="sourceCode cpp"><span class="op">(</span>u8<span class="op">)</span>identifier_of</code>,
<code class="sourceCode cpp">operator_of</code>,
<code class="sourceCode cpp">define_static_string</code>.</li>
<li>renamed <code class="sourceCode cpp">display_name_of</code> to
<code class="sourceCode cpp">display_string_of</code></li>
<li>adding a number of missing predicates:
<code class="sourceCode cpp">is_enumerator</code>,
<code class="sourceCode cpp">is_copy_constructor</code>,
<code class="sourceCode cpp">is_move_constructor</code>,
<code class="sourceCode cpp">is_assignment</code>,
<code class="sourceCode cpp">is_move_assignment</code>,
<code class="sourceCode cpp">is_copy_assignment</code>,
<code class="sourceCode cpp">is_default_constructor</code>,
<code class="sourceCode cpp">has_default_member_initializer</code>,
<code class="sourceCode cpp">is_lvalue_reference_qualified</code>,
<code class="sourceCode cpp">is_rvalue_reference_qualified</code>, <code class="sourceCode cpp">is_literal_operator<span class="op">(</span>_template<span class="op">)</span></code>,
<code class="sourceCode cpp">is_conversion_function<span class="op">(</span>_template<span class="op">)</span></code>,
<code class="sourceCode cpp">is_operator<span class="op">(</span>_template<span class="op">)</span></code>,
<code class="sourceCode cpp">is_data_member_spec</code>, <code class="sourceCode cpp">has_<span class="op">(</span>thread<span class="op">|</span>automatic<span class="op">)</span>_storage_duration</code></li>
<li>changed offset API to be one function that returns a type with named
members</li>
<li>Tightened constraints on calls to
<code class="sourceCode cpp">data_member_spec</code>, and defined
comparison among reflections returned by it.</li>
<li>changed <code class="sourceCode cpp">is_alias</code> to <code class="sourceCode cpp">is_<span class="op">(</span>type<span class="op">|</span><span class="kw">namespace</span><span class="op">)</span>_alias</code></li>
<li>changed <code class="sourceCode cpp">is_incomplete_type</code> to
<code class="sourceCode cpp">is_complete_type</code></li>
<li>Many wording updates in response to feedback from CWG.</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R3"><a href="https://wg21.link/p2996r3" role="doc-biblioref">[P2996R3]</a></span>:</p>
<ul>
<li>changes to name functions to improve Unicode-friendliness; added
<code class="sourceCode cpp">u8name_of</code>,
<code class="sourceCode cpp">u8qualified_name_of</code>,
<code class="sourceCode cpp">u8display_name_of</code>.</li>
<li>the return of <code class="sourceCode cpp">reflect_value</code>:
separated <code class="sourceCode cpp">reflect_result</code> into three
functions: <code class="sourceCode cpp">reflect_value</code>,
<code class="sourceCode cpp">reflect_object</code>,
<code class="sourceCode cpp">reflect_function</code></li>
<li>more strongly specified comparison and linkage rules for reflections
of aliases</li>
<li>changed <code class="sourceCode cpp">is_noexcept</code> to apply to
a wider class of entities</li>
<li>reworked the API for reflecting on accessible class members</li>
<li>renamed <code class="sourceCode cpp">test_type</code> and
<code class="sourceCode cpp">test_types</code> to
<code class="sourceCode cpp">test_trait</code></li>
<li>added missing <code class="sourceCode cpp">has_module_linkage</code>
metafunction</li>
<li>clarified difference between a reflection of a variable and its
object; added <code class="sourceCode cpp">object_of</code>
metafunction</li>
<li>more wording</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R2"><a href="https://wg21.link/p2996r2" role="doc-biblioref">[P2996R2]</a></span>:</p>
<ul>
<li>many wording changes, additions, and improvements</li>
<li>elaborated on equivalence among reflections and linkage of templated
entities specialized by reflections</li>
<li>added <code class="sourceCode cpp">accessible_members_of</code>
variants to restore a TS-era agreement</li>
<li>renamed function previously called
<code class="sourceCode cpp">value_of</code> to
<code class="sourceCode cpp">extract</code>, and expanded it to operate
on functions</li>
<li>clarified support for reflections of values and objects rather than
constant expressions</li>
<li>added Godbolt links to Clang/P2996 implementation</li>
<li>added <code class="sourceCode cpp">can_substitute</code>,
<code class="sourceCode cpp">is_value</code>,
<code class="sourceCode cpp">is_object</code>, and (new)
<code class="sourceCode cpp">value_of</code></li>
<li>added explanation of a naming issue with the <a href="#other-type-traits">type traits</a></li>
<li>added an alternative <a href="#named-tuple">named tuple</a>
implementation</li>
<li>made default/value/zero-initializing a
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>
yield a null reflection</li>
<li>added addressed splicing, which is implemented but was omitted from
the paper</li>
<li>added another overload to
<code class="sourceCode cpp">reflect_invoke</code> to support template
arguments</li>
<li>renamed all the type traits to start with
<code class="sourceCode cpp">type_</code> to avoid name clashes. added
more generalized <code class="sourceCode cpp">is_const</code>,
<code class="sourceCode cpp">is_final</code>, and
<code class="sourceCode cpp">is_volatile</code></li>
<li>added <code class="sourceCode cpp">is_noexcept</code> and fixed
<code class="sourceCode cpp">is_explicit</code> to only apply to member
functions, not member function templates</li>
<li>added section on <a href="#reflecting-source-text">handling
text</a></li>
<li>added a section discussing ODR concerns</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R1"><a href="https://wg21.link/p2996r1" role="doc-biblioref">[P2996R1]</a></span>, several changes to the
overall library API:</p>
<ul>
<li>added <code class="sourceCode cpp">qualified_name_of</code> (to
partner with <code class="sourceCode cpp">name_of</code>)</li>
<li>removed <code class="sourceCode cpp">is_static</code> for being
ambiguous, added
<code class="sourceCode cpp">has_internal_linkage</code> (and
<code class="sourceCode cpp">has_linkage</code> and
<code class="sourceCode cpp">has_external_linkage</code>) and
<code class="sourceCode cpp">is_static_member</code> instead</li>
<li>added <code class="sourceCode cpp">is_class_member</code>,
<code class="sourceCode cpp">is_namespace_member</code>, and
<code class="sourceCode cpp">is_concept</code></li>
<li>added <code class="sourceCode cpp">reflect_invoke</code></li>
<li>added <a href="#other-type-traits">all the type traits</a></li>
</ul>
<p>Other paper changes:</p>
<ul>
<li>some updates to examples, including a new examples which add a <a href="#named-tuple">named tuple</a> and <a href="#emulating-typeful-reflection">emulate typeful
reflection</a>.</li>
<li>more discussion of syntax, constant evaluation order, aliases, and
freestanding.</li>
<li>adding lots of wording</li>
</ul>
<p>Since <span class="citation" data-cites="P2996R0"><a href="https://wg21.link/p2996r0" role="doc-biblioref">[P2996R0]</a></span>:</p>
<ul>
<li>added links to Compiler Explorer demonstrating just about all of the
examples</li>
<li>respecified <code class="sourceCode cpp">synth_struct</code> to
<code class="sourceCode cpp">define_class</code></li>
<li>respecified a few metafunctions to be functions instead of function
templates</li>
<li>introduced section on error handling mechanism and our preference
for exceptions (removing invalid reflections)</li>
<li>added ticket counter and variant examples</li>
<li>collapsed <code class="sourceCode cpp">entity_ref</code> and
<code class="sourceCode cpp">pointer_to_member</code> into
<code class="sourceCode cpp">value_of</code></li>
</ul>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">2</span>
Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This is a proposal for a reduced initial set of features to support
static reflection in C++. Specifically, we are mostly proposing a subset
of features suggested in <span class="citation" data-cites="P1240R2"><a href="https://wg21.link/p1240r2" role="doc-biblioref">[P1240R2]</a></span>:</p>
<ul>
<li>the representation of program elements via constant-expressions
producing <em>reflection values</em> — <em>reflections</em> for short —
of an opaque type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,</li>
<li>a <em>reflection operator</em> (prefix
<code class="sourceCode cpp"><span class="op">^^</span></code>) that
computes a reflection value for its operand construct,</li>
<li>a number of
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
<em>metafunctions</em> to work with reflections (including deriving
other reflections), and</li>
<li>constructs called <em>splicers</em> to produce grammatical elements
from reflections (e.g., <code class="sourceCode cpp"><span class="op">[:</span> <em>refl</em> <span class="op">:]</span></code>).</li>
</ul>
<p>(Note that this aims at something a little broader than pure
“reflection”. We not only want to observe the structure of the program:
We also want to ease generating code that depends on those observations.
That combination is sometimes referred to as “reflective
metaprogramming”, but within WG21 discussion the term “reflection” has
often been used informally to refer to the same general idea.)</p>
<p>This proposal is not intended to be the end-game as far as reflection
and compile-time metaprogramming are concerned. Instead, we expect it
will be a useful core around which more powerful features will be added
incrementally over time. In particular, we believe that most or all the
remaining features explored in P1240R2 and that code injection (along
the lines described in <span class="citation" data-cites="P2237R0"><a href="https://wg21.link/p2237r0" role="doc-biblioref">[P2237R0]</a></span>) are desirable directions to
pursue.</p>
<p>Our choice to start with something smaller is primarily motivated by
the belief that that improves the chances of these facilities making it
into the language sooner rather than later.</p>
<h2 data-number="2.1" id="notable-additions-to-p1240"><span class="header-section-number">2.1</span> Notable Additions to P1240<a href="#notable-additions-to-p1240" class="self-link"></a></h2>
<p>While we tried to select a useful subset of the P1240 features, we
also made a few additions and changes. Most of those changes are minor.
For example, we added a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>test_trait</code>
interface that makes it convenient to use existing standard type
predicates (such as <code class="sourceCode cpp">is_class_v</code>) in
reflection computations.</p>
<p>One addition does stand out, however: We have added metafunctions
that permit the synthesis of simple struct and union types. While it is
not nearly as powerful as generalized code injection (see <span class="citation" data-cites="P2237R0"><a href="https://wg21.link/p2237r0" role="doc-biblioref">[P2237R0]</a></span>), it can be remarkably
effective in practice.</p>
<h2 data-number="2.2" id="why-a-single-opaque-reflection-type"><span class="header-section-number">2.2</span> Why a single opaque reflection
type?<a href="#why-a-single-opaque-reflection-type" class="self-link"></a></h2>
<p>Perhaps the most common suggestion made regarding the framework
outlined in P1240 is to switch from the single <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
type to a family of types covering various language elements (e.g.,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>variable</code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type</code>,
etc.).</p>
<p>We believe that doing so would be a mistake with very serious
consequences for the future of C++.</p>
<p>Specifically, it would codify the language design into the type
system. We know from experience that it has been quasi-impossible to
change the semantics of standard types once they were standardized, and
there is no reason to think that such evolution would become easier in
the future. Suppose for example that we had standardized a reflection
type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>variable</code>
in C++03 to represent what the standard called “variables” at the time.
In C++11, the term “variable” was extended to include “references”. Such
an change would have been difficult to do given that C++ by then likely
would have had plenty of code that depended on a type arrangement around
the more restricted definition of “variable”. That scenario is clearly
backward-looking, but there is no reason to believe that similar changes
might not be wanted in the future and we strongly believe that it
behooves us to avoid adding undue constraints on the evolution of the
language.</p>
<p>Other advantages of a single opaque type include:</p>
<ul>
<li>it makes no assumptions about the representation used within the
implementation (e.g., it doesn’t advantage one compiler over
another),</li>
<li>it is trivially extensible (no types need to be added to represent
additional language elements and meta-elements as the language evolves),
and</li>
<li>it allows convenient collections of heterogeneous constructs without
having to surface reference semantics (e.g., a <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>
can easily represent a mixed template argument list — containing types
and nontypes — without fear of slicing values).</li>
</ul>
<h2 data-number="2.3" id="implementation-status"><span class="header-section-number">2.3</span> Implementation Status<a href="#implementation-status" class="self-link"></a></h2>
<p>Lock3 implemented the equivalent of much that is proposed here in a
fork of Clang (specifically, it worked with the P1240 proposal, but also
included several other capabilities including a first-class injection
mechanism).</p>
<p>EDG has an ongoing implementation of this proposal that is currently
available on Compiler Explorer (thank you, Matt Godbolt).</p>
<p>Additionally, Bloomberg has open sourced a fork of Clang which
provides a second implementation of this proposal, also available on
Compiler Explorer (again thank you, Matt Godbolt), which can be found
here: <a href="https://github.com/bloomberg/clang-p2996">https://github.com/bloomberg/clang-p2996</a>.</p>
<p>Neither implementation is complete, but all significant features
proposed by this paper have been implemented by at least one
implementation (including namespace and template splicers). Both
implementations have their “quirks” and continue to evolve alongside
this paper.</p>
<p>Nearly all of the examples below have links to Compiler Explorer
demonstrating them in both EDG and Clang.</p>
<p>The implementations notably lack some of the other proposed language
features that dovetail well with reflection; most notably, expansion
statements are absent. A workaround that will be used in the linked
implementations of examples is the following facility:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> __impl <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span><span class="op">...</span> vals<span class="op">&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> replicator_type <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">void</span> <span class="kw">operator</span><span class="op">&gt;&gt;(</span>F body<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span>body<span class="op">.</span><span class="kw">template</span> <span class="kw">operator</span><span class="op">()&lt;</span>vals<span class="op">&gt;()</span>, <span class="op">...)</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span><span class="op">...</span> vals<span class="op">&gt;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  replicator_type<span class="op">&lt;</span>vals<span class="op">...&gt;</span> replicator <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> expand<span class="op">(</span>R range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  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> args;</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> r <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    args<span class="op">.</span>push_back<span class="op">(</span>reflect_constant<span class="op">(</span>r<span class="op">))</span>;</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> substitute<span class="op">(^^</span>__impl<span class="op">::</span>replicator, args<span class="op">)</span>;</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Used like:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>With expansion statements</strong>
</div></th>
<th><div style="text-align:center">
<strong>With <code class="sourceCode cpp">expand</code>
workaround</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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> E<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>is_enum_v<span class="op">&lt;</span>E<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string enum_to_string<span class="op">(</span>E value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> e <span class="op">:</span> std<span class="op">::</span>meta<span class="op">::</span>enumerators_of<span class="op">(^^</span>E<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">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="op">[:</span>e<span class="op">:])</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>string<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(</span>e<span class="op">))</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</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>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span>;</span>
<span id="cb2-11"><a href="#cb2-11" 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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> E<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>is_enum_v<span class="op">&lt;</span>E<span class="op">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string enum_to_string<span class="op">(</span>E value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string result <span class="op">=</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">[:</span>expand<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>enumerators_of<span class="op">(^^</span>E<span class="op">)):]</span> <span class="op">&gt;&gt;</span> <span class="op">[&amp;]&lt;</span><span class="kw">auto</span> e<span class="op">&gt;{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="op">[:</span>e<span class="op">:])</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>      result <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(</span>e<span class="op">)</span>;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> result;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="examples"><span class="header-section-number">3</span> Examples<a href="#examples" class="self-link"></a></h1>
<p>We start with a number of examples that show off what is possible
with the proposed set of features. It is expected that these are mostly
self-explanatory. Read ahead to the next sections for a more systematic
description of each element of this proposal.</p>
<p>A number of our examples here show a few other language features that
we hope to progress at the same time. This facility does not strictly
rely on these features, and it is possible to do without them - but it
would greatly help the usability experience if those could be adopted as
well:</p>
<ul>
<li><span class="title"><span class="citation" data-cites="P1306R2"><a href="https://wg21.link/p1306r2" role="doc-biblioref">[P1306R2]
(Expansion statements)</a></span></span></li>
<li><span class="title"><span class="citation" data-cites="P3289R1"><a href="https://wg21.link/p3289r1" role="doc-biblioref">[P3289R1]
(Consteval blocks)</a></span></span></li>
<li>non-transient constexpr allocation – <span class="title"><span class="citation" data-cites="P0784R7"><a href="https://wg21.link/p0784r7" role="doc-biblioref">[P0784R7] (More
constexpr containers)</a></span></span>, <span class="title"><span class="citation" data-cites="P1974R0"><a href="https://wg21.link/p1974r0" role="doc-biblioref">[P1974R0]
(Non-transient constexpr allocation using propconst)</a></span></span>,
<span class="title"><span class="citation" data-cites="P2670R1"><a href="https://wg21.link/p2670r1" role="doc-biblioref">[P2670R1]
(Non-transient constexpr allocation)</a></span></span>, <span class="title"><span class="citation" data-cites="P3554R0"><a href="https://wg21.link/p3554r0" role="doc-biblioref">[P3554R0]
(Non-transient allocation with vector and
basic_string)</a></span></span></li>
</ul>
<h2 data-number="3.1" id="back-and-forth"><span class="header-section-number">3.1</span> Back-And-Forth<a href="#back-and-forth" class="self-link"></a></h2>
<p>Our first example is not meant to be compelling but to show how to go
back and forth between the reflection domain and the grammatical
domain:</p>
<div class="std">
<blockquote>
<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="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^^</span><span class="dt">int</span>;</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">typename</span><span class="op">[:</span>r<span class="op">:]</span> x <span class="op">=</span> <span class="dv">42</span>;       <span class="co">// Same as: int x = 42;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">typename</span><span class="op">[:^^</span><span class="dt">char</span><span class="op">:]</span> c <span class="op">=</span> <span class="ch">&#39;*&#39;</span>;  <span class="co">// Same as: char c = &#39;*&#39;;</span></span></code></pre></div>
</blockquote>
</div>
<p>The
<code class="sourceCode cpp"><span class="kw">typename</span></code>
prefix can be omitted in the same contexts as with dependent qualified
names (i.e., in what the standard calls <em>type-only contexts</em>).
For example:</p>
<div class="std">
<blockquote>
<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="kw">using</span> MyType <span class="op">=</span> <span class="op">[:</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)&lt;</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">long</span><span class="op">)?</span> <span class="op">^^</span><span class="dt">long</span> <span class="op">:</span> <span class="op">^^</span><span class="dt">int</span><span class="op">:]</span>;  <span class="co">// Implicit &quot;typename&quot; prefix.</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/4hK564scs">EDG</a>, <a href="https://godbolt.org/z/71647q5Mo">Clang</a>.</p>
<h2 data-number="3.2" id="selecting-members"><span class="header-section-number">3.2</span> Selecting Members<a href="#selecting-members" class="self-link"></a></h2>
<p>Our second example enables selecting a member “by number” for a
specific type:</p>
<div class="std">
<blockquote>
<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">struct</span> S <span class="op">{</span> <span class="dt">unsigned</span> i<span class="op">:</span><span class="dv">2</span>, j<span class="op">:</span><span class="dv">6</span>; <span class="op">}</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> member_number<span class="op">(</span><span class="dt">int</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="cf">return</span> <span class="op">^^</span>S<span class="op">::</span>i;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>n <span class="op">==</span> <span class="dv">1</span><span class="op">)</span> <span class="cf">return</span> <span class="op">^^</span>S<span class="op">::</span>j;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  S s<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">}</span>;</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_number<span class="op">(</span><span class="dv">1</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">42</span>;  <span class="co">// Same as: s.j = 42;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_number<span class="op">(</span><span class="dv">5</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">0</span>;   <span class="co">// Error (member_number(5) is not a constant).</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This example also illustrates that bit fields are not beyond the
reach of this proposal.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/cKaK4v8nr">EDG</a>, <a href="https://godbolt.org/z/Tb57jEn8a">Clang</a>.</p>
<p>Note that a “member access splice” like <code class="sourceCode cpp">s<span class="op">.[:</span>member_number<span class="op">(</span><span class="dv">1</span><span class="op">):]</span></code>
is a more direct member access mechanism than the traditional syntax. It
doesn’t involve member name lookup, access checking, or — if the spliced
reflection value represents a member function — overload resolution.</p>
<p>This proposal includes a number of consteval “metafunctions” that
enable the introspection of various language constructs. Among those
metafunctions is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of</code>
which returns a vector of reflection values that describe the non-static
members of a given type. We could thus rewrite the above example as:</p>
<div class="std">
<blockquote>
<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="kw">struct</span> S <span class="op">{</span> <span class="dt">unsigned</span> i<span class="op">:</span><span class="dv">2</span>, j<span class="op">:</span><span class="dv">6</span>; <span class="op">}</span>;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> member_number<span class="op">(</span><span class="dt">int</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of<span class="op">(^^</span>S, ctx<span class="op">)[</span>n<span class="op">]</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  S s<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">}</span>;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_number<span class="op">(</span><span class="dv">1</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">42</span>;  <span class="co">// Same as: s.j = 42;</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_number<span class="op">(</span><span class="dv">5</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">0</span>;   <span class="co">// Error (member_number(5) is not a constant).</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/7P3ax5K16">EDG</a>, <a href="https://godbolt.org/z/naTTzGebr">Clang</a>.</p>
<p>This proposal specifies that namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code> is
associated with the reflection type (<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>);
the <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span></code>
qualification can therefore be omitted in the example above.</p>
<p>Another frequently-useful metafunction is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>identifier_of</code>,
which returns a <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>
describing the identifier with which an entity represented by a given
reflection value was declared. With such a facility, we could
conceivably access non-static data members “by string”:</p>
<div class="std">
<blockquote>
<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="kw">struct</span> S <span class="op">{</span> <span class="dt">unsigned</span> i<span class="op">:</span><span class="dv">2</span>, j<span class="op">:</span><span class="dv">6</span>; <span class="op">}</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> member_named<span class="op">(</span>std<span class="op">::</span>string_view name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info field <span class="op">:</span> nonstatic_data_members_of<span class="op">(^^</span>S, ctx<span class="op">))</span> <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>has_identifier<span class="op">(</span>field<span class="op">)</span> <span class="op">&amp;&amp;</span> identifier_of<span class="op">(</span>field<span class="op">)</span> <span class="op">==</span> name<span class="op">)</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> field;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>  S s<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">}</span>;</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_named<span class="op">(</span><span class="st">&quot;j&quot;</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">42</span>;  <span class="co">// Same as: s.j = 42;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  s<span class="op">.[:</span>member_named<span class="op">(</span><span class="st">&quot;x&quot;</span><span class="op">):]</span> <span class="op">=</span> <span class="dv">0</span>;   <span class="co">// Error (member_named(&quot;x&quot;) is not a constant).</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/hhd9vePW7">EDG</a>, <a href="https://godbolt.org/z/q3c55jsKE">Clang</a>.</p>
<h2 data-number="3.3" id="list-of-types-to-list-of-sizes"><span class="header-section-number">3.3</span> List of Types to List of
Sizes<a href="#list-of-types-to-list-of-sizes" class="self-link"></a></h2>
<p>Here, <code class="sourceCode cpp">sizes</code> will be a <code class="sourceCode cpp">std<span class="op">::</span>array<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="dv">3</span><span class="op">&gt;</span></code>
initialized with <code class="sourceCode cpp"><span class="op">{</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span>, <span class="kw">sizeof</span><span class="op">(</span><span class="dt">float</span><span class="op">)</span>, <span class="kw">sizeof</span><span class="op">(</span><span class="dt">double</span><span class="op">)}</span></code>:</p>
<div class="std">
<blockquote>
<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="kw">constexpr</span> std<span class="op">::</span>array types <span class="op">=</span> <span class="op">{^^</span><span class="dt">int</span>, <span class="op">^^</span><span class="dt">float</span>, <span class="op">^^</span><span class="dt">double</span><span class="op">}</span>;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>array sizes <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, types<span class="op">.</span>size<span class="op">()&gt;</span> r;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>transform<span class="op">(</span>types, r<span class="op">.</span>begin<span class="op">()</span>, std<span class="op">::</span>meta<span class="op">::</span>size_of<span class="op">)</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> r;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Compare this to the following type-based approach, which produces the
same array <code class="sourceCode cpp">sizes</code>:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">struct</span> list <span class="op">{}</span>;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> types <span class="op">=</span> list<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">float</span>, <span class="dt">double</span><span class="op">&gt;</span>;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> sizes <span class="op">=</span> <span class="op">[]&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> L, <span class="kw">class</span><span class="op">...</span> T<span class="op">&gt;(</span>L<span class="op">&lt;</span>T<span class="op">...&gt;)</span> <span class="op">{</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>array<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>T<span class="op">)&gt;{{</span> <span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)...</span> <span class="op">}}</span>;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="op">}(</span>types<span class="op">{})</span>;</span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/83zK4erj7">EDG</a>, <a href="https://godbolt.org/z/raa87vMjf">Clang</a>.</p>
<h2 data-number="3.4" id="implementing-make_integer_sequence"><span class="header-section-number">3.4</span> Implementing
<code class="sourceCode cpp">make_integer_sequence</code><a href="#implementing-make_integer_sequence" class="self-link"></a></h2>
<p>We can provide a better implementation of
<code class="sourceCode cpp">make_integer_sequence</code> than a
hand-rolled approach using regular template metaprogramming (although
standard libraries today rely on an intrinsic for this):</p>
<div class="std">
<blockquote>
<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="pp">#include </span><span class="im">&lt;utility&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;vector&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-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="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info make_integer_seq_refl<span class="op">(</span>T N<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector args<span class="op">{^^</span>T<span class="op">}</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span>T k <span class="op">=</span> <span class="dv">0</span>; k <span class="op">&lt;</span> N; <span class="op">++</span>k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    args<span class="op">.</span>push_back<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span>k<span class="op">))</span>;</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> substitute<span class="op">(^^</span>std<span class="op">::</span>integer_sequence, args<span class="op">)</span>;</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, T N<span class="op">&gt;</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> make_integer_sequence <span class="op">=</span> <span class="op">[:</span>make_integer_seq_refl<span class="op">&lt;</span>T<span class="op">&gt;(</span>N<span class="op">):]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/G3TM9Tbad">EDG</a>, <a href="https://godbolt.org/z/57bcYqbv8">Clang</a>.</p>
<p>Note that the memoization implicit in the template substitution
process still applies. So having multiple uses of, e.g., <code class="sourceCode cpp">make_integer_sequence<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">20</span><span class="op">&gt;</span></code>
will only involve one evaluation of <code class="sourceCode cpp">make_integer_seq_refl<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span><span class="dv">20</span><span class="op">)</span></code>.</p>
<h2 data-number="3.5" id="getting-class-layout"><span class="header-section-number">3.5</span> Getting Class Layout<a href="#getting-class-layout" class="self-link"></a></h2>
<div class="std">
<blockquote>
<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">struct</span> member_descriptor</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span><span class="dt">size_t</span> offset;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span><span class="dt">size_t</span> size;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="co">// returns std::array&lt;member_descriptor, N&gt;</span></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> S<span class="op">&gt;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> get_layout<span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">size_t</span> N <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of<span class="op">(^^</span>S, ctx<span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> members <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of<span class="op">(^^</span>S, ctx<span class="op">)</span>;</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array<span class="op">&lt;</span>member_descriptor, N<span class="op">&gt;</span> layout;</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> members<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>      layout<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>          <span class="op">.</span>offset<span class="op">=</span><span class="kw">static_cast</span><span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">&gt;(</span>std<span class="op">::</span>meta<span class="op">::</span>offset_of<span class="op">(</span>members<span class="op">[</span>i<span class="op">]).</span>bytes<span class="op">)</span>,</span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>          <span class="op">.</span>size<span class="op">=</span>std<span class="op">::</span>meta<span class="op">::</span>size_of<span class="op">(</span>members<span class="op">[</span>i<span class="op">])</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span>;</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> layout;</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X</span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> a;</span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> b;</span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>    <span class="dt">double</span> c;</span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a><span class="co">/*constexpr*/</span> <span class="kw">auto</span> Xd <span class="op">=</span> get_layout<span class="op">&lt;</span>X<span class="op">&gt;()</span>;</span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a><span class="co">/*</span></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a><span class="co">where Xd would be std::array&lt;member_descriptor, 3&gt;{{</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a><span class="co">  { 0, 1 }, { 4, 4 }, { 8, 8 }</span></span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true" tabindex="-1"></a><span class="co">}}</span></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true" tabindex="-1"></a><span class="co">*/</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/ss9hfaMKT">EDG</a>, <a href="https://godbolt.org/z/doe83nGze">Clang</a>.</p>
<h2 data-number="3.6" id="enum-to-string"><span class="header-section-number">3.6</span> Enum to String<a href="#enum-to-string" class="self-link"></a></h2>
<p>One of the most commonly requested facilities is to convert an enum
value to a string (this example relies on expansion statements):</p>
<div class="std">
<blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">typename</span> E, <span class="dt">bool</span> Enumerable <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>is_enumerable_type<span class="op">(^^</span>E<span class="op">)&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>is_enum_v<span class="op">&lt;</span>E<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string_view enum_to_string<span class="op">(</span>E value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>Enumerable<span class="op">)</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> e <span class="op">:</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>                  std<span class="op">::</span>define_static_array<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>enumerators_of<span class="op">(^^</span>E<span class="op">)))</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="op">[:</span>e<span class="op">:])</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(</span>e<span class="op">)</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span>;</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">enum</span> Color <span class="op">:</span> <span class="dt">int</span>;</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>enum_to_string<span class="op">(</span>Color<span class="op">(</span><span class="dv">0</span><span class="op">))</span> <span class="op">==</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span><span class="op">)</span>;</span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Color 0: {}&quot;</span>, enum_to_string<span class="op">(</span>Color<span class="op">(</span><span class="dv">0</span><span class="op">)))</span>;  <span class="co">// prints &#39;&lt;unnamed&gt;&#39;</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">enum</span> Color <span class="op">:</span> <span class="dt">int</span> <span class="op">{</span> red, green, blue <span class="op">}</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>enum_to_string<span class="op">(</span>Color<span class="op">::</span>red<span class="op">)</span> <span class="op">==</span> <span class="st">&quot;red&quot;</span><span class="op">)</span>;</span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>enum_to_string<span class="op">(</span>Color<span class="op">(</span><span class="dv">42</span><span class="op">))</span> <span class="op">==</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span><span class="op">)</span>;</span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Color 0: {}&quot;</span>, enum_to_string<span class="op">(</span>Color<span class="op">(</span><span class="dv">0</span><span class="op">)))</span>;  <span class="co">// prints &#39;red&#39;</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We can also do the reverse in pretty much the same way:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> E, <span class="dt">bool</span> Enumerable <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>is_enumerable_type<span class="op">(^^</span>E<span class="op">)&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>is_enum_v<span class="op">&lt;</span>E<span class="op">&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>optional<span class="op">&lt;</span>E<span class="op">&gt;</span> string_to_enum<span class="op">(</span>std<span class="op">::</span>string_view name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>Enumerable<span class="op">)</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> e <span class="op">:</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>                  std<span class="op">::</span>define_static_array<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>enumerators_of<span class="op">(^^</span>E<span class="op">)))</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>name <span class="op">==</span> std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(</span>e<span class="op">))</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">[:</span>e<span class="op">:]</span>;</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>nullopt;</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>But we don’t have to use expansion statements - we can also use
algorithms. For instance,
<code class="sourceCode cpp">enum_to_string</code> can also be
implemented this way (this example relies on non-transient constexpr
allocation), which also demonstrates choosing a different algorithm
based on the number of enumerators:</p>
<div class="std">
<blockquote>
<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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> E<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>is_enum_v<span class="op">&lt;</span>E<span class="op">&gt;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>string enum_to_string<span class="op">(</span>E value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> get_pairs <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>enumerators_of<span class="op">(^^</span>E<span class="op">)</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>      <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span>std<span class="op">::</span>meta<span class="op">::</span>info e<span class="op">){</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>          <span class="cf">return</span> std<span class="op">::</span>pair<span class="op">&lt;</span>E, std<span class="op">::</span>string<span class="op">&gt;(</span>std<span class="op">::</span>meta<span class="op">::</span>extract<span class="op">&lt;</span>E<span class="op">&gt;(</span>e<span class="op">)</span>, std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(</span>e<span class="op">))</span>;</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> get_name <span class="op">=</span> <span class="op">[](</span>E value<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>optional<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>enumerators_of<span class="op">(^^</span>E<span class="op">).</span>size<span class="op">()</span> <span class="op">&lt;=</span> <span class="dv">7</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>      <span class="co">// if there aren&#39;t many enumerators, use a vector with find_if()</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> enumerators <span class="op">=</span> get_pairs<span class="op">()</span> <span class="op">|</span> std<span class="op">::</span>ranges<span class="op">::</span>to<span class="op">&lt;</span>std<span class="op">::</span>vector<span class="op">&gt;()</span>;</span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> it <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>find_if<span class="op">(</span>enumerators, <span class="op">[</span>value<span class="op">](</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> pr<span class="op">){</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> pr<span class="op">.</span>first <span class="op">==</span> value;</span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>      <span class="op">})</span>;</span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>it <span class="op">==</span> enumerators<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> std<span class="op">::</span>nullopt;</span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> it<span class="op">-&gt;</span>second;</span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>      <span class="co">// if there are lots of enumerators, use a map with find()</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> enumerators <span class="op">=</span> get_pairs<span class="op">()</span> <span class="op">|</span> std<span class="op">::</span>ranges<span class="op">::</span>to<span class="op">&lt;</span>std<span class="op">::</span>map<span class="op">&gt;()</span>;</span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> it <span class="op">=</span> enumerators<span class="op">.</span>find<span class="op">(</span>value<span class="op">)</span>;</span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>it <span class="op">==</span> enumerators<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> std<span class="op">::</span>nullopt;</span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> it<span class="op">-&gt;</span>second;</span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> get_name<span class="op">(</span>value<span class="op">).</span>value_or<span class="op">(</span><span class="st">&quot;&lt;unnamed&gt;&quot;</span><span class="op">)</span>;</span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Note that this last version has lower complexity: While the versions
using an expansion statement use an expected O(N) number of comparisons
to find the matching entry, a
<code class="sourceCode cpp">std<span class="op">::</span>map</code>
achieves the same with O(log(N)) complexity (where N is the number of
enumerator constants).</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/hf777PfGo">EDG</a>, <a href="https://godbolt.org/z/TTxMs4fMa">Clang</a>.</p>
<p>Many many variations of these functions are possible and beneficial
depending on the needs of the client code. For example:</p>
<ul>
<li>the “&lt;unnamed&gt;” case could instead output a valid cast
expression like “E(5)”</li>
<li>a more sophisticated lookup algorithm could be selected at compile
time depending on the length of <code class="sourceCode cpp">enumerators_of<span class="op">(^^</span>E<span class="op">)</span></code></li>
<li>a compact two-way persistent data structure could be generated to
support both <code class="sourceCode cpp">enum_to_string</code> and
<code class="sourceCode cpp">string_to_enum</code> with a minimal
footprint</li>
<li>etc.</li>
</ul>
<h2 data-number="3.7" id="parsing-command-line-options"><span class="header-section-number">3.7</span> Parsing Command-Line Options<a href="#parsing-command-line-options" class="self-link"></a></h2>
<p>Our next example shows how a command-line option parser could work by
automatically inferring flags based on member names. A real command-line
parser would of course be more complex, this is just the beginning.</p>
<div class="std">
<blockquote>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Opts<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> parse_options<span class="op">(</span>std<span class="op">::</span>span<span class="op">&lt;</span>std<span class="op">::</span>string_view <span class="kw">const</span><span class="op">&gt;</span> args<span class="op">)</span> <span class="op">-&gt;</span> Opts <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  Opts opts;</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> dm <span class="op">:</span> nonstatic_data_members_of<span class="op">(^^</span>Opts, ctx<span class="op">))</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> it <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>find_if<span class="op">(</span>args,</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">[](</span>std<span class="op">::</span>string_view arg<span class="op">){</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> arg<span class="op">.</span>starts_with<span class="op">(</span><span class="st">&quot;--&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> arg<span class="op">.</span>substr<span class="op">(</span><span class="dv">2</span><span class="op">)</span> <span class="op">==</span> identifier_of<span class="op">(</span>dm<span class="op">)</span>;</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>      <span class="op">})</span>;</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>it <span class="op">==</span> args<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>      <span class="co">// no option provided, use default</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">continue</span>;</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>it <span class="op">+</span> <span class="dv">1</span> <span class="op">==</span> args<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>print<span class="op">(</span>stderr, <span class="st">&quot;Option {} is missing a value</span><span class="sc">\n</span><span class="st">&quot;</span>, <span class="op">*</span>it<span class="op">)</span>;</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>exit<span class="op">(</span>EXIT_FAILURE<span class="op">)</span>;</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> T <span class="op">=</span> <span class="kw">typename</span><span class="op">[:</span>type_of<span class="op">(</span>dm<span class="op">):]</span>;</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> iss <span class="op">=</span> std<span class="op">::</span>ispanstream<span class="op">(</span>it<span class="op">[</span><span class="dv">1</span><span class="op">])</span>;</span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>iss <span class="op">&gt;&gt;</span> opts<span class="op">.[:</span>dm<span class="op">:]</span>; <span class="op">!</span>iss<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>print<span class="op">(</span>stderr, <span class="st">&quot;Failed to parse option {} into a {}</span><span class="sc">\n</span><span class="st">&quot;</span>, <span class="op">*</span>it, display_string_of<span class="op">(^^</span>T<span class="op">))</span>;</span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>exit<span class="op">(</span>EXIT_FAILURE<span class="op">)</span>;</span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> opts;</span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> MyOpts <span class="op">{</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string file_name <span class="op">=</span> <span class="st">&quot;input.txt&quot;</span>;  <span class="co">// Option &quot;--file_name &lt;string&gt;&quot;</span></span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span>    count <span class="op">=</span> <span class="dv">1</span>;                     <span class="co">// Option &quot;--count &lt;int&gt;&quot;</span></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc, <span class="dt">char</span> <span class="op">*</span>argv<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a>  MyOpts opts <span class="op">=</span> parse_options<span class="op">&lt;</span>MyOpts<span class="op">&gt;(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string_view<span class="op">&gt;(</span>argv<span class="op">+</span><span class="dv">1</span>, argv<span class="op">+</span>argc<span class="op">))</span>;</span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This example is based on a presentation by Matúš Chochlík.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/jGfGv84oh">EDG</a>, <a href="https://godbolt.org/z/5rYqnYWq4">Clang</a>.</p>
<h2 data-number="3.8" id="a-simple-tuple-type"><span class="header-section-number">3.8</span> A Simple Tuple Type<a href="#a-simple-tuple-type" class="self-link"></a></h2>
<div class="std">
<blockquote>
<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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" 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 class="kw">struct</span> Tuple <span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> storage;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(^^</span>storage, <span class="op">{</span>data_member_spec<span class="op">(^^</span>Ts<span class="op">)...})</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>  storage data;</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>  Tuple<span class="op">():</span> data<span class="op">{}</span> <span class="op">{}</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>  Tuple<span class="op">(</span>Ts <span class="kw">const</span><span class="op">&amp;</span> <span class="op">...</span>vs<span class="op">):</span> data<span class="op">{</span> vs<span class="op">...</span> <span class="op">}</span> <span class="op">{}</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-14"><a href="#cb17-14" 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="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> std<span class="op">::</span>tuple_size<span class="op">&lt;</span>Tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;:</span> <span class="kw">public</span> integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;</span> <span class="op">{}</span>;</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-17"><a href="#cb17-17" 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="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> std<span class="op">::</span>tuple_element<span class="op">&lt;</span>I, Tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> std<span class="op">::</span>array types <span class="op">=</span> <span class="op">{^^</span>Ts<span class="op">...}</span>;</span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> <span class="op">[:</span> types<span class="op">[</span>I<span class="op">]</span> <span class="op">:]</span>;</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info get_nth_field<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r, std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> nonstatic_data_members_of<span class="op">(</span>r, std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">())[</span>n<span class="op">]</span>;</span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-27"><a href="#cb17-27" 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="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> get<span class="op">(</span>Tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span> <span class="op">&amp;</span>t<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> std<span class="op">::</span>tuple_element_t<span class="op">&lt;</span>I, Tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;&amp;</span> <span class="op">{</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> t<span class="op">.</span>data<span class="op">.[:</span>get_nth_field<span class="op">(^^</span><span class="kw">decltype</span><span class="op">(</span>t<span class="op">.</span>data<span class="op">)</span>, I<span class="op">):]</span>;</span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a><span class="co">// Similarly for other value categories...</span></span></code></pre></div>
</blockquote>
</div>
<p>This example uses a “magic” <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_aggregate</code>
template along with member reflection through the
<code class="sourceCode cpp">nonstatic_data_members_of</code>
metafunction to implement a
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>-like
type without the usual complex and costly template metaprogramming
tricks that that involves when these facilities are not available.
<code class="sourceCode cpp">define_aggregate</code> takes a reflection
for an incomplete class or union plus a vector of non-static data member
descriptions, and completes the give class or union type to have the
described members.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/76EojjcEe">EDG</a>, <a href="https://godbolt.org/z/E9hxqKzE9">Clang</a>.</p>
<h2 data-number="3.9" id="a-simple-variant-type"><span class="header-section-number">3.9</span> A Simple Variant Type<a href="#a-simple-variant-type" class="self-link"></a></h2>
<p>Similarly to how we can implement a tuple using
<code class="sourceCode cpp">define_aggregate</code> to create on the
fly a type with one member for each
<code class="sourceCode cpp">Ts<span class="op">...</span></code>, we
can implement a variant that simply defines a
<code class="sourceCode cpp"><span class="kw">union</span></code>
instead of a
<code class="sourceCode cpp"><span class="kw">struct</span></code>. One
difference here is how the destructor of a
<code class="sourceCode cpp"><span class="kw">union</span></code> is
currently defined:</p>
<div class="std">
<blockquote>
<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><span class="kw">union</span> U1 <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> c;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U2 <span class="op">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string s;</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p><code class="sourceCode cpp">U1</code> has a trivial destructor, but
<code class="sourceCode cpp">U2</code>’s destructor is defined as
deleted (because
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
has a non-trivial destructor). This is a problem because we need to
define this thing… somehow. However, for the purposes of
<code class="sourceCode cpp">define_aggregate</code>, there really is
only one reasonable option to choose here:</p>
<div class="std">
<blockquote>
<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">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// all of our members</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  Ts<span class="op">...</span> members;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// a defaulted destructor if all of the types are trivially destructible</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="op">~</span>U<span class="op">()</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... otherwise a destructor that does nothing</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="op">~</span>U<span class="op">()</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If we make <a href="#data_member_spec-define_aggregate"><code class="sourceCode cpp">define_aggregate</code></a>
for a <code class="sourceCode cpp"><span class="kw">union</span></code>
have this behavior, then we can implement a
<code class="sourceCode cpp">variant</code> in a much more
straightforward way than in current implementations. This is not a
complete implementation of
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>
(and cheats using libstdc++ internals, and also uses Boost.Mp11’s
<code class="sourceCode cpp">mp_with_index</code>) but should
demonstrate the idea:</p>
<div class="std">
<blockquote>
<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="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="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Variant <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> Storage;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Empty <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>      define_aggregate<span class="op">(^^</span>Storage, <span class="op">{</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>          data_member_spec<span class="op">(^^</span>Empty, <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;empty&quot;</span><span class="op">})</span>,</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>          data_member_spec<span class="op">(^^</span>Ts<span class="op">)...</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>      <span class="op">})</span>;</span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info get_nth_field<span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> nonstatic_data_members_of<span class="op">(^^</span>Storage, ctx<span class="op">)[</span>n<span class="op">+</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>    Storage storage_;</span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> index_ <span class="op">=</span> <span class="op">-</span><span class="dv">1</span>;</span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>    <span class="co">// cheat: use libstdc++&#39;s implementation</span></span>
<span id="cb20-22"><a href="#cb20-22" 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="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> accepted_index <span class="op">=</span> std<span class="op">::</span>__detail<span class="op">::</span>__variant<span class="op">::</span>__accepted_index<span class="op">&lt;</span>T, std<span class="op">::</span>variant<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span>;</span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F<span class="op">&gt;</span></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> with_index<span class="op">(</span>F<span class="op">&amp;&amp;</span> f<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> mp_with_index<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;(</span>index_, <span class="op">(</span>F<span class="op">&amp;&amp;)</span>f<span class="op">)</span>;</span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Variant<span class="op">()</span> <span class="kw">requires</span> std<span class="op">::</span>is_default_constructible_v<span class="op">&lt;</span>Ts<span class="op">...[</span><span class="dv">0</span><span class="op">]&gt;</span></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>        <span class="co">// should this work: storage_{. [: get_nth_field(0) :]{} }</span></span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>construct_at<span class="op">(&amp;</span>storage_<span class="op">.[:</span> get_nth_field<span class="op">(</span><span class="dv">0</span><span class="op">)</span> <span class="op">:])</span>;</span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-39"><a href="#cb20-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="op">~</span>Variant<span class="op">()</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="kw">and</span> <span class="op">...)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-40"><a href="#cb20-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="op">~</span>Variant<span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>index_ <span class="op">!=</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-42"><a href="#cb20-42" aria-hidden="true" tabindex="-1"></a>            with_index<span class="op">([&amp;](</span><span class="kw">auto</span> I<span class="op">){</span></span>
<span id="cb20-43"><a href="#cb20-43" aria-hidden="true" tabindex="-1"></a>                std<span class="op">::</span>destroy_at<span class="op">(&amp;</span>storage_<span class="op">.[:</span> get_nth_field<span class="op">(</span>I<span class="op">)</span> <span class="op">:])</span>;</span>
<span id="cb20-44"><a href="#cb20-44" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb20-45"><a href="#cb20-45" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-46"><a href="#cb20-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-47"><a href="#cb20-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-48"><a href="#cb20-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> I <span class="op">=</span> accepted_index<span class="op">&lt;</span>T<span class="op">&amp;&amp;&gt;&gt;</span></span>
<span id="cb20-49"><a href="#cb20-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>is_base_of_v<span class="op">&lt;</span>Variant, std<span class="op">::</span>decay_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;)</span></span>
<span id="cb20-50"><a href="#cb20-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Variant<span class="op">(</span>T<span class="op">&amp;&amp;</span> t<span class="op">)</span></span>
<span id="cb20-51"><a href="#cb20-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-52"><a href="#cb20-52" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb20-53"><a href="#cb20-53" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-54"><a href="#cb20-54" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>construct_at<span class="op">(&amp;</span>storage_<span class="op">.[:</span> get_nth_field<span class="op">(</span>I<span class="op">)</span> <span class="op">:]</span>, <span class="op">(</span>T<span class="op">&amp;&amp;)</span>t<span class="op">)</span>;</span>
<span id="cb20-55"><a href="#cb20-55" aria-hidden="true" tabindex="-1"></a>        index_ <span class="op">=</span> <span class="op">(</span><span class="dt">int</span><span class="op">)</span>I;</span>
<span id="cb20-56"><a href="#cb20-56" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-57"><a href="#cb20-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-58"><a href="#cb20-58" aria-hidden="true" tabindex="-1"></a>    <span class="co">// you can&#39;t actually express this constraint nicely until P2963</span></span>
<span id="cb20-59"><a href="#cb20-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Variant<span class="op">(</span>Variant <span class="kw">const</span><span class="op">&amp;)</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_copyable_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="kw">and</span> <span class="op">...)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-60"><a href="#cb20-60" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Variant<span class="op">(</span>Variant <span class="kw">const</span><span class="op">&amp;</span> rhs<span class="op">)</span></span>
<span id="cb20-61"><a href="#cb20-61" aria-hidden="true" tabindex="-1"></a>            <span class="kw">requires</span> <span class="op">((</span>std<span class="op">::</span>is_copy_constructible_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="kw">and</span> <span class="op">...)</span></span>
<span id="cb20-62"><a href="#cb20-62" aria-hidden="true" tabindex="-1"></a>                <span class="kw">and</span> <span class="kw">not</span> <span class="op">(</span>std<span class="op">::</span>is_trivially_copyable_v<span class="op">&lt;</span>Ts<span class="op">&gt;</span> <span class="kw">and</span> <span class="op">...))</span></span>
<span id="cb20-63"><a href="#cb20-63" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-64"><a href="#cb20-64" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb20-65"><a href="#cb20-65" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-66"><a href="#cb20-66" aria-hidden="true" tabindex="-1"></a>        rhs<span class="op">.</span>with_index<span class="op">([&amp;](</span><span class="kw">auto</span> I<span class="op">){</span></span>
<span id="cb20-67"><a href="#cb20-67" aria-hidden="true" tabindex="-1"></a>            <span class="kw">constexpr</span> <span class="kw">auto</span> field <span class="op">=</span> get_nth_field<span class="op">(</span>I<span class="op">)</span>;</span>
<span id="cb20-68"><a href="#cb20-68" aria-hidden="true" tabindex="-1"></a>            std<span class="op">::</span>construct_at<span class="op">(&amp;</span>storage_<span class="op">.[:</span> field <span class="op">:]</span>, rhs<span class="op">.</span>storage_<span class="op">.[:</span> field <span class="op">:])</span>;</span>
<span id="cb20-69"><a href="#cb20-69" aria-hidden="true" tabindex="-1"></a>            index_ <span class="op">=</span> I;</span>
<span id="cb20-70"><a href="#cb20-70" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb20-71"><a href="#cb20-71" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-72"><a href="#cb20-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-73"><a href="#cb20-73" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> index<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span> <span class="cf">return</span> index_; <span class="op">}</span></span>
<span id="cb20-74"><a href="#cb20-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-75"><a href="#cb20-75" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F<span class="op">&gt;</span></span>
<span id="cb20-76"><a href="#cb20-76" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> visit<span class="op">(</span>F<span class="op">&amp;&amp;</span> f<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-77"><a href="#cb20-77" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>index_ <span class="op">==</span> <span class="op">-</span><span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-78"><a href="#cb20-78" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> std<span class="op">::</span>bad_variant_access<span class="op">()</span>;</span>
<span id="cb20-79"><a href="#cb20-79" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-80"><a href="#cb20-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-81"><a href="#cb20-81" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> mp_with_index<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;(</span>index_, <span class="op">[&amp;](</span><span class="kw">auto</span> I<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-82"><a href="#cb20-82" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> std<span class="op">::</span>invoke<span class="op">((</span>F<span class="op">&amp;&amp;)</span>f,  storage_<span class="op">.[:</span> get_nth_field<span class="op">(</span>I<span class="op">)</span> <span class="op">:])</span>;</span>
<span id="cb20-83"><a href="#cb20-83" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb20-84"><a href="#cb20-84" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-85"><a href="#cb20-85" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Effectively, <code class="sourceCode cpp">Variant<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code>
synthesizes a union type <code class="sourceCode cpp">Storage</code>
which looks like this:</p>
<div class="std">
<blockquote>
<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="kw">union</span> Storage <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    Empty empty;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    T <em>unnamed<sub>0</sub></em>;</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    U <em>unnamed<sub>1</sub></em>;</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 class="op">~</span>Storage<span class="op">()</span> <span class="kw">requires</span> std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>is_trivially_destructible_v<span class="op">&lt;</span>U<span class="op">&gt;</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">~</span>Storage<span class="op">()</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The question here is whether we should be should be able to directly
initialize members of a defined union using a splicer, as in:</p>
<div class="std">
<blockquote>
<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><span class="op">:</span> storage<span class="op">{.[:</span> get_nth_field<span class="op">(</span><span class="dv">0</span><span class="op">)</span> <span class="op">:]={}}</span></span></code></pre></div>
</blockquote>
</div>
<p>Arguably, the answer should be yes - this would be consistent with
how other accesses work. This is instead proposed in <span class="citation" data-cites="P3293R1"><a href="https://wg21.link/p3293r1" role="doc-biblioref">[P3293R1]</a></span>.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/W74qxqnhf">EDG</a>, <a href="https://godbolt.org/z/eqj6e3Tjr">Clang</a>.</p>
<h2 data-number="3.10" id="struct-to-struct-of-arrays"><span class="header-section-number">3.10</span> Struct to Struct of Arrays<a href="#struct-to-struct-of-arrays" class="self-link"></a></h2>
<div class="std">
<blockquote>
<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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;array&gt;</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-4"><a href="#cb23-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="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> struct_of_arrays_impl <span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> impl;</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>    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> old_members <span class="op">=</span> nonstatic_data_members_of<span class="op">(^^</span>T, ctx<span class="op">)</span>;</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>    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> new_members <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info member <span class="op">:</span> old_members<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> array_type <span class="op">=</span> substitute<span class="op">(^^</span>std<span class="op">::</span>array, <span class="op">{</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>            type_of<span class="op">(</span>member<span class="op">)</span>,</span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>            std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span>N<span class="op">)</span>,</span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> mem_descr <span class="op">=</span> data_member_spec<span class="op">(</span>array_type, <span class="op">{.</span>name <span class="op">=</span> identifier_of<span class="op">(</span>member<span class="op">)})</span>;</span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a>        new_members<span class="op">.</span>push_back<span class="op">(</span>mem_descr<span class="op">)</span>;</span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(^^</span>impl, new_members<span class="op">)</span>;</span>
<span id="cb23-23"><a href="#cb23-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb23-24"><a href="#cb23-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb23-25"><a href="#cb23-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-26"><a href="#cb23-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="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb23-27"><a href="#cb23-27" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> struct_of_arrays <span class="op">=</span> struct_of_arrays_impl<span class="op">&lt;</span>T, N<span class="op">&gt;::</span>impl;</span></code></pre></div>
</blockquote>
</div>
<p>Example:</p>
<div class="std">
<blockquote>
<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">struct</span> point <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> x;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> y;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> z;</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>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> points <span class="op">=</span> struct_of_arrays<span class="op">&lt;</span>point, <span class="dv">30</span><span class="op">&gt;</span>;</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="co">// equivalent to:</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a><span class="co">// struct points {</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="co">//   std::array&lt;float, 30&gt; x;</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="co">//   std::array&lt;float, 30&gt; y;</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a><span class="co">//   std::array&lt;float, 30&gt; z;</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a><span class="co">// };</span></span></code></pre></div>
</blockquote>
</div>
<p>Again, the combination of
<code class="sourceCode cpp">nonstatic_data_members_of</code> and
<code class="sourceCode cpp">define_aggregate</code> is put to good
use.</p>
<p>This example also illustrates some requirements that we have on
<code class="sourceCode cpp">define_aggregate</code>. In particular,
that function is said to produce an “injected declaration” and the
target scope of the declaration must be within the same “cone of
instantiation” as the evaluation that produced it. Which means that the
following similar structure is ill-formed:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> struct_of_arrays_impl;</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-4"><a href="#cb25-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="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> struct_of_arrays <span class="op">=</span> <span class="op">[:</span> <span class="op">[]{</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... same logic ..</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: the target scope of this declaration is a</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// different instantiation from the one we are currently in.</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>  define_aggregate<span class="op">(^^</span>struct_of_arrays_impl<span class="op">&lt;</span>T, N<span class="op">&gt;</span>, new_members<span class="op">)</span>;</span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span> <span class="op">:]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>That could be fixed if we reorganize it like this:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> struct_of_arrays <span class="op">=</span> <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="co">// ... same logic ..</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, same instantiation</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> impl;</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>  define_aggregate<span class="op">(^^</span>impl, new_members<span class="op">)</span>;</span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span> <span class="op">:]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But now <code class="sourceCode cpp">struct_of_arrays<span class="op">&lt;</span>point, <span class="dv">30</span><span class="op">&gt;</span></code>
has no linkage, whereas we wanted it to have external linkage. Hence the
structure in the example above where we are instead defining a nested
class in a class template — so that we have a type with external linkage
but don’t run afoul of the “cone of instantiation” rule.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/jWrPGhn5s">EDG</a>, <a href="https://godbolt.org/z/vqxzMoPcj">Clang</a>.</p>
<h2 data-number="3.11" id="parsing-command-line-options-ii"><span class="header-section-number">3.11</span> Parsing Command-Line Options
II<a href="#parsing-command-line-options-ii" class="self-link"></a></h2>
<p>Now that we’ve seen a couple examples of using <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_aggregate</code>
to create a type, we can create a more sophisticated command-line parser
example.</p>
<p>This is the opening example for <a href="https://docs.rs/clap/latest/clap/">clap</a> (Rust’s
<strong>C</strong>ommand <strong>L</strong>ine <strong>A</strong>rgument
<strong>P</strong>arser):</p>
<div class="std">
<blockquote>
<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="kw">struct</span> Args <span class="op">:</span> Clap <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>  Option<span class="op">&lt;</span>std<span class="op">::</span>string, <span class="op">{.</span>use_short<span class="op">=</span><span class="kw">true</span>, <span class="op">.</span>use_long<span class="op">=</span><span class="kw">true</span><span class="op">}&gt;</span> name;</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>  Option<span class="op">&lt;</span><span class="dt">int</span>, <span class="op">{.</span>use_short<span class="op">=</span><span class="kw">true</span>, <span class="op">.</span>use_long<span class="op">=</span><span class="kw">true</span><span class="op">}&gt;</span> count <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc, <span class="dt">char</span><span class="op">**</span> argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> opts <span class="op">=</span> Args<span class="op">{}.</span>parse<span class="op">(</span>argc, argv<span class="op">)</span>;</span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> opts<span class="op">.</span>count; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span>  <span class="co">// opts.count has type int</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;Hello {}!&quot;</span>, opts<span class="op">.</span>name<span class="op">)</span>;   <span class="co">// opts.name has type std::string</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Which we can implement like this:</p>
<div class="std">
<blockquote>
<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> Flags <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> use_short;</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> use_long;</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, Flags flags<span class="op">&gt;</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Option <span class="op">{</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span> initializer <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// some suitable constructors and accessors for flags</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</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><span class="co">// convert a type (all of whose non-static data members are specializations of Option)</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a><span class="co">// to a type that is just the appropriate members.</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a><span class="co">// For example, if type is a reflection of the Args presented above, then this</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a><span class="co">// function would evaluate to a reflection of the type</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a><span class="co">// struct {</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="co">//   std::string name;</span></span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a><span class="co">//   int count;</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a><span class="co">// }</span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> spec_to_opts<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info opts,</span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>                            std<span class="op">::</span>meta<span class="op">::</span>info spec<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a>  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> new_members;</span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info member <span class="op">:</span> nonstatic_data_members_of<span class="op">(</span>spec, ctx<span class="op">))</span> <span class="op">{</span></span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> type_new <span class="op">=</span> template_arguments_of<span class="op">(</span>type_of<span class="op">(</span>member<span class="op">))[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a>    new_members<span class="op">.</span>push_back<span class="op">(</span>data_member_spec<span class="op">(</span>type_new, <span class="op">{.</span>name<span class="op">=</span>identifier_of<span class="op">(</span>member<span class="op">)}))</span>;</span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> define_aggregate<span class="op">(</span>opts, new_members<span class="op">)</span>;</span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-32"><a href="#cb28-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-33"><a href="#cb28-33" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Clap <span class="op">{</span></span>
<span id="cb28-34"><a href="#cb28-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Spec<span class="op">&gt;</span></span>
<span id="cb28-35"><a href="#cb28-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> parse<span class="op">(</span><span class="kw">this</span> Spec <span class="kw">const</span><span class="op">&amp;</span> spec, <span class="dt">int</span> argc, <span class="dt">char</span><span class="op">**</span> argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-36"><a href="#cb28-36" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string_view<span class="op">&gt;</span> cmdline<span class="op">(</span>argv<span class="op">+</span><span class="dv">1</span>, argv<span class="op">+</span>argc<span class="op">)</span></span>
<span id="cb28-37"><a href="#cb28-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-38"><a href="#cb28-38" aria-hidden="true" tabindex="-1"></a>    <span class="co">// check if cmdline contains --help, etc.</span></span>
<span id="cb28-39"><a href="#cb28-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-40"><a href="#cb28-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Opts;</span>
<span id="cb28-41"><a href="#cb28-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb28-42"><a href="#cb28-42" aria-hidden="true" tabindex="-1"></a>      spec_to_opts<span class="op">(^^</span>Opts, <span class="op">^^</span>Spec<span class="op">)</span>;</span>
<span id="cb28-43"><a href="#cb28-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-44"><a href="#cb28-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-45"><a href="#cb28-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb28-46"><a href="#cb28-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> <span class="op">[</span>sm, om<span class="op">]</span> <span class="op">:</span></span>
<span id="cb28-47"><a href="#cb28-47" aria-hidden="true" tabindex="-1"></a>                  std<span class="op">::</span>define_static_array<span class="op">(</span></span>
<span id="cb28-48"><a href="#cb28-48" aria-hidden="true" tabindex="-1"></a>                      std<span class="op">::</span>views<span class="op">::</span>zip<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>Spec, ctx<span class="op">)</span>,</span>
<span id="cb28-49"><a href="#cb28-49" aria-hidden="true" tabindex="-1"></a>                                      nonstatic_data_members_of<span class="op">(^^</span>Opts, ctx<span class="op">))</span> <span class="op">|</span></span>
<span id="cb28-50"><a href="#cb28-50" aria-hidden="true" tabindex="-1"></a>                      std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span> z<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>pair<span class="op">(</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>z<span class="op">)</span>, get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>z<span class="op">))</span>; <span class="op">})))</span> <span class="op">{</span></span>
<span id="cb28-51"><a href="#cb28-51" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> cur <span class="op">=</span> spec<span class="op">.[:</span>sm<span class="op">:]</span>;</span>
<span id="cb28-52"><a href="#cb28-52" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> type <span class="op">=</span> type_of<span class="op">(</span>om<span class="op">)</span>;</span>
<span id="cb28-53"><a href="#cb28-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-54"><a href="#cb28-54" aria-hidden="true" tabindex="-1"></a>      <span class="co">// find the argument associated with this option</span></span>
<span id="cb28-55"><a href="#cb28-55" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> it <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>find_if<span class="op">(</span>cmdline,</span>
<span id="cb28-56"><a href="#cb28-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">[&amp;](</span>std<span class="op">::</span>string_view arg<span class="op">){</span></span>
<span id="cb28-57"><a href="#cb28-57" aria-hidden="true" tabindex="-1"></a>          <span class="cf">return</span> <span class="op">(</span>cur<span class="op">.</span>use_short <span class="op">&amp;&amp;</span> arg<span class="op">.</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">2</span> <span class="op">&amp;&amp;</span> arg<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;-&#39;</span> <span class="op">&amp;&amp;</span> arg<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">==</span> identifier_of<span class="op">(</span>sm<span class="op">)[</span><span class="dv">0</span><span class="op">])</span></span>
<span id="cb28-58"><a href="#cb28-58" aria-hidden="true" tabindex="-1"></a>              <span class="op">||</span> <span class="op">(</span>cur<span class="op">.</span>use_long <span class="op">&amp;&amp;</span> arg<span class="op">.</span>starts_with<span class="op">(</span><span class="st">&quot;--&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> arg<span class="op">.</span>substr<span class="op">(</span><span class="dv">2</span><span class="op">)</span> <span class="op">==</span> identifier_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb28-59"><a href="#cb28-59" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb28-60"><a href="#cb28-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-61"><a href="#cb28-61" aria-hidden="true" tabindex="-1"></a>      <span class="co">// no such argument</span></span>
<span id="cb28-62"><a href="#cb28-62" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>it <span class="op">==</span> cmdline<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb28-63"><a href="#cb28-63" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>has_template_arguments<span class="op">(</span>type<span class="op">)</span> <span class="kw">and</span> template_of<span class="op">(</span>type<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span>std<span class="op">::</span>optional<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-64"><a href="#cb28-64" aria-hidden="true" tabindex="-1"></a>          <span class="co">// the type is optional, so the argument is too</span></span>
<span id="cb28-65"><a href="#cb28-65" aria-hidden="true" tabindex="-1"></a>          <span class="cf">continue</span>;</span>
<span id="cb28-66"><a href="#cb28-66" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>cur<span class="op">.</span>initializer<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-67"><a href="#cb28-67" aria-hidden="true" tabindex="-1"></a>          <span class="co">// the type isn&#39;t optional, but an initializer is provided, use that</span></span>
<span id="cb28-68"><a href="#cb28-68" aria-hidden="true" tabindex="-1"></a>          opts<span class="op">.[:</span>om<span class="op">:]</span> <span class="op">=</span> <span class="op">*</span>cur<span class="op">.</span>initializer;</span>
<span id="cb28-69"><a href="#cb28-69" aria-hidden="true" tabindex="-1"></a>          <span class="cf">continue</span>;</span>
<span id="cb28-70"><a href="#cb28-70" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb28-71"><a href="#cb28-71" aria-hidden="true" tabindex="-1"></a>          std<span class="op">::</span>print<span class="op">(</span>stderr, <span class="st">&quot;Missing required option {}</span><span class="sc">\n</span><span class="st">&quot;</span>, display_string_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb28-72"><a href="#cb28-72" aria-hidden="true" tabindex="-1"></a>          std<span class="op">::</span>exit<span class="op">(</span>EXIT_FAILURE<span class="op">)</span>;</span>
<span id="cb28-73"><a href="#cb28-73" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-74"><a href="#cb28-74" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>it <span class="op">+</span> <span class="dv">1</span> <span class="op">==</span> cmdline<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb28-75"><a href="#cb28-75" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>print<span class="op">(</span>stderr, <span class="st">&quot;Option {} for {} is missing a value</span><span class="sc">\n</span><span class="st">&quot;</span>, <span class="op">*</span>it, display_string_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb28-76"><a href="#cb28-76" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>exit<span class="op">(</span>EXIT_FAILURE<span class="op">)</span>;</span>
<span id="cb28-77"><a href="#cb28-77" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb28-78"><a href="#cb28-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-79"><a href="#cb28-79" aria-hidden="true" tabindex="-1"></a>      <span class="co">// found our argument, try to parse it</span></span>
<span id="cb28-80"><a href="#cb28-80" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span> iss <span class="op">=</span> ispanstream<span class="op">(</span>it<span class="op">[</span><span class="dv">1</span><span class="op">])</span>;</span>
<span id="cb28-81"><a href="#cb28-81" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>iss <span class="op">&gt;&gt;</span> opts<span class="op">.[:</span>om<span class="op">:]</span>; <span class="op">!</span>iss<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-82"><a href="#cb28-82" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>print<span class="op">(</span>stderr, <span class="st">&quot;Failed to parse {:?} into option {} of type {}</span><span class="sc">\n</span><span class="st">&quot;</span>,</span>
<span id="cb28-83"><a href="#cb28-83" aria-hidden="true" tabindex="-1"></a>          it<span class="op">[</span><span class="dv">1</span><span class="op">]</span>, display_string_of<span class="op">(</span>sm<span class="op">)</span>, display_string_of<span class="op">(</span>type<span class="op">))</span>;</span>
<span id="cb28-84"><a href="#cb28-84" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>exit<span class="op">(</span>EXIT_FAILURE<span class="op">)</span>;</span>
<span id="cb28-85"><a href="#cb28-85" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb28-86"><a href="#cb28-86" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-87"><a href="#cb28-87" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> opts;</span>
<span id="cb28-88"><a href="#cb28-88" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb28-89"><a href="#cb28-89" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/4aseo5eGq">EDG</a>, <a href="https://godbolt.org/z/Yjv1dM4eK">Clang</a>.</p>
<h2 data-number="3.12" id="a-universal-formatter"><span class="header-section-number">3.12</span> A Universal Formatter<a href="#a-universal-formatter" class="self-link"></a></h2>
<p>This example is taken from Boost.Describe:</p>
<div class="std">
<blockquote>
<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> universal_formatter <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> parse<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;</span> ctx<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> ctx<span class="op">.</span>begin<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-4"><a href="#cb29-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="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> format<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> t, <span class="kw">auto</span><span class="op">&amp;</span> ctx<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> out <span class="op">=</span> std<span class="op">::</span>format_to<span class="op">(</span>ctx<span class="op">.</span>out<span class="op">()</span>, <span class="st">&quot;{}{{&quot;</span>, has_identifier<span class="op">(^^</span>T<span class="op">)</span> <span class="op">?</span> identifier_of<span class="op">(^^</span>T<span class="op">)</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>                                                                      <span class="op">:</span> <span class="st">&quot;(unnamed-type)&quot;</span>;<span class="op">)</span>;</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> delim <span class="op">=</span> <span class="op">[</span>first<span class="op">=</span><span class="kw">true</span><span class="op">]()</span> <span class="kw">mutable</span> <span class="op">{</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(!</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">*</span>out<span class="op">++</span> <span class="op">=</span> <span class="ch">&#39;,&#39;</span>;</span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">*</span>out<span class="op">++</span> <span class="op">=</span> <span class="ch">&#39; &#39;</span>;</span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>      first <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unchecked<span class="op">()</span>;</span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> base <span class="op">:</span> define_static_array<span class="op">(</span>bases_of<span class="op">(^^</span>T, ctx<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>      delim<span class="op">()</span>;</span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>      out <span class="op">=</span> std<span class="op">::</span>format_to<span class="op">(</span>out, <span class="st">&quot;{}&quot;</span>, <span class="op">(</span><span class="kw">typename</span> <span class="op">[:</span> type_of<span class="op">(</span>base<span class="op">)</span> <span class="op">:]</span> <span class="kw">const</span><span class="op">&amp;)(</span>t<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></span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> mem <span class="op">:</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a>                  define_static_array<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>T, ctx<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>      delim<span class="op">()</span>;</span>
<span id="cb29-27"><a href="#cb29-27" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>string_view mem_label <span class="op">=</span> has_identifier<span class="op">(</span>mem<span class="op">)</span> <span class="op">?</span> identifier_of<span class="op">(</span>mem<span class="op">)</span></span>
<span id="cb29-28"><a href="#cb29-28" aria-hidden="true" tabindex="-1"></a>                                                       <span class="op">:</span> <span class="st">&quot;(unnamed-member)&quot;</span>;</span>
<span id="cb29-29"><a href="#cb29-29" aria-hidden="true" tabindex="-1"></a>      out <span class="op">=</span> std<span class="op">::</span>format_to<span class="op">(</span>out, <span class="st">&quot;.{}={}&quot;</span>, mem_label, t<span class="op">.[:</span>mem<span class="op">:])</span>;</span>
<span id="cb29-30"><a href="#cb29-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-31"><a href="#cb29-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-32"><a href="#cb29-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>out<span class="op">++</span> <span class="op">=</span> <span class="ch">&#39;}&#39;</span>;</span>
<span id="cb29-33"><a href="#cb29-33" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> out;</span>
<span id="cb29-34"><a href="#cb29-34" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-35"><a href="#cb29-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb29-36"><a href="#cb29-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-37"><a href="#cb29-37" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">{</span> <span class="dt">int</span> m0 <span class="op">=</span> <span class="dv">0</span>; <span class="op">}</span>;</span>
<span id="cb29-38"><a href="#cb29-38" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span> <span class="dt">int</span> m1 <span class="op">=</span> <span class="dv">1</span>; <span class="op">}</span>;</span>
<span id="cb29-39"><a href="#cb29-39" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Y <span class="op">{</span> <span class="dt">int</span> m2 <span class="op">=</span> <span class="dv">2</span>; <span class="op">}</span>;</span>
<span id="cb29-40"><a href="#cb29-40" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Z <span class="op">:</span> <span class="kw">public</span> X, <span class="kw">private</span> Y <span class="op">{</span> <span class="dt">int</span> m3 <span class="op">=</span> <span class="dv">3</span>; <span class="dt">int</span> m4 <span class="op">=</span> <span class="dv">4</span>; <span class="op">}</span>;</span>
<span id="cb29-41"><a href="#cb29-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-42"><a href="#cb29-42" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> std<span class="op">::</span>formatter<span class="op">&lt;</span>B<span class="op">&gt;</span> <span class="op">:</span> universal_formatter <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb29-43"><a href="#cb29-43" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> std<span class="op">::</span>formatter<span class="op">&lt;</span>X<span class="op">&gt;</span> <span class="op">:</span> universal_formatter <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb29-44"><a href="#cb29-44" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> std<span class="op">::</span>formatter<span class="op">&lt;</span>Y<span class="op">&gt;</span> <span class="op">:</span> universal_formatter <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb29-45"><a href="#cb29-45" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> std<span class="op">::</span>formatter<span class="op">&lt;</span>Z<span class="op">&gt;</span> <span class="op">:</span> universal_formatter <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb29-46"><a href="#cb29-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-47"><a href="#cb29-47" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-48"><a href="#cb29-48" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;{}&quot;</span>, Z<span class="op">())</span>;</span>
<span id="cb29-49"><a href="#cb29-49" aria-hidden="true" tabindex="-1"></a>      <span class="co">// Z{X{B{.m0=0}, .m1 = 1}, Y{{.m0=0}, .m2 = 2}, .m3 = 3, .m4 = 4}</span></span>
<span id="cb29-50"><a href="#cb29-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/99dTErdG6">Clang</a>.</p>
<p>Note that currently, we do not have the ability to access a base
class subobject using the <code class="sourceCode cpp">t<span class="op">.[:</span> base <span class="op">:]</span></code>
syntax - which means that the only way to get at the base is to use a
cast:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">static_cast</span><span class="op">&lt;[:</span> type_of<span class="op">(</span>base<span class="op">)</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">:]&gt;(</span>t<span class="op">)</span></code>,
or</li>
<li><code class="sourceCode cpp"><span class="op">(</span><span class="kw">typename</span> <span class="op">[:</span> type_of<span class="op">(</span>base<span class="op">)</span> <span class="op">:]</span> <span class="kw">const</span><span class="op">&amp;)</span>t</code></li>
</ul>
<p>Both have to explicitly specify the
<code class="sourceCode cpp"><span class="kw">const</span></code>-ness
of the type in the cast. The
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>
additionally has to check access. The C-style cast is one many people
find unsavory, though in this case it avoids checking access - but
requires writing
<code class="sourceCode cpp"><span class="kw">typename</span></code>
since this isn’t a type-only context.</p>
<h2 data-number="3.13" id="implementing-member-wise-hash_append"><span class="header-section-number">3.13</span> Implementing member-wise
<code class="sourceCode cpp">hash_append</code><a href="#implementing-member-wise-hash_append" class="self-link"></a></h2>
<p>Based on the <span class="citation" data-cites="N3980"><a href="https://wg21.link/n3980" role="doc-biblioref">[N3980]</a></span>
API:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> H, <span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">requires</span> std<span class="op">::</span>is_standard_layout_v<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> hash_append<span class="op">(</span>H<span class="op">&amp;</span> algo, T <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unchecked<span class="op">()</span>;</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> mem <span class="op">:</span> nonstatic_data_members_of<span class="op">(^^</span>T, ctx<span class="op">))</span> <span class="op">{</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>      hash_append<span class="op">(</span>algo, t<span class="op">.[:</span>mem<span class="op">:])</span>;</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Of course, any production-ready
<code class="sourceCode cpp">hash_append</code> would include a facility
for classes to opt members in and out of participation in hashing.
Annotations as proposed by <span class="title"><span class="citation" data-cites="P3394R2"><a href="https://wg21.link/p3394r2" role="doc-biblioref">[P3394R2] (Annotations for
Reflection)</a></span></span> provides just such a mechanism.</p>
<h2 data-number="3.14" id="converting-a-struct-to-a-tuple"><span class="header-section-number">3.14</span> Converting a Struct to a
Tuple<a href="#converting-a-struct-to-a-tuple" class="self-link"></a></h2>
<p>This approach requires allowing packs in structured bindings <span class="citation" data-cites="P1061R10"><a href="https://wg21.link/p1061r10" role="doc-biblioref">[P1061R10]</a></span>, but can also be written
using <code class="sourceCode cpp">std<span class="op">::</span>make_index_sequence</code>:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> std<span class="op">::</span><span class="dt">size_t</span> N <span class="op">=</span> nonstatic_data_members_of<span class="op">(^^</span>T, ctx<span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> members <span class="op">=</span> nonstatic_data_members<span class="op">(^^</span>T, ctx<span class="op">)</span>;</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> indices <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>array<span class="op">&lt;</span><span class="dt">int</span>, N<span class="op">&gt;</span> indices;</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>ranges<span class="op">::</span>iota<span class="op">(</span>indices, <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> indices;</span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="op">[...</span>Is<span class="op">]</span> <span class="op">=</span> indices;</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>make_tuple<span class="op">(</span>t<span class="op">.[:</span> members<span class="op">[</span>Is<span class="op">]</span> <span class="op">:]...)</span>;</span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>An alternative approach is:</p>
<div class="std">
<blockquote>
<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><span class="kw">consteval</span> <span class="kw">auto</span> type_struct_to_tuple<span class="op">(</span>info type<span class="op">)</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> substitute<span class="op">(^^</span>std<span class="op">::</span>tuple,</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>                    nonstatic_data_members_of<span class="op">(</span>type, ctx<span class="op">)</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>type_of<span class="op">)</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>remove_cvref<span class="op">)</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> std<span class="op">::</span>ranges<span class="op">::</span>to<span class="op">&lt;</span>std<span class="op">::</span>vector<span class="op">&gt;())</span>;</span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> To, <span class="kw">typename</span> From, std<span class="op">::</span>meta<span class="op">::</span>info <span class="op">...</span> members<span class="op">&gt;</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple_helper<span class="op">(</span>From <span class="kw">const</span><span class="op">&amp;</span> from<span class="op">)</span> <span class="op">-&gt;</span> To <span class="op">{</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> To<span class="op">(</span>from<span class="op">.[:</span>members<span class="op">:]...)</span>;</span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> From<span class="op">&gt;</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> get_struct_to_tuple_helper<span class="op">()</span> <span class="op">{</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> To <span class="op">=</span> <span class="op">[:</span> type_struct_to_tuple<span class="op">(^^</span>From<span class="op">):</span> <span class="op">]</span>;</span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector args <span class="op">=</span> <span class="op">{^^</span>To, <span class="op">^^</span>From<span class="op">}</span>;</span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> mem <span class="op">:</span> nonstatic_data_members_of<span class="op">(^^</span>From, ctx<span class="op">))</span> <span class="op">{</span></span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>    args<span class="op">.</span>push_back<span class="op">(</span>reflect_constant<span class="op">(</span>mem<span class="op">))</span>;</span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">/*</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a><span class="co">  Alternatively, with Ranges:</span></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a><span class="co">  args.append_range(</span></span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a><span class="co">    nonstatic_data_members_of(^^From, ctx)</span></span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a><span class="co">    | std::views::transform(std::meta::reflect_constant)</span></span>
<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a><span class="co">    );</span></span>
<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a><span class="co">  */</span></span>
<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> extract<span class="op">&lt;</span>To<span class="op">(*)(</span>From <span class="kw">const</span><span class="op">&amp;)&gt;(</span></span>
<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a>    substitute<span class="op">(^^</span>struct_to_tuple_helper, args<span class="op">))</span>;</span>
<span id="cb32-35"><a href="#cb32-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-36"><a href="#cb32-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-37"><a href="#cb32-37" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> From<span class="op">&gt;</span></span>
<span id="cb32-38"><a href="#cb32-38" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple<span class="op">(</span>From <span class="kw">const</span><span class="op">&amp;</span> from<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-39"><a href="#cb32-39" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> get_struct_to_tuple_helper<span class="op">&lt;</span>From<span class="op">&gt;()(</span>from<span class="op">)</span>;</span>
<span id="cb32-40"><a href="#cb32-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Here, <code class="sourceCode cpp">type_struct_to_tuple</code> takes
a reflection of a type like <code class="sourceCode cpp"><span class="kw">struct</span> <span class="op">{</span> T t; U <span class="kw">const</span><span class="op">&amp;</span> u; V v; <span class="op">}</span></code>
and returns a reflection of the type <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>T, U, V<span class="op">&gt;</span></code>.
That gives us the return type. Then,
<code class="sourceCode cpp">struct_to_tuple_helper</code> is a function
template that does the actual conversion — which it can do by having all
the reflections of the members as a non-type template parameter pack.
This is a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
function and not a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
function because in the general case the conversion is a run-time
operation. However, determining the instance of
<code class="sourceCode cpp">struct_to_tuple_helper</code> that is
needed is a compile-time operation and has to be performed with a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
function (because the function invokes
<code class="sourceCode cpp">nonstatic_data_members_of</code>), hence
the separate function template <code class="sourceCode cpp">get_struct_to_tuple_helper<span class="op">()</span></code>.</p>
<p>Everything is put together by using
<code class="sourceCode cpp">substitute</code> to create the
instantiation of
<code class="sourceCode cpp">struct_to_tuple_helper</code> that we need,
and a compile-time reference to that instance is obtained with
<code class="sourceCode cpp">extract</code>. Thus
<code class="sourceCode cpp">f</code> is a function reference to the
correct specialization of
<code class="sourceCode cpp">struct_to_tuple_helper</code>, which we can
simply invoke.</p>
<p>On Compiler Explorer (with a different implementation than either of
the above): <a href="https://godbolt.org/z/1Tffn4vzn">EDG</a>, <a href="https://godbolt.org/z/dn58s5Pvz">Clang</a>.</p>
<h2 data-number="3.15" id="implementing-tuple_cat"><span class="header-section-number">3.15</span> Implementing
<code class="sourceCode cpp">tuple_cat</code><a href="#implementing-tuple_cat" class="self-link"></a></h2>
<p>Courtesy of Tomasz Kaminski, <a href="https://godbolt.org/z/M38b3a7z4">on compiler explorer</a>:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span><span class="op">&lt;</span>std<span class="op">::</span>pair<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">&gt;...</span> indices<span class="op">&gt;</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Indexer <span class="op">{</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>   <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Tuples<span class="op">&gt;</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>   <span class="co">// Can use tuple indexing instead of tuple of tuples</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>   <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>Tuples<span class="op">&amp;&amp;</span> tuples<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>     <span class="kw">using</span> ResultType <span class="op">=</span> std<span class="op">::</span>tuple<span class="op">&lt;</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>       std<span class="op">::</span>tuple_element_t<span class="op">&lt;</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>         indices<span class="op">.</span>second,</span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>         std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>std<span class="op">::</span>tuple_element_t<span class="op">&lt;</span>indices<span class="op">.</span>first, std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>Tuples<span class="op">&gt;&gt;&gt;</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>       <span class="op">&gt;...</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>     <span class="op">&gt;</span>;</span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>     <span class="cf">return</span> ResultType<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>indices<span class="op">.</span>second<span class="op">&gt;(</span>std<span class="op">::</span>get<span class="op">&lt;</span>indices<span class="op">.</span>first<span class="op">&gt;(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Tuples<span class="op">&gt;(</span>tuples<span class="op">)))...)</span>;</span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> subst_by_value<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info tmpl, std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> args<span class="op">)</span></span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> std<span class="op">::</span>meta<span class="op">::</span>info</span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>    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> a2;</span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>T x <span class="op">:</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a>        a2<span class="op">.</span>push_back<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span>x<span class="op">))</span>;</span>
<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> substitute<span class="op">(</span>tmpl, a2<span class="op">)</span>;</span>
<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb33-27"><a href="#cb33-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-28"><a href="#cb33-28" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> make_indexer<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">&gt;</span> sizes<span class="op">)</span></span>
<span id="cb33-29"><a href="#cb33-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> std<span class="op">::</span>meta<span class="op">::</span>info</span>
<span id="cb33-30"><a href="#cb33-30" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb33-31"><a href="#cb33-31" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>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;&gt;</span> args;</span>
<span id="cb33-32"><a href="#cb33-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-33"><a href="#cb33-33" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> tidx <span class="op">=</span> <span class="dv">0</span>; tidx <span class="op">&lt;</span> sizes<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>tidx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-34"><a href="#cb33-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> eidx <span class="op">=</span> <span class="dv">0</span>; eidx <span class="op">&lt;</span> sizes<span class="op">[</span>tidx<span class="op">]</span>; <span class="op">++</span>eidx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-35"><a href="#cb33-35" aria-hidden="true" tabindex="-1"></a>            args<span class="op">.</span>push_back<span class="op">({</span>tidx, eidx<span class="op">})</span>;</span>
<span id="cb33-36"><a href="#cb33-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb33-37"><a href="#cb33-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-38"><a href="#cb33-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-39"><a href="#cb33-39" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> subst_by_value<span class="op">(^^</span>Indexer, args<span class="op">)</span>;</span>
<span id="cb33-40"><a href="#cb33-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb33-41"><a href="#cb33-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-42"><a href="#cb33-42" 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> Tuples<span class="op">&gt;</span></span>
<span id="cb33-43"><a href="#cb33-43" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> my_tuple_cat<span class="op">(</span>Tuples<span class="op">&amp;&amp;...</span> tuples<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-44"><a href="#cb33-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">typename</span> <span class="op">[:</span> make_indexer<span class="op">({</span>tuple_size<span class="op">(</span>remove_cvref<span class="op">(^^</span>Tuples<span class="op">))...})</span> <span class="op">:]</span> indexer;</span>
<span id="cb33-45"><a href="#cb33-45" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> indexer<span class="op">(</span>std<span class="op">::</span>forward_as_tuple<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Tuples<span class="op">&gt;(</span>tuples<span class="op">)...))</span>;</span>
<span id="cb33-46"><a href="#cb33-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h2 data-number="3.16" id="named-tuple"><span class="header-section-number">3.16</span> Named Tuple<a href="#named-tuple" class="self-link"></a></h2>
<p>The tricky thing with implementing a named tuple is actually strings
as non-type template parameters. Because you cannot just pass <code class="sourceCode cpp"><span class="st">&quot;x&quot;</span></code> into
a non-type template parameter of the form
<code class="sourceCode cpp"><span class="kw">auto</span> V</code>, that
leaves us with two ways of specifying the constituents:</p>
<ol type="1">
<li>Can introduce a <code class="sourceCode cpp">pair</code> type so
that we can write <code class="sourceCode cpp">make_named_tuple<span class="op">&lt;</span>pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="st">&quot;x&quot;</span><span class="op">&gt;</span>, pair<span class="op">&lt;</span><span class="dt">double</span>, <span class="st">&quot;y&quot;</span><span class="op">&gt;&gt;()</span></code>,
or</li>
<li>Can just do reflections all the way down so that we can write</li>
</ol>
<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>make_named_tuple<span class="op">&lt;^^</span><span class="dt">int</span>, std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span><span class="st">&quot;x&quot;</span><span class="op">)</span>,</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>                 <span class="op">^^</span><span class="dt">double</span>, std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span><span class="st">&quot;y&quot;</span><span class="op">)&gt;()</span></span></code></pre></div>
<p>We do not currently support splicing string literals, and the
<code class="sourceCode cpp">pair</code> approach follows the similar
pattern already shown with
<code class="sourceCode cpp">define_aggregate</code> (given a suitable
<code class="sourceCode cpp">fixed_string</code> type):</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, fixed_string Name<span class="op">&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> name<span class="op">()</span> <span class="op">-&gt;</span> std<span class="op">::</span>string_view <span class="op">{</span> <span class="cf">return</span> Name<span class="op">.</span>view<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Tags<span class="op">&gt;</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> make_named_tuple<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info type, Tags<span class="op">...</span> tags<span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>    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> nsdms;</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> f <span class="op">=</span> <span class="op">[&amp;]&lt;</span><span class="kw">class</span> Tag<span class="op">&gt;(</span>Tag tag<span class="op">){</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>        nsdms<span class="op">.</span>push_back<span class="op">(</span>data_member_spec<span class="op">(</span></span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>            dealias<span class="op">(^^</span><span class="kw">typename</span> Tag<span class="op">::</span>type<span class="op">)</span>,</span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">{.</span>name<span class="op">=</span>Tag<span class="op">::</span>name<span class="op">()}))</span>;</span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span>f<span class="op">(</span>tags<span class="op">)</span>, <span class="op">...)</span>;</span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> define_aggregate<span class="op">(</span>type, nsdms<span class="op">)</span>;</span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> R;</span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a>  make_named_tuple<span class="op">(^^</span>R, pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="st">&quot;x&quot;</span><span class="op">&gt;{}</span>, pair<span class="op">&lt;</span><span class="dt">double</span>, <span class="st">&quot;y&quot;</span><span class="op">&gt;{})</span>;</span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>type_of<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>R, ctx<span class="op">)[</span><span class="dv">0</span><span class="op">])</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>type_of<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>R, ctx<span class="op">)[</span><span class="dv">1</span><span class="op">])</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">double</span><span class="op">)</span>;</span>
<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-29"><a href="#cb35-29" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb35-30"><a href="#cb35-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">[[</span><span class="at">maybe_unused</span><span class="op">]]</span> <span class="kw">auto</span> r <span class="op">=</span> R<span class="op">{.</span>x<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>y<span class="op">=</span><span class="fl">2.0</span><span class="op">}</span>;</span>
<span id="cb35-31"><a href="#cb35-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/64qTe4KG1">EDG</a>, <a href="https://godbolt.org/z/rPM5xsbvW">Clang</a>.</p>
<p>Alternatively, can side-step the question of non-type template
parameters entirely by keeping everything in the value domain:</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> <span class="kw">auto</span> make_named_tuple<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info type,</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>                                std<span class="op">::</span>initializer_list<span class="op">&lt;</span>std<span class="op">::</span>pair<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info, std<span class="op">::</span>string_view<span class="op">&gt;&gt;</span> members<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>data_member_spec<span class="op">&gt;</span> nsdms;</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="op">[</span>type, name<span class="op">]</span> <span class="op">:</span> members<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>        nsdms<span class="op">.</span>push_back<span class="op">(</span>data_member_spec<span class="op">(</span>type, <span class="op">{.</span>name<span class="op">=</span>name<span class="op">}))</span>;</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> define_aggregate<span class="op">(</span>type, nsdms<span class="op">)</span>;</span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> R;</span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>  make_named_tuple<span class="op">(^^</span>R, <span class="op">{{^^</span><span class="dt">int</span>, <span class="st">&quot;x&quot;</span><span class="op">}</span>, <span class="op">{^^</span><span class="dt">double</span>, <span class="st">&quot;y&quot;</span><span class="op">}})</span>;</span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>type_of<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>R, ctx<span class="op">)[</span><span class="dv">0</span><span class="op">])</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>type_of<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>R, ctx<span class="op">)[</span><span class="dv">1</span><span class="op">])</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">double</span><span class="op">)</span>;</span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">[[</span><span class="at">maybe_unused</span><span class="op">]]</span> <span class="kw">auto</span> r <span class="op">=</span> R<span class="op">{.</span>x<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>y<span class="op">=</span><span class="fl">2.0</span><span class="op">}</span>;</span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/oY6ETbv9x">EDG
and Clang</a> (the EDG and Clang implementations differ only in Clang
having the updated <code class="sourceCode cpp">data_member_spec</code>
API that returns an <code class="sourceCode cpp">info</code>, and the
updated name <code class="sourceCode cpp">define_aggregate</code>).</p>
<h2 data-number="3.17" id="compile-time-ticket-counter"><span class="header-section-number">3.17</span> Compile-Time Ticket Counter<a href="#compile-time-ticket-counter" class="self-link"></a></h2>
<p>The features proposed here make it a little easier to update a ticket
counter at compile time. This is not an ideal implementation (we’d
prefer direct support for compile-time —– i.e.,
<code class="sourceCode cpp"><span class="kw">consteval</span></code> —
variables), but it shows how compile-time mutable state surfaces in new
ways.</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span><span class="op">&lt;</span><span class="dt">int</span> N<span class="op">&gt;</span> <span class="kw">struct</span> Helper;</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="kw">struct</span> TU_Ticket <span class="op">{</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">int</span> latest<span class="op">()</span> <span class="op">{</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>is_complete_type<span class="op">(</span>substitute<span class="op">(^^</span>Helper,</span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>                                       <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span>k<span class="op">)</span> <span class="op">})))</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">++</span>k;</span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> k;</span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">void</span> increment<span class="op">()</span> <span class="op">{</span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(</span>substitute<span class="op">(^^</span>Helper,</span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a>                                <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span>latest<span class="op">())})</span>,</span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a>                     <span class="op">{})</span>;</span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-19"><a href="#cb37-19" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> x <span class="op">=</span> TU_Ticket<span class="op">::</span>latest<span class="op">()</span>;  <span class="co">// x initialized to 0.</span></span>
<span id="cb37-20"><a href="#cb37-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-21"><a href="#cb37-21" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> TU_Ticket<span class="op">::</span>increment<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb37-22"><a href="#cb37-22" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> y <span class="op">=</span> TU_Ticket<span class="op">::</span>latest<span class="op">()</span>;  <span class="co">// y initialized to 1.</span></span>
<span id="cb37-23"><a href="#cb37-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-24"><a href="#cb37-24" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> TU_Ticket<span class="op">::</span>increment<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb37-25"><a href="#cb37-25" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> z <span class="op">=</span> TU_Ticket<span class="op">::</span>latest<span class="op">()</span>;  <span class="co">// z initialized to 2.</span></span>
<span id="cb37-26"><a href="#cb37-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-27"><a href="#cb37-27" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>x <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb37-28"><a href="#cb37-28" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>y <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb37-29"><a href="#cb37-29" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>z <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/e1r8q3sWv">EDG</a>, <a href="https://godbolt.org/z/z4KKe5e57">Clang</a>.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="proposed-features"><span class="header-section-number">4</span>
Proposed Features<a href="#proposed-features" class="self-link"></a></h1>
<h2 data-number="4.1" id="the-reflection-operator"><span class="header-section-number">4.1</span> The Reflection Operator
(<code class="sourceCode cpp"><span class="op">^^</span></code>)<a href="#the-reflection-operator" class="self-link"></a></h2>
<p>The reflection operator produces a reflection value from a
grammatical construct (its operand):</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><em>unary-expression</em></code>:<br />
      …<br />
      <code class="sourceCode cpp"><span class="op">^^</span></code>
<code class="sourceCode cpp"><span class="op">::</span></code><br />
      <code class="sourceCode cpp"><span class="op">^^</span></code>
<code class="sourceCode cpp"><em>namespace-name</em></code><br />
      <code class="sourceCode cpp"><span class="op">^^</span></code>
<code class="sourceCode cpp"><em>type-id</em></code><br />
      <code class="sourceCode cpp"><span class="op">^^</span></code>
<code class="sourceCode cpp"><em>id-expression</em></code></div>
</blockquote>
<p>The expression
<code class="sourceCode cpp"><span class="op">^^::</span></code>
evaluates to a reflection of the global namespace. When the operand is a
<code class="sourceCode cpp"><em>namespace-name</em></code> or
<code class="sourceCode cpp"><em>type-id</em></code>, the resulting
value is a reflection of the designated namespace or type.</p>
<p>When the operand is an
<code class="sourceCode cpp"><em>id-expression</em></code>, the
resulting value is a reflection of the designated entity found by
lookup. This might be any of:</p>
<ul>
<li>a variable, static data member, or structured binding</li>
<li>a function (including member functions)</li>
<li>a non-static data member</li>
<li>a primary template or primary member template</li>
<li>an enumerator</li>
</ul>
<p>For all other operands, the expression is ill-formed. In a SFINAE
context, a failure to substitute the operand of a reflection operator
construct causes that construct to not evaluate to constant.</p>
<p>Earlier revisions of this paper allowed for taking the reflection of
any <code class="sourceCode cpp"><em>cast-expression</em></code> that
could be evaluated as a constant expression, as we believed that a
constant expression could be internally “represented” by just capturing
the value to which it evaluated. However, the possibility of side
effects from constant evaluation (introduced by this very paper) renders
this approach infeasible: even a constant expression would have to be
evaluated every time it’s spliced. It was ultimately decided to defer
all support for expression reflection, but we intend to introduce it
through a future paper using the syntax <code class="sourceCode cpp"><span class="op">^^(</span>expr<span class="op">)</span></code>.</p>
<p>This paper does, however, support reflections of <em>values</em> and
of <em>objects</em> (including subobjects). Such reflections arise
naturally when iterating over template arguments.</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span> P1, <span class="kw">const</span> <span class="dt">int</span> <span class="op">&amp;</span>P2<span class="op">&gt;</span> <span class="dt">void</span> fn<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> p<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span>;</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> spec <span class="op">=</span> <span class="op">^^</span>fn<span class="op">&lt;</span>p<span class="op">[</span><span class="dv">0</span><span class="op">]</span>, p<span class="op">[</span><span class="dv">1</span><span class="op">]&gt;</span>;</span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_value<span class="op">(</span>template_arguments_of<span class="op">(</span>spec<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span>;</span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_object<span class="op">(</span>template_arguments_of<span class="op">(</span>spec<span class="op">)[</span><span class="dv">1</span><span class="op">]))</span>;</span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_variable<span class="op">(</span>template_arguments_of<span class="op">(</span>spec<span class="op">)[</span><span class="dv">1</span><span class="op">]))</span>;</span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">([:</span>template_arguments_of<span class="op">(</span>spec<span class="op">)[</span><span class="dv">0</span><span class="op">]:]</span> <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(&amp;[:</span>template_arguments_of<span class="op">(</span>spec<span class="op">)[</span><span class="dv">1</span><span class="op">]:]</span> <span class="op">==</span> <span class="op">&amp;</span>p<span class="op">[</span><span class="dv">1</span><span class="op">])</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Such reflections cannot generally be obtained using the
<code class="sourceCode cpp"><span class="op">^^</span></code>-operator,
but the <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_constant</code>
and <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_object</code>
functions make it easy to reflect particular values or objects. The
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>constant_of</code>
metafunction can also be used to map a reflection of an object to a
reflection of its value.</p>
<h3 data-number="4.1.1" id="syntax-discussion"><span class="header-section-number">4.1.1</span> Syntax discussion<a href="#syntax-discussion" class="self-link"></a></h3>
<p>The original TS landed on <code class="sourceCode cpp"><span class="cf">reflexpr</span><span class="op">(...)</span></code>
as the syntax to reflect source constructs and <span class="citation" data-cites="P1240R0"><a href="https://wg21.link/p1240r0" role="doc-biblioref">[P1240R0]</a></span> adopted that syntax as well.
As more examples were discussed, it became clear that that syntax was
both (a) too “heavy” and (b) insufficiently distinct from a function
call. SG7 eventually agreed upon the prefix
<code class="sourceCode cpp"><span class="op">^</span></code> operator.
The “upward arrow” interpretation of the caret matches the “lift” or
“raise” verbs that are sometimes used to describe the reflection
operation in other contexts.</p>
<p>The caret already has a meaning as a binary operator in C++
(“exclusive OR”), but that is clearly not conflicting with a prefix
operator. In C++/CLI (a Microsoft C++ dialect) the caret is also used as
a new kind of <code class="sourceCode cpp"><em>ptr-operator</em></code>
(<span>9.3.1 <a href="https://wg21.link/dcl.decl.general">[dcl.decl.general]</a></span>)
to declare <a href="https://learn.microsoft.com/en-us/cpp/extensions/handle-to-object-operator-hat-cpp-component-extensions?view=msvc-170">“handles”</a>.
That is also not conflicting with the use of the caret as a unary
operator because C++/CLI uses the usual prefix
<code class="sourceCode cpp"><span class="op">*</span></code> operator
to dereference handles.</p>
<p>Apple also uses the caret in <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html">syntax
“blocks”</a> and unfortunately we believe that does conflict with our
proposed use of the caret.</p>
<p>Since the syntax discussions in SG7 landed on the use of the caret,
new basic source characters have become available:
<code class="sourceCode cpp"><span class="op">@</span></code>,
<code><span class="op">`</span></code>, and
<code><span class="op">$</span></code>. While we have since discussed
some alternatives (e.g.,
<code class="sourceCode cpp"><span class="op">@</span></code> for
lifting, <code class="sourceCode cpp">\</code> and
<code class="sourceCode cpp"><span class="op">/</span></code> for
“raising” and “lowering”), we have grown quite fond of the existing
syntax.</p>
<p>In Wrocław 2024, SG7 and EWG voted to adopt
<code class="sourceCode cpp"><span class="op">^^</span></code> as the
new reflection operator (as proposed by <span class="citation" data-cites="P3381R0"><a href="https://wg21.link/p3381r0" role="doc-biblioref">[P3381R0]</a></span>). The R8 revision of this
paper integrates that change.</p>
<h2 data-number="4.2" id="splicers"><span class="header-section-number">4.2</span> Splicers
(<code class="sourceCode cpp"><span class="op">[:</span></code>…<code class="sourceCode cpp"><span class="op">:]</span></code>)<a href="#splicers" class="self-link"></a></h2>
<p>A reflection can be “spliced” into source code using one of several
<em>splicer</em> forms:</p>
<ul>
<li><code class="sourceCode cpp"><span class="op">[:</span> r <span class="op">:]</span></code>
produces an <em>expression</em> evaluating to the entity represented by
<code class="sourceCode cpp">r</code> in grammatical contexts that
permit expressions. In type-only contexts (<span>13.8.1 <a href="https://wg21.link/temp.res.general">[temp.res.general]</a></span>/4),
<code class="sourceCode cpp"><span class="op">[:</span> r <span class="op">:]</span></code>
produces a type (and <code class="sourceCode cpp">r</code> must be the
reflection of a type). In contexts that only permit a namespace name,
<code class="sourceCode cpp"><span class="op">[:</span> r <span class="op">:]</span></code>
produces a namespace (and <code class="sourceCode cpp">r</code> must be
the reflection of a namespace or alias thereof).</li>
<li><code class="sourceCode cpp"><span class="kw">typename</span><span class="op">[:</span> r <span class="op">:]</span></code>
produces a <em>simple-type-specifier</em> corresponding to the type
represented by <code class="sourceCode cpp">r</code>.</li>
<li><code class="sourceCode cpp"><span class="kw">template</span><span class="op">[:</span> r <span class="op">:]</span></code>
produces a <em>template-name</em> corresponding to the template
represented by <code class="sourceCode cpp">r</code>.</li>
<li><code class="sourceCode cpp"><span class="op">[:</span>r<span class="op">:]::</span></code>
produces a <em>nested-name-specifier</em> corresponding to the
namespace, enumeration type, or class type represented by
<code class="sourceCode cpp">r</code>.</li>
</ul>
<p>The operand of a splicer is implicitly converted to a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
prvalue (i.e., if the operand expression has a class type that with a
conversion function to convert to <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
splicing can still work).</p>
<p>Attempting to splice a reflection value that does not meet the
requirement of the splice is ill-formed. For example:</p>
<div class="std">
<blockquote>
<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="kw">typename</span><span class="op">[:</span> <span class="op">^^::</span> <span class="op">:]</span> x <span class="op">=</span> <span class="dv">0</span>;  <span class="co">// Error.</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.2.1" id="addressed-splicing"><span class="header-section-number">4.2.1</span> Addressed Splicing<a href="#addressed-splicing" class="self-link"></a></h3>
<p>In the same way that <code class="sourceCode cpp"><span class="op">&amp;</span>C<span class="op">::</span>mem</code>
can produce a pointer, pointer to member data, pointer to function, or
pointer to member function depending on what
<code class="sourceCode cpp">mem</code> refers to, <code class="sourceCode cpp"><span class="op">&amp;[:</span> r <span class="op">:]</span></code>
can likewise produce the same set of pointers if
<code class="sourceCode cpp">r</code> is a reflection of a suitable
entity:</p>
<ul>
<li>If <code class="sourceCode cpp">r</code> is a reflection of a static
data member or a variable, <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
is a pointer.</li>
<li>Otherwise if <code class="sourceCode cpp">r</code> is a reflection
of a non-static data member, <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
is a pointer to data member.</li>
<li>Otherwise, if <code class="sourceCode cpp">r</code> is a reflection
of a static member function, a function, or a non-static member function
with an explicit object parameter, <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
is a pointer to function</li>
<li>Otherwise, if <code class="sourceCode cpp">r</code> is a reflection
of a non-static member function with an implicit object parameter, <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
is a pointer to member function.</li>
<li>Otherwise, if <code class="sourceCode cpp">r</code> is a reflection
of a function template, <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
is the address of that overload set - which would then require external
context to resolve as usual.</li>
</ul>
<p>For most members, this doesn’t even require any additional wording
since that’s just what you get when you take the address of the splice
based on the current rules we have today.</p>
<p>Now, there are a couple interesting cases to point out when <code class="sourceCode cpp"><span class="op">&amp;[:</span>r<span class="op">:]</span></code>
isn’t just the same as <code class="sourceCode cpp"><span class="op">&amp;</span>X<span class="op">::</span>f</code>.</p>
<p>When <code class="sourceCode cpp">r</code> is a reflection of a
function or function template that is part of an overload set, overload
resolution will not consider the whole overload set, just the specific
function or function template that <code class="sourceCode cpp">r</code>
represents:</p>
<div class="std">
<blockquote>
<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="kw">struct</span> C <span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="dt">void</span> f<span class="op">(</span>T<span class="op">)</span>; <span class="co">// #1</span></span>
<span id="cb40-3"><a href="#cb40-3" 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>; <span class="co">// #2</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="op">(</span>C<span class="op">::*</span>p1<span class="op">)(</span><span class="dt">int</span><span class="op">)</span> <span class="op">=</span> <span class="op">&amp;</span>C<span class="op">::</span>f;  <span class="co">// error: ambiguous</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f1 <span class="op">=</span></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">((</span>members_of<span class="op">(^^</span>C<span class="op">)</span> <span class="op">|</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>is_function_template<span class="op">)).</span>front<span class="op">())</span>;</span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f2 <span class="op">=</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">((</span>members_of<span class="op">(^^</span>C<span class="op">)</span> <span class="op">|</span></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>is_function<span class="op">)).</span>front<span class="op">())</span>;</span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="op">(</span>C<span class="op">::*</span>p2<span class="op">)(</span><span class="dt">int</span><span class="op">)</span> <span class="op">=</span> <span class="op">&amp;[:</span>f1<span class="op">:]</span>; <span class="co">// ok, refers to C::f&lt;int&gt; (#1)</span></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="op">(</span>C<span class="op">::*</span>p3<span class="op">)(</span><span class="dt">int</span><span class="op">)</span> <span class="op">=</span> <span class="op">&amp;[:</span>f2<span class="op">:]</span>; <span class="co">// ok, refers to C::f      (#2)</span></span></code></pre></div>
</blockquote>
</div>
<p>Another interesting question is what does this mean when
<code class="sourceCode cpp">r</code> is the reflection of a constructor
or destructor? Consider the type:</p>
<div class="std">
<blockquote>
<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="kw">struct</span> X <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>    X<span class="op">(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And let <code class="sourceCode cpp">rc</code> be a reflection of the
constructor and <code class="sourceCode cpp">rd</code> be a reflection
of the destructor. The sensible syntax and semantics for how you would
use <code class="sourceCode cpp">rc</code> and
<code class="sourceCode cpp">rd</code> should be as follows:</p>
<div class="std">
<blockquote>
<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="kw">auto</span> x <span class="op">=</span> <span class="op">[:</span> rc <span class="op">:](</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">)</span>; <span class="co">// gives you an X</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>x<span class="op">.[:</span> rd <span class="op">:]()</span>;            <span class="co">// destroys it</span></span></code></pre></div>
</blockquote>
</div>
<p>Or, with pointers:</p>
<div class="std">
<blockquote>
<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="kw">auto</span> pc <span class="op">=</span> <span class="op">&amp;[:</span> rc <span class="op">:]</span>;</span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> pd <span class="op">=</span> <span class="op">&amp;[:</span> rd <span class="op">:]</span>;</span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> x <span class="op">=</span> <span class="op">(*</span>pc<span class="op">)(</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">)</span>;   <span class="co">// gives you an X</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>x<span class="op">.*</span>pd<span class="op">)()</span>;              <span class="co">// destroys it</span></span></code></pre></div>
</blockquote>
</div>
<p>That is, splicing a constructor behaves like a free function that
produces an object of that type, so <code class="sourceCode cpp"><span class="op">&amp;[:</span> rc <span class="op">:]</span></code>
has type <code class="sourceCode cpp">X<span class="op">(*)(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span></code>.
On the other hand, splicing a destructor behaves like a regular member
function, so <code class="sourceCode cpp"><span class="op">&amp;[:</span> rd <span class="op">:]</span></code>
has type <code class="sourceCode cpp"><span class="dt">void</span> <span class="op">(</span>X<span class="op">::*)()</span></code>.</p>
<p>However, we are <em>not</em> proposing splicing constructors or
destructors at the moment.</p>
<h3 data-number="4.2.2" id="limitations"><span class="header-section-number">4.2.2</span> Limitations<a href="#limitations" class="self-link"></a></h3>
<p>Splicers can appear in many contexts, but our implementation
experience has uncovered a small set of circumstances in which a splicer
must be disallowed. Mostly these are because any entity designated by a
splicer can be dependent on a template argument, so any context in which
the language already disallows a dependent name must also disallow a
dependent splicer. It also becomes possible for the first time to have
the “name” of a namespace or concept become dependent on a template
argument. Our implementation experience has helped to sort through which
uses of these dependent names pose no difficulties, and which must be
disallowed.</p>
<p>This proposal places the following limitations on splicers.</p>
<h4 data-number="4.2.2.1" id="splicing-reflections-of-constructors"><span class="header-section-number">4.2.2.1</span> Splicing reflections of
constructors<a href="#splicing-reflections-of-constructors" class="self-link"></a></h4>
<p>Iterating over the members of a class (e.g., using <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>members_of</code>)
allows one, for the first time, to obtain “handles” representing
constructors. An immediate question arises of whether it’s possible to
reify these constructors to construct objects, or even to take their
address. While we are very interested in exploring these ideas, we defer
their discussion to a future paper; this proposal disallows splicing a
reflection of a constructor (or constructor template) in any
context.</p>
<h4 data-number="4.2.2.2" id="splicing-namespaces-in-namespace-definitions"><span class="header-section-number">4.2.2.2</span> Splicing namespaces in
namespace definitions<a href="#splicing-namespaces-in-namespace-definitions" class="self-link"></a></h4>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> A <span class="op">{}</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info NS_A <span class="op">=</span> <span class="op">^^</span>A;</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> B <span class="op">{</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> <span class="op">[:</span>NS_A<span class="op">:]</span> <span class="op">{</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> fn<span class="op">()</span>;  <span class="co">// Is this &#39;::A::fn&#39; or &#39;::B::A::fn&#39; ?</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>
</blockquote>
</div>
<p>We found no satisfying answer as to how to interpret examples like
the one given above. Neither did we find motivating use cases: many of
the “interesting” uses for reflections of namespaces are either to
introspect their members, or to pass them as template arguments - but
the above example does nothing to help with introspection, and neither
can namespaces be reopened within any dependent context. Rather than
choose between unintuitive options for a syntax without a motivating use
case, we are disallowing splicers from appearing in the opening of a
namespace.</p>
<h4 data-number="4.2.2.3" id="splicing-namespaces-in-using-directives-and-using-enum-declarators"><span class="header-section-number">4.2.2.3</span> Splicing namespaces in
using-directives and using-enum-declarators<a href="#splicing-namespaces-in-using-directives-and-using-enum-declarators" class="self-link"></a></h4>
<div class="std">
<blockquote>
<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>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="dt">void</span> fn1<span class="op">()</span> <span class="op">{</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="kw">enum</span> <span class="op">[:</span>R<span class="op">:]::</span>EnumCls;  <span class="co">// #1</span></span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="dt">void</span> fn2<span class="op">()</span> <span class="op">{</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="kw">namespace</span> <span class="op">[:</span>R<span class="op">:]</span>;      <span class="co">// #2</span></span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>C++20 already disallowed dependent enumeration types from appearing
in <em>using-enum-declarators</em> (as in #1), as it would otherwise
force the parser to consider every subsequent identifier as possibly a
member of the substituted enumeration type. We extend this limitation to
splices of dependent reflections of enumeration types, and further
disallow the use of dependent reflections of namespaces in
<em>using-directives</em> (as in #2) following the same principle.</p>
<h4 data-number="4.2.2.4" id="splicing-concepts-in-declarations-of-template-parameters"><span class="header-section-number">4.2.2.4</span> Splicing concepts in
declarations of template parameters<a href="#splicing-concepts-in-declarations-of-template-parameters" class="self-link"></a></h4>
<div class="std">
<blockquote>
<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> T<span class="op">&gt;</span> <span class="kw">concept</span> C <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">requires</span> <span class="kw">true</span>; <span class="op">}</span>;</span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="kw">struct</span> Outer <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">template</span> <span class="op">[:</span>R<span class="op">:]</span> S<span class="op">&gt;</span> <span class="kw">struct</span> Inner <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>What kind of parameter is <code class="sourceCode cpp">S</code>? If
<code class="sourceCode cpp">R</code> represents a class template, then
it is a non-type template parameter of deduced type, but if
<code class="sourceCode cpp">R</code> represents a concept, it is a type
template parameter. There is no other circumstance in the language for
which it is not possible to decide at parse time whether a template
parameter is a type or a non-type, and we don’t wish to introduce one
for this use case.</p>
<p>The most obvious solution would be to introduce a <code class="sourceCode cpp"><span class="kw">concept</span> <span class="op">[:</span>R<span class="op">:]</span></code>
syntax that requires that <code class="sourceCode cpp">R</code> reflect
a concept, and while this could be added going forward, we weren’t
convinced of its value at this time - especially since the above can
easily be rewritten:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="kw">struct</span> Outer <span class="op">{</span></span>
<span id="cb47-2"><a href="#cb47-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 class="kw">requires</span> <span class="kw">template</span> <span class="op">[:</span>R<span class="op">:]&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Inner <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>We are resolving this ambiguity by simply disallowing a reflection of
a concept, whether dependent or otherwise, from being spliced in the
declaration of a template parameter (thus in the above example, the
parser can assume that <code class="sourceCode cpp">S</code> is a
non-type parameter).</p>
<h4 data-number="4.2.2.5" id="splicing-class-members-as-designators-in-designated-initializer-lists"><span class="header-section-number">4.2.2.5</span> Splicing class members as
designators in designated-initializer-lists<a href="#splicing-class-members-as-designators-in-designated-initializer-lists" class="self-link"></a></h4>
<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="kw">struct</span> S <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> S s <span class="op">=</span> <span class="op">{.[:^^</span>S<span class="op">::</span>a<span class="op">:]</span> <span class="op">=</span> <span class="dv">2</span><span class="op">}</span>;</span></code></pre></div>
<p>Although we would like for splices of class members to be usable as
designators in an initializer-list, we lack implementation experience
with the syntax and would first like to verify that there are no issues
with dependent reflections. We are very likely to propose this as an
extension in a future paper.</p>
<h3 data-number="4.2.3" id="range-splicers"><span class="header-section-number">4.2.3</span> Range Splicers<a href="#range-splicers" class="self-link"></a></h3>
<p>The splicers described above all take a single object of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
(described in more detail below). However, there are many cases where we
don’t have a single reflection, we have a range of reflections - and we
want to splice them all in one go. For that, the predecessor to this
paper, <span class="citation" data-cites="P1240R0"><a href="https://wg21.link/p1240r0" role="doc-biblioref">[P1240R0]</a></span>, proposed an additional form
of splicer: a range splicer.</p>
<p>Construct the <a href="#converting-a-struct-to-a-tuple">struct-to-tuple</a> example from
above. It was demonstrated using a single splice, but it would be
simpler if we had a range splice:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>With Single Splice</strong>
</div></th>
<th><div style="text-align:center">
<strong>With Range Splice</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> members <span class="op">=</span> nonstatic_data_members_of<span class="op">(^^</span>T<span class="op">)</span>;</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> indices <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>array<span class="op">&lt;</span><span class="dt">int</span>, members<span class="op">.</span>size<span class="op">()&gt;</span> indices;</span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>ranges<span class="op">::</span>iota<span class="op">(</span>indices, <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> indices;</span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="op">[...</span>Is<span class="op">]</span> <span class="op">=</span> indices;</span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>make_tuple<span class="op">(</span>t<span class="op">.[:</span> members<span class="op">[</span>Is<span class="op">]</span> <span class="op">:]...)</span>;</span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> members <span class="op">=</span> nonstatic_data_members_of<span class="op">(^^</span>T<span class="op">)</span>;</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>make_tuple<span class="op">(</span>t<span class="op">.[:</span> <span class="op">...</span>members <span class="op">:]...)</span>;</span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>A range splice, <code class="sourceCode cpp"><span class="op">[:</span> <span class="op">...</span> r <span class="op">:]</span></code>,
would accept as its argument a constant range of
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>,
<code class="sourceCode cpp">r</code>, and would behave as an unexpanded
pack of splices. So the above expression</p>
<div class="std">
<blockquote>
<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>make_tuple<span class="op">(</span>t<span class="op">.[:</span> <span class="op">...</span> members <span class="op">:]...)</span></span></code></pre></div>
</blockquote>
</div>
<p>would evaluate as</p>
<div class="std">
<blockquote>
<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>make_tuple<span class="op">(</span>t<span class="op">.[:</span>members<span class="op">[</span><span class="dv">0</span><span class="op">]:]</span>, t<span class="op">.[:</span>members<span class="op">[</span><span class="dv">1</span><span class="op">]:]</span>, <span class="op">...</span>, t<span class="op">.[:</span>members<span class="op">[</span><em>N-1</em><span class="op">]:])</span></span></code></pre></div>
</blockquote>
</div>
<p>This is a very useful facility indeed!</p>
<p>However, range splicing of dependent arguments is at least an order
of magnitude harder to implement than ordinary splicing. We think that
not including range splicing gives us a better chance of having
reflection in C++26. Especially since, as this paper’s examples
demonstrate, a lot can be done without them.</p>
<p>Another way to work around a lack of range splicing would be to
implement <code class="sourceCode cpp">with_size<span class="op">&lt;</span>N<span class="op">&gt;(</span>f<span class="op">)</span></code>,
which would behave like <code class="sourceCode cpp">f<span class="op">(</span>integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="dv">0</span><span class="op">&gt;{}</span>, integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="dv">1</span><span class="op">&gt;{}</span>, <span class="op">...</span>, integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, N<span class="op">-</span><span class="dv">1</span><span class="op">&gt;{})</span></code>.
Which is enough for a tolerable implementation:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-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="op">&gt;</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> struct_to_tuple<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> members <span class="op">=</span> nonstatic_data_members_of<span class="op">(^^</span>T<span class="op">)</span>;</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> with_size<span class="op">&lt;</span>members<span class="op">.</span>size<span class="op">()&gt;([&amp;](</span><span class="kw">auto</span><span class="op">...</span> Is<span class="op">){</span></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>make_tuple<span class="op">(</span>t<span class="op">.[:</span> members<span class="op">[</span>Is<span class="op">]</span> <span class="op">:]...)</span>;</span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.2.4" id="syntax-discussion-1"><span class="header-section-number">4.2.4</span> Syntax discussion<a href="#syntax-discussion-1" class="self-link"></a></h3>
<p>Early discussions of splice-like constructs (related to the TS
design) considered using <code class="sourceCode cpp"><span class="cf">unreflexpr</span><span class="op">(...)</span></code>
for that purpose. <span class="citation" data-cites="P1240R0"><a href="https://wg21.link/p1240r0" role="doc-biblioref">[P1240R0]</a></span> adopted that option for
<em>expression</em> splicing, observing that a single splicing syntax
could not viably be parsed (some disambiguation is needed to distinguish
types and templates). SG-7 eventually agreed to adopt the <code class="sourceCode cpp"><span class="op">[:</span> <span class="op">...</span> <span class="op">:]</span></code>
syntax — with disambiguating tokens such as
<code class="sourceCode cpp"><span class="kw">typename</span></code>
where needed — which is a little lighter and more distinctive.</p>
<p>We propose
<code class="sourceCode cpp"><span class="op">[:</span></code> and
<code class="sourceCode cpp"><span class="op">:]</span></code> be single
tokens rather than combinations of
<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>. Among
others, it simplifies the handling of expressions like <code class="sourceCode cpp">arr<span class="op">[[:</span><span class="at">refl</span><span class="op">():]]</span></code>.
On the flip side, it requires a special rule like the one that was made
to handle
<code class="sourceCode cpp"><span class="op">&lt;::</span></code> to
leave the meaning of <code class="sourceCode cpp">arr<span class="op">[::</span>N<span class="op">]</span></code>
unchanged and another one to avoid breaking a (somewhat useless)
attribute specifier of the form <code class="sourceCode cpp"><span class="op">[[</span><span class="kw">using</span><span class="at"> ns</span><span class="op">:]]</span></code>.</p>
<p>A syntax that is delimited on the left and right is useful here
because spliced expressions may involve lower-precedence operators.
Additionally, it’s important that the left- and right-hand delimiters
are different so as to allow nested splices when that comes up.</p>
<p>However, there are other possibilities. For example, now that
<code><span class="op">$</span></code> or
<code><span class="op">@</span></code> are available in the basic source
character set, we might consider those. One option that was recently
brought up was <code class="sourceCode cpp"><span class="op">@</span> <em>primary-expression</em></code>
which would allow writing
<code class="sourceCode cpp"><span class="op">@</span>e</code> for the
simple <code class="sourceCode cpp"><em>identifier</em></code> splices
but for the more complex operations still require parenthesizing for
readability. <code class="sourceCode cpp"><span class="op">$</span><span class="op">&lt;</span><em>expr</em><span class="op">&gt;</span></code>
is somewhat natural to those of us that have used systems where
<code><span class="op">$</span></code> is used to expand placeholders in
document templates:</p>
<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="op">[::]</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="op">[:</span> <span class="op">:]</span></code>
(with space)</strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="op">@</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp"><span class="er">$</span></code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode cpp"><span class="op">[:</span>refl<span class="op">:]</span></code></td>
<td><code class="sourceCode cpp"><span class="op">[:</span> refl <span class="op">:]</span></code></td>
<td><code class="sourceCode cpp"><span class="op">@</span>refl</code></td>
<td><code class="sourceCode cpp"><span class="er">$</span>refl</code></td>
</tr>
<tr class="even">
<td><code class="sourceCode cpp"><span class="op">[:</span>type_of<span class="op">(</span>refl<span class="op">):]</span></code></td>
<td><code class="sourceCode cpp"><span class="op">[:</span> type_of<span class="op">(</span>refl<span class="op">)</span> <span class="op">:]</span></code></td>
<td><code class="sourceCode cpp"><span class="op">@(</span>type_of<span class="op">(</span>refl<span class="op">))</span></code></td>
<td><code class="sourceCode cpp"><span class="er">$</span><span class="op">(</span>type_of<span class="op">(</span>refl<span class="op">))</span></code></td>
</tr>
</tbody>
</table>
<p>There are two other pieces of functionality that we will probably
need syntax for in the future:</p>
<ul>
<li>code injection (of whatever form), and</li>
<li>annotations (reflectable attributes, as values. <span class="citation" data-cites="P1887R1"><a href="https://wg21.link/p1887r1" role="doc-biblioref">[P1887R1]</a></span> suggested
<code class="sourceCode cpp"><span class="op">+</span></code> as an
annotation introducer, but
<code class="sourceCode cpp"><span class="op">+</span></code> can begin
an expression so another token is probably better. See also: <a href="https://lists.isocpp.org/sg7/2023/10/0450.php">this
thread</a>).</li>
</ul>
<p>So any syntax discussion needs to consider the entirety of the
feature.</p>
<p>The prefixes
<code class="sourceCode cpp"><span class="kw">typename</span></code> and
<code class="sourceCode cpp"><span class="kw">template</span></code> are
only strictly needed in some cases where the operand of the splice is a
dependent expression. In our proposal, however, we only make
<code class="sourceCode cpp"><span class="kw">typename</span></code>
optional in the same contexts where it would be optional for qualified
names with dependent name qualifiers. That has the advantage to catch
unfortunate errors while keeping a single rule and helping human readers
parse the intended meaning of otherwise ambiguous constructs.</p>
<h2 data-number="4.3" id="stdmetainfo"><span class="header-section-number">4.3</span> <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code><a href="#stdmetainfo" class="self-link"></a></h2>
<p>The type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
can be defined as follows:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> meta <span class="op">{</span></span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> info <span class="op">=</span> <span class="kw">decltype</span><span class="op">(^^::)</span>;</span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>In our initial proposal a value of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
can represent:</p>
<ul>
<li>any (C++) type and type alias</li>
<li>any function (or member function)</li>
<li>any variable, static data member, or structured binding</li>
<li>any non-static data member</li>
<li>any enumerator</li>
<li>any template</li>
<li>any namespace (including the global namespace) or namespace
alias</li>
<li>any object that is a <em>permitted result of a constant
expression</em></li>
<li>any value with <em>structural type</em> that is a permitted result
of a constant expression</li>
<li>the null reflection (when default-constructed)</li>
</ul>
<p>We for now restrict the space of reflectable values to those of
structural type in order to meet two requirements:</p>
<ol type="1">
<li>The compiler must know how to mangle any reflectable value (i.e.,
when a reflection thereof is used as a template argument).</li>
<li>The compiler must know how to compare any two reflectable values,
ideally without interpreting user-defined comparison operators (i.e., to
implement comparison between reflections).</li>
</ol>
<p>Values of structural types can already be used as template arguments
(so implementations must already know how to mangle them), and the
notion of <em>template-argument-equivalent</em> values defined on the
class of structural types helps guarantee that <code class="sourceCode cpp"><span class="op">&amp;</span>fn<span class="op">&lt;^^</span>value1<span class="op">&gt;</span> <span class="op">==</span> <span class="op">&amp;</span>fn<span class="op">&lt;^^</span>value2<span class="op">&gt;</span></code>
if and only if <code class="sourceCode cpp"><span class="op">&amp;</span>fn<span class="op">&lt;</span>value1<span class="op">&gt;</span> <span class="op">==</span> <span class="op">&amp;</span>fn<span class="op">&lt;</span>value2<span class="op">&gt;</span></code>.</p>
<p>Notably absent at this time are reflections of expressions. For
example, one might wish to walk over the subexpressions of a function
call:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-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="op">&gt;</span> <span class="dt">void</span> fn<span class="op">(</span>T<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> call <span class="op">=</span> <span class="op">^^(</span>fn<span class="op">(</span><span class="dv">42</span><span class="op">))</span>;</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span></span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a>      template_arguments_of<span class="op">(</span>function_of<span class="op">(</span>call<span class="op">))[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span></span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Previous revisions of this proposal suggested limited support for
reflections of constant expressions. The introduction of side effects
from constant evaluations (by this very paper), however, renders this
roughly as difficult for constant expressions as it is for non-constant
expressions. We instead defer all expression reflection to a future
paper, and only present value and object reflection in the present
proposal.</p>
<h3 data-number="4.3.1" id="comparing-reflections"><span class="header-section-number">4.3.1</span> Comparing reflections<a href="#comparing-reflections" class="self-link"></a></h3>
<p>The type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
is a <em>scalar</em> type for which equality and inequality are
meaningful, but for which no ordering relation is defined.</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span><span class="dt">int</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span><span class="dt">int</span> <span class="op">!=</span> <span class="op">^^</span><span class="kw">const</span> <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span><span class="dt">int</span> <span class="op">!=</span> <span class="op">^^</span><span class="dt">int</span> <span class="op">&amp;)</span>;</span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Alias <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span><span class="dt">int</span> <span class="op">!=</span> <span class="op">^^</span>Alias<span class="op">)</span>;</span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span><span class="dt">int</span> <span class="op">==</span> dealias<span class="op">(^^</span>Alias<span class="op">))</span>;</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="kw">namespace</span> AliasNS <span class="op">=</span> <span class="op">::</span>std;</span>
<span id="cb56-10"><a href="#cb56-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^::</span>std <span class="op">!=</span> <span class="op">^^</span>AliasNS<span class="op">)</span>;</span>
<span id="cb56-11"><a href="#cb56-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^::</span> <span class="op">==</span> parent_of<span class="op">(^^::</span>std<span class="op">))</span>;</span></code></pre></div>
</blockquote>
</div>
<p>When the
<code class="sourceCode cpp"><span class="op">^^</span></code> operator
is followed by an <em>id-expression</em>, the resulting <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
represents the entity named by the expression. Such reflections are
equivalent only if they reflect the same entity.</p>
<div class="std">
<blockquote>
<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><span class="dt">int</span> x;</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span> <span class="kw">static</span> <span class="dt">int</span> y; <span class="op">}</span>;</span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>x <span class="op">==</span> <span class="op">^^</span>x<span class="op">)</span>;</span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>x <span class="op">!=</span> <span class="op">^^</span>S<span class="op">::</span>y<span class="op">)</span>;</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>S<span class="op">::</span>y <span class="op">==</span> static_data_members_of<span class="op">(^^</span>S<span class="op">)[</span><span class="dv">0</span><span class="op">])</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Special rules apply when comparing certain kinds of reflections. A
reflection of an alias compares equal to another reflection if and only
if they are both aliases, alias the same type, and share the same name
and scope. In particular, these rules allow e.g., <code class="sourceCode cpp">fn<span class="op">&lt;^^</span>std<span class="op">::</span>string<span class="op">&gt;</span></code>
to refer to the same instantiation across translation units.</p>
<div class="std">
<blockquote>
<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="kw">using</span> Alias1 <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Alias2 <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> Alias1 <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">^^</span>Alias;</span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>Alias1 <span class="op">==</span> <span class="op">^^</span>Alias1<span class="op">)</span>;</span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>Alias1 <span class="op">!=</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>Alias1 <span class="op">!=</span> <span class="op">^^</span>Alias2<span class="op">)</span>;</span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>Alias1 <span class="op">!=</span> fn<span class="op">())</span>;</span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>A reflection of an object (including variables) does not compare
equally to a reflection of its value. Two values of different types
never compare equally.</p>
<div class="std">
<blockquote>
<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="kw">constexpr</span> <span class="dt">int</span> i <span class="op">=</span> <span class="dv">42</span>, j <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info r <span class="op">=</span> <span class="op">^^</span>i, s <span class="op">=</span> <span class="op">^^</span>i;</span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>r <span class="op">==</span> r <span class="op">&amp;&amp;</span> r <span class="op">==</span> s<span class="op">)</span>;</span>
<span id="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>i <span class="op">!=</span> <span class="op">^^</span>j<span class="op">)</span>;  <span class="co">// &#39;i&#39; and &#39;j&#39; are different entities.</span></span>
<span id="cb59-7"><a href="#cb59-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>constant_of<span class="op">(^^</span>i<span class="op">)</span> <span class="op">==</span> constant_of<span class="op">(^^</span>j<span class="op">))</span>;    <span class="co">// Two equivalent values.</span></span>
<span id="cb59-8"><a href="#cb59-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>i <span class="op">!=</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_object<span class="op">(</span>i<span class="op">))</span>      <span class="co">// A variable is distinct from the</span></span>
<span id="cb59-9"><a href="#cb59-9" aria-hidden="true" tabindex="-1"></a>                                                        <span class="co">// object it designates.</span></span>
<span id="cb59-10"><a href="#cb59-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>i <span class="op">!=</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span><span class="dv">42</span><span class="op">))</span>;  <span class="co">// A reflection of an object</span></span>
<span id="cb59-11"><a href="#cb59-11" aria-hidden="true" tabindex="-1"></a>                                                        <span class="co">// is not the same as its value.</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.3.2" id="the-associated-stdmeta-namespace"><span class="header-section-number">4.3.2</span> The associated
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
namespace<a href="#the-associated-stdmeta-namespace" class="self-link"></a></h3>
<p>The namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code> is
an associated namespace of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
which allows standard library meta functions to be invoked without
explicit qualification. For example:</p>
<div class="std">
<blockquote>
<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><span class="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string name2 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>identifier_of<span class="op">(^^</span>S<span class="op">)</span>;  <span class="co">// Okay.</span></span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string name1 <span class="op">=</span> identifier_of<span class="op">(^^</span>S<span class="op">)</span>;             <span class="co">// Also okay.</span></span></code></pre></div>
</blockquote>
</div>
<p>Default constructing or value-initializing an object of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
gives it a null reflection value. A null reflection value is equal to
any other null reflection value and is different from any other
reflection that refers to one of the mentioned entities. For
example:</p>
<div class="std">
<blockquote>
<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><span class="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">()</span> <span class="op">==</span> std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">())</span>;</span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">()</span> <span class="op">!=</span> <span class="op">^^</span>S<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.3.3" id="consteval-only"><span class="header-section-number">4.3.3</span> Consteval-only<a href="#consteval-only" class="self-link"></a></h3>
<p>It’s important that <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
not be allowed to propagate to runtime. This has no meaning, so it would
be ideal to simply prevent the type from being usable to runtime in any
way whatsoever.</p>
<p>We propose doing this by saying that <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
and all types compounded from it (meaning anythig from
<code class="sourceCode cpp">info<span class="op">*</span></code> to
classes with <code class="sourceCode cpp">info</code> members,
e.g. <code class="sourceCode cpp">tuple<span class="op">&lt;</span>info<span class="op">&gt;</span></code>
or <code class="sourceCode cpp">vector<span class="op">&lt;</span>info<span class="op">&gt;</span></code>)
are consteval-only types. We then add two kinds of restrictions (both of
which are necessary):</p>
<ul>
<li>an <em>object</em> of consteval-only type can only exist at compile
time.</li>
<li>an <em>expression</em> with an operand of consteval-only type can
only be evaluated at compile time.</li>
</ul>
<p>The first we can achieve by requiring such objects to either be part
of a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
variable, a template parameter object, or have its lifetime entirely
within constant evaluation. The latter we can achieve by plugging into
the already-existing immediate escalating machinery that we have for
immediate functions to also consider consteval-only types as
escalating.</p>
<p>This has an interesting consequence that necessitates an
<code class="sourceCode cpp">is_consteval_only</code> type trait that we
discovered. In libc++,
<code class="sourceCode cpp">std<span class="op">::</span>sort</code> is
implemented <a href="https://github.com/llvm/llvm-project/blob/acc6bcdc504ad2e8c09a628dc18de0067f7344b8/libcxx/include/__algorithm/sort.h">like
this</a>:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> _AlgPolicy, <span class="kw">class</span> _RandomAccessIterator, <span class="kw">class</span> _Comp<span class="op">&gt;</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 <span class="dt">void</span></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>__sort_impl<span class="op">(</span>_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp<span class="op">&amp;</span> __comp<span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>__debug_randomize_range<span class="op">&lt;</span>_AlgPolicy<span class="op">&gt;(</span>__first, __last<span class="op">)</span>;</span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>__libcpp_is_constant_evaluated<span class="op">())</span> <span class="op">{</span></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__partial_sort<span class="op">&lt;</span>_AlgPolicy<span class="op">&gt;(</span></span>
<span id="cb62-8"><a href="#cb62-8" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__first<span class="op">)</span>, std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__last<span class="op">)</span>, std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__last<span class="op">)</span>, __comp<span class="op">)</span>;</span>
<span id="cb62-9"><a href="#cb62-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb62-10"><a href="#cb62-10" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__sort_dispatch<span class="op">&lt;</span>_AlgPolicy<span class="op">&gt;(</span>std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__first<span class="op">)</span>, std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__last<span class="op">)</span>, __comp<span class="op">)</span>;</span>
<span id="cb62-11"><a href="#cb62-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb62-12"><a href="#cb62-12" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>__check_strict_weak_ordering_sorted<span class="op">(</span>std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__first<span class="op">)</span>, std<span class="op">::</span>__unwrap_iter<span class="op">(</span>__last<span class="op">)</span>, __comp<span class="op">)</span>;</span>
<span id="cb62-13"><a href="#cb62-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>During constant evaluation, we call
<code class="sourceCode cpp">__partial_sort</code> (which is
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>).
Otherwise, we call <code class="sourceCode cpp">__sort_dispatch</code>
(which is not). If we instantiate
<code class="sourceCode cpp">__sort_impl</code> with a
<code class="sourceCode cpp">_RandomAccessIterator</code> type of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">*</span></code>,
then this eventually ends up also instantiating <code class="sourceCode cpp">std<span class="op">::</span>__introsort</code>
(<a href="https://github.com/llvm/llvm-project/blob/acc6bcdc504ad2e8c09a628dc18de0067f7344b8/libcxx/include/__algorithm/sort.h#L715">here</a>,
also not
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>)
which in the body does this:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> _AlgPolicy, <span class="kw">class</span> _Compare, <span class="kw">class</span> _RandomAccessIterator, <span class="dt">bool</span> _UseBitSetPartition<span class="op">&gt;</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> __introsort<span class="op">(</span>_RandomAccessIterator __first,</span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>                 _RandomAccessIterator __last,</span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>                 _Compare __comp,</span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">typename</span> iterator_traits<span class="op">&lt;</span>_RandomAccessIterator<span class="op">&gt;::</span>difference_type __depth,</span>
<span id="cb63-6"><a href="#cb63-6" aria-hidden="true" tabindex="-1"></a>                 <span class="dt">bool</span> __leftmost <span class="op">=</span> <span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb63-7"><a href="#cb63-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb63-8"><a href="#cb63-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb63-9"><a href="#cb63-9" aria-hidden="true" tabindex="-1"></a>    difference_type __len <span class="op">=</span> __last <span class="op">-</span> __first;</span>
<span id="cb63-10"><a href="#cb63-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb63-11"><a href="#cb63-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb63-12"><a href="#cb63-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The expression <code class="sourceCode cpp">__last <span class="op">-</span> __first</code>,
because these are <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">*</span></code>s,
must be a constant. Because it’s not here
(<code class="sourceCode cpp">__first</code> and
<code class="sourceCode cpp">__last</code> are just function
parameters), that triggers the immediate-escalation machinery from <span class="title"><span class="citation" data-cites="P2564R3"><a href="https://wg21.link/p2564r3" role="doc-biblioref">[P2564R3]
(consteval needs to propagate up)</a></span></span> (before that paper,
it would have been ill-formed on the spot). But because
<code class="sourceCode cpp">__introsort</code> is not
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>,
propagation fails at that point, and the program is ill-formed.</p>
<p>Even though during we would’ve never actually gotten to this code
during runtime.</p>
<p>Let’s go back to the problem function and reduce it and un-uglify the
names:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> RandomAccessIterator<span class="op">&gt;</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> sort<span class="op">(</span>RandomAccessIterator first, RandomAccessIterator last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__consteval_only_sort<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__runtime_only_sort<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb64-8"><a href="#cb64-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>At issue is that
<code class="sourceCode cpp">__runtime_only_sort</code> isn’t
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
and instantiating it with <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">*</span></code>
fails.</p>
<p>We thought of a few ways to approach this issue:</p>
<p>We could just mark
<code class="sourceCode cpp">__runtime_only_sort</code>
<code class="sourceCode cpp"><span class="kw">constexpr</span></code> —
but marking something
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
that we explicitly do not want to evaluate during constant evaluation
time (as our rename makes obvious), seems like a bad approach. It’s a
confusing annotation at best.</p>
<p>We considered changing the semantics of <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">consteval</span></code>
so that it could discard (in the <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span></code>
sense) the non-taken branch if actually evaluated during constant
evaluation time. In this case, that would avoid having to instantiate
<code class="sourceCode cpp">__runtime_only_sort<span class="op">&lt;</span>meta<span class="op">::</span>info<span class="op">*&gt;</span></code>
and we’d be okay. But that kind of change seemed very complicated.</p>
<p>We also considered just implicitly making function templates with any
function parameter having consteval-only type be
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
anyway. That is,
<code class="sourceCode cpp">__runtime_only_sort</code>, despite the
name, actually is
<code class="sourceCode cpp"><span class="kw">consteval</span></code>.
That also seemed a bit adventurous, and while it addresses this
particular issue, we weren’t sure what other possible issues might come
up.</p>
<p>Instead, we’re taking a simpler and easier-to-justify approach:
adding a new type trait to detect whether a type is consteval-only (a
trait which is fairly straightforward to implement on top of the other
facilities provided in this proposal). With that trait, the fix is
simple (if perhaps surprising to the reader): explicitly discard the
runtime branch:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> RandomAccessIterator<span class="op">&gt;</span></span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> sort<span class="op">(</span>RandomAccessIterator first, RandomAccessIterator last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__consteval_only_sort<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb65-5"><a href="#cb65-5" 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><span class="kw">not</span> is_consteval_only_type<span class="op">(^^</span>RandomAccessIterator<span class="op">))</span> <span class="op">{</span></span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>__runtime_only_sort<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb65-7"><a href="#cb65-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb65-8"><a href="#cb65-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h2 data-number="4.4" id="metafunctions"><span class="header-section-number">4.4</span> Metafunctions<a href="#metafunctions" class="self-link"></a></h2>
<p>We propose a number of metafunctions declared in namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code> to
operator on reflection values. Adding metafunctions to an implementation
is expected to be relatively “easy” compared to implementing the core
language features described previously. However, despite offering a
normal consteval C++ function interface, each on of these relies on
“compiler magic” to a significant extent.</p>
<h3 data-number="4.4.1" id="constant-evaluation-order"><span class="header-section-number">4.4.1</span> Constant evaluation order<a href="#constant-evaluation-order" class="self-link"></a></h3>
<p>In C++23, “constant evaluation” produces pure values without
observable side-effects and thus the order in which constant-evaluation
occurs is immaterial. In fact, while the language is designed to permit
constant evaluation to happen at compile time, an implementation is not
strictly required to take advantage of that possibility.</p>
<p>Some of the proposed metafunctions, however, have side-effects that
have an effect on the remainder of the program. For example, we provide
a <code class="sourceCode cpp">define_aggregate</code> metafunction that
provides a definition for a given class. Clearly, we want the effect of
calling that metafunction to be “prompt” in a lexical-order sense. For
example:</p>
<div class="std">
<blockquote>
<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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S;</span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span></span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(^^</span>S, <span class="op">{})</span>;</span>
<span id="cb66-7"><a href="#cb66-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb66-8"><a href="#cb66-8" aria-hidden="true" tabindex="-1"></a>  S s;  <span class="co">// S should be defined at this point.</span></span>
<span id="cb66-9"><a href="#cb66-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Hence this proposal also introduces constraints on constant
evaluation as follows…</p>
<p>First, consteval blocks (from <span class="citation" data-cites="P3289R1"><a href="https://wg21.link/p3289r1" role="doc-biblioref">[P3289R1]</a></span>) have the property that their
evaluation must occur and must succeed in a valid C++ program. We
require that a programmer can count on those evaluations occurring
exactly once and completing at translation time.</p>
<p>Second, we sequence consteval blocks within the lexical order.
Specifically, we require that the evaluation of a non-dependent
consteval block occurs before the implementation checks the validity of
source constructs lexically following them.</p>
<p>Those constraints are mostly intuitive, but they are a significant
change to the underlying principles of the current standard in this
respect.</p>
<p><span class="title"><span class="citation" data-cites="P2758R4"><a href="https://wg21.link/p2758r4" role="doc-biblioref">[P2758R4]
(Emitting messages at compile time)</a></span></span> also has to deal
with side effects during constant evaluation. However, those effects
(“output”) are of a slightly different nature in the sense that they can
be buffered until a manifestly constant-evaluated expression/conversion
has completed. “Buffering” a class type completion is not practical
(e.g., because other metafunctions may well depend on the completed
class type). Still, we are not aware of incompatibilities between our
proposal and P2758.</p>
<h3 data-number="4.4.2" id="error-handling-in-reflection"><span class="header-section-number">4.4.2</span> Error-Handling in
Reflection<a href="#error-handling-in-reflection" class="self-link"></a></h3>
<p>Earlier revisions of this proposal suggested several possible
approaches to handling errors in reflection metafunctions. This question
arises naturally when considering, for instance, examples like <code class="sourceCode cpp">template_of<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>:
the argument is a reflection of a type, but that type is not a
specialization of a template, so there is no valid template that we can
return.</p>
<p>Some of the possibilities that we have considered include:</p>
<ol type="1">
<li>Returning an invalid reflection (similar to
<code class="sourceCode cpp">NaN</code> for floating point) which
carries source location info and some useful message (i.e., the approach
suggested by P1240)</li>
<li>Returning a <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info, E<span class="op">&gt;</span></code>
for some reflection-specific error type
<code class="sourceCode cpp">E</code>, which carries source location
info and some useful message</li>
<li>Failing to be a constant expression</li>
<li>Throwing an exception of type <code class="sourceCode cpp">E</code>,
which requires a language extension for such exceptions to be catchable
during
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
evaluation</li>
</ol>
<p>We found that we disliked (1) since there is no satisfying value that
can be returned for a call like <code class="sourceCode cpp">template_arguments_of<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>:
We could return a <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>
having a single invalid reflection, but this makes for awkward error
handling. The experience offered by (3) is at least consistent, but
provides no immediate means for a user to “recover” from an error.</p>
<p>Either <code class="sourceCode cpp">std<span class="op">::</span>expected</code> or
constexpr exceptions would allow for a consistent and straightforward
interface. Deciding between the two, we noticed that many of usual
concerns about exceptions do not apply during translation:</p>
<ul>
<li>concerns about runtime performance, object file size, etc. do not
exist, and</li>
<li>concerns about code evolving to add new uncaught exception types do
not apply</li>
</ul>
<p>An interesting example illustrates one reason for our preference for
exceptions over <code class="sourceCode cpp">std<span class="op">::</span>expected</code>:</p>
<div class="std">
<blockquote>
<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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span>template_of<span class="op">(^^</span>T<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span>std<span class="op">::</span>optional<span class="op">)</span></span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">()</span>;</span></code></pre></div>
</blockquote>
</div>
<ul>
<li><p>If <code class="sourceCode cpp">template_of</code> returns an
<code class="sourceCode cpp">expected<span class="op">&lt;</span>info, E<span class="op">&gt;</span></code>,
then <code class="sourceCode cpp">foo<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
is a substitution failure — <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
is equality-comparable to <code class="sourceCode cpp">T</code>, that
comparison would evaluate to
<code class="sourceCode cpp"><span class="kw">false</span></code> but
still be a constant expression.</p></li>
<li><p>If <code class="sourceCode cpp">template_of</code> returns
<code class="sourceCode cpp">info</code> but throws an exception, then
<code class="sourceCode cpp">foo<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
would cause that exception to be uncaught, which would make the
comparison not a constant expression. This actually makes the constraint
ill-formed - not a substitution failure. In order to have <code class="sourceCode cpp">foo<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
be a substitution failure, either the constraint would have to first
check that <code class="sourceCode cpp">T</code> is a template or we
would have to change the language rule that requires constraints to be
constant expressions (we would of course still keep the requirement that
the constraint is a
<code class="sourceCode cpp"><span class="dt">bool</span></code>).</p></li>
</ul>
<p>Since the R2 revision of this paper, <span class="citation" data-cites="P3068R1"><a href="https://wg21.link/p3068r1" role="doc-biblioref">[P3068R1]</a></span> has proposed the introduction
of constexpr exceptions. The proposal addresses hurdles like compiler
modes that disable exception support, and a Clang-based implementation
is underway. We believe this to be the most desirable error-handling
mechanism for reflection metafunctions.</p>
<p>Because constexpr exceptions have not yet been adopted into the
working draft, we do not specify any functions in this paper that throw
exceptions. Rather, we propose that they fail to be constant expressions
(i.e., case 3 above), and note that this approach will allow us to
forward-compatibly add exceptions at a later time. In the interim
period, implementations should have all of the information needed to
issue helpful diagnostics (e.g., “<em>note:
<code class="sourceCode cpp">R</code> does not reflect a template
specialization</em>”) to improve the experience of writing reflection
code.</p>
<h3 data-number="4.4.3" id="range-based-metafunctions"><span class="header-section-number">4.4.3</span> Range-Based Metafunctions<a href="#range-based-metafunctions" class="self-link"></a></h3>
<p>There are a number of functions, both in the “core” reflection API
that we intend to provide as well as converting some of the standard
library type traits that can accept or return a range of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>.</p>
<p>For example:</p>
<ul>
<li><code class="sourceCode cpp">template_arguments_of<span class="op">(^^</span>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span></code>
is <code class="sourceCode cpp"><span class="op">{^^</span><span class="dt">int</span><span class="op">}</span></code></li>
<li><code class="sourceCode cpp">substitute<span class="op">(^^</span>std<span class="op">::</span>tuple, <span class="op">{^^</span><span class="dt">int</span><span class="op">})</span></code>
is <code class="sourceCode cpp"><span class="op">^^</span>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code></li>
</ul>
<p>This requires us to answer the question: how do we accept a range
parameter and how do we provide a range return.</p>
<p>For return, we intend on returning <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>
from all such APIs. This is by far the easiest for users to deal with.
We definitely don’t want to return a <code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info <span class="kw">const</span><span class="op">&gt;</span></code>,
since this requires keeping all the information in the compiler memory
forever (unlike
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
which could free its allocation). The only other option would be a
custom container type which is optimized for compile-time by being able
to produce elements lazily on demand - i.e. so that <code class="sourceCode cpp">nonstatic_data_members_of<span class="op">(^^</span>T<span class="op">)[</span><span class="dv">3</span><span class="op">]</span></code>
wouldn’t have to populate <em>all</em> the data members, just do enough
work to be able to return the 4th one. But that adds a lot of complexity
that’s probably not worth the effort.</p>
<p>For parameters, there are basically three options:</p>
<ol type="1">
<li>Accept <code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info <span class="kw">const</span><span class="op">&gt;</span></code>,
which now accepts braced-init-list arguments so it’s pretty convenient
in this regard.</li>
<li>Accept <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></li>
<li>Accept <em>any</em> range whose
<code class="sourceCode cpp">type_value</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>.</li>
</ol>
<p>Now, for compiler efficiency reasons, it’s definitely better to have
all the arguments contiguously. So the compiler wants
<code class="sourceCode cpp">span</code> (or something like it). There’s
really no reason to prefer <code class="sourceCode cpp">vector</code>
over <code class="sourceCode cpp">span</code>. Accepting any range would
look something like this:</p>
<div class="std">
<blockquote>
<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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> reflection_range <span class="op">=</span> ranges<span class="op">::</span>input_range<span class="op">&lt;</span>R<span class="op">&gt;</span></span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a>                            <span class="op">&amp;&amp;</span> same_as<span class="op">&lt;</span>ranges<span class="op">::</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, info<span class="op">&gt;</span>;</span>
<span id="cb68-5"><a href="#cb68-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-6"><a href="#cb68-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> substitute<span class="op">(</span>info tmpl, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb68-8"><a href="#cb68-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This API is more user friendly than accepting <code class="sourceCode cpp">span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;</span></code>
by virtue of simply accepting more kinds of ranges. The default template
argument allows for braced-init-lists to still work. <a href="https://godbolt.org/z/P49MPhn4T">Example</a>.</p>
<p>Specifically, if the user is doing anything with range adaptors, they
will either end up with a non-contiguous or non-sized range, which will
no longer be convertible to <code class="sourceCode cpp">span</code> -
so they will have to manually convert their range to a <code class="sourceCode cpp">vector<span class="op">&lt;</span>info<span class="op">&gt;</span></code>
in order to pass it to the algorithm. Because the implementation wants
contiguity anyway, that conversion to
<code class="sourceCode cpp">vector</code> will happen either way - so
it’s just a matter of whether every call needs to do it manually or the
implementation can just do it once.</p>
<p>For example, converting a struct to a tuple type:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">span</code> only</strong>
</div></th>
<th><div style="text-align:center">
<strong>any range</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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><span class="kw">consteval</span> <span class="kw">auto</span> type_struct_to_tuple<span class="op">(</span>info type<span class="op">)</span> <span class="op">-&gt;</span> meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> substitute<span class="op">(</span></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">^^</span>tuple,</span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a>        nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></span>
<span id="cb69-5"><a href="#cb69-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> views<span class="op">::</span>transform<span class="op">(</span>meta<span class="op">::</span>type_of<span class="op">)</span></span>
<span id="cb69-6"><a href="#cb69-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> views<span class="op">::</span>transform<span class="op">(</span>meta<span class="op">::</span>remove_cvref<span class="op">)</span></span>
<span id="cb69-7"><a href="#cb69-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;())</span>;</span>
<span id="cb69-8"><a href="#cb69-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<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><span class="kw">consteval</span> <span class="kw">auto</span> type_struct_to_tuple<span class="op">(</span>info type<span class="op">)</span> <span class="op">-&gt;</span> meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> substitute<span class="op">(</span></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">^^</span>tuple,</span>
<span id="cb70-4"><a href="#cb70-4" aria-hidden="true" tabindex="-1"></a>        nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></span>
<span id="cb70-5"><a href="#cb70-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> views<span class="op">::</span>transform<span class="op">(</span>meta<span class="op">::</span>type_of<span class="op">)</span></span>
<span id="cb70-6"><a href="#cb70-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> views<span class="op">::</span>transform<span class="op">(</span>meta<span class="op">::</span>remove_cvref<span class="op">)</span></span>
<span id="cb70-7"><a href="#cb70-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span>;</span>
<span id="cb70-8"><a href="#cb70-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>This shouldn’t cause much compilation overhead. Checking
convertibility to <code class="sourceCode cpp">span</code>
<em>already</em> uses Ranges machinery. And implementations can just do
the right thing interally:</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> <span class="kw">auto</span> <span class="fu">__builtin_substitute</span><span class="op">(</span>info tmpl, info <span class="kw">const</span><span class="op">*</span> arg, <span class="dt">size_t</span> num_args<span class="op">)</span> <span class="op">-&gt;</span> info;</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><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> substitute<span class="op">(</span>info tmpl, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>ranges<span class="op">::</span>sized_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> ranges<span class="op">::</span>contiguous_range<span class="op">&lt;</span>R<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">__builtin_substitute</span><span class="op">(</span>tmpl, ranges<span class="op">::</span>data<span class="op">(</span>args<span class="op">)</span>, ranges<span class="op">::</span>size<span class="op">(</span>args<span class="op">))</span>;</span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> as_vector <span class="op">=</span> ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&lt;</span>info<span class="op">&gt;&gt;((</span>R<span class="op">&amp;&amp;)</span>args<span class="op">)</span>;</span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">__builtin_substitute</span><span class="op">(</span>tmpl, as_vector<span class="op">.</span>data<span class="op">()</span>, as_vector<span class="op">.</span>size<span class="op">())</span>;</span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb71-11"><a href="#cb71-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>As such, we propose that all the range-accepting algorithms accept
any range.</p>
<h3 data-number="4.4.4" id="handling-aliases"><span class="header-section-number">4.4.4</span> Handling Aliases<a href="#handling-aliases" class="self-link"></a></h3>
<p>Consider</p>
<div class="std">
<blockquote>
<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><span class="kw">using</span> A <span class="op">=</span> <span class="dt">int</span>;</span></code></pre></div>
</blockquote>
</div>
<p>In C++ today, <code class="sourceCode cpp">A</code> and
<code class="sourceCode cpp"><span class="dt">int</span></code> can be
used interchangeably and there is no distinction between the two types.
With reflection as proposed in this paper, that will no longer be the
case. <code class="sourceCode cpp"><span class="op">^^</span>A</code>
yields a reflection of an alias to
<code class="sourceCode cpp"><span class="dt">int</span></code>, while
<code class="sourceCode cpp"><span class="op">^^</span><span class="dt">int</span></code>
yields a reflection of
<code class="sourceCode cpp"><span class="dt">int</span></code>. <code class="sourceCode cpp"><span class="op">^^</span>A <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span></code>
evaluates to
<code class="sourceCode cpp"><span class="kw">false</span></code>, but
there will be a way to strip aliases - so <code class="sourceCode cpp">dealias<span class="op">(^^</span>A<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span></code>
evaluates to
<code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p>This opens up the question of how various other metafunctions handle
aliases and it is worth going over a few examples:</p>
<div class="std">
<blockquote>
<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><span class="kw">using</span> A <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> B <span class="op">=</span> std<span class="op">::</span>unique_ptr<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>;</span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">using</span> C <span class="op">=</span> std<span class="op">::</span>unique_ptr<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This paper is proposing that:</p>
<ul>
<li><code class="sourceCode cpp">is_type<span class="op">(^^</span>A<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
<code class="sourceCode cpp"><span class="op">^^</span>A</code> is an
alias, but it’s an alias to a type, and if this evaluated as
<code class="sourceCode cpp"><span class="kw">false</span></code> then
everyone would have to <code class="sourceCode cpp">dealias</code>
everything all the time.</li>
<li><code class="sourceCode cpp">has_template_arguments<span class="op">(^^</span>B<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>
while <code class="sourceCode cpp">has_template_arguments<span class="op">(^^</span>C<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Even though <code class="sourceCode cpp">B</code> is an alias to a type
that itself has template arguments (<code class="sourceCode cpp">unique_ptr<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>),
<code class="sourceCode cpp">B</code> itself is simply a type alias and
does not. This reflects the actual usage.</li>
<li>Meanwhile, <code class="sourceCode cpp">template_arguments_of<span class="op">(^^</span>C<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span></code>
yields <code class="sourceCode cpp"><span class="op">{^^</span><span class="dt">int</span><span class="op">}</span></code>
while <code class="sourceCode cpp">template_arguments_of<span class="op">(^^</span>std<span class="op">::</span>unique_ptr<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span></code>
yields <code class="sourceCode cpp"><span class="op">{^^</span><span class="dt">int</span>, <span class="op">^^</span>std<span class="op">::</span>default_deleter<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;}</span></code>.
This is because <code class="sourceCode cpp">C</code> has its own
template arguments that can be reflected on.</li>
</ul>
<p>What about when querying the type of an entity?</p>
<div class="std">
<blockquote>
<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>std<span class="op">::</span>string Str;</span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std<span class="op">::</span>string <span class="op">&amp;</span>Ref <span class="op">=</span> Str;</span>
<span id="cb74-3"><a href="#cb74-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb74-4"><a href="#cb74-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info StrTy <span class="op">=</span> type_of<span class="op">(^^</span>Str<span class="op">)</span>;</span>
<span id="cb74-5"><a href="#cb74-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info RefTy <span class="op">=</span> type_of<span class="op">(^^</span>Ref<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>What are <code class="sourceCode cpp">StrTy</code> and
<code class="sourceCode cpp">RefTy</code>? This question is more
difficult. Two distinct issues complicate the answer:</p>
<ol type="1">
<li><p>Our experience using these facilities has consistently shown that
if <code class="sourceCode cpp">StrTy</code> represents
<code class="sourceCode cpp">std<span class="op">::</span>string</code>,
many uses of <code class="sourceCode cpp">StrTy</code> require writing
<code class="sourceCode cpp">dealias<span class="op">(</span>StrTy<span class="op">)</span></code>
rather than using <code class="sourceCode cpp">StrTy</code> directly
(because a reflection of a type aliases compares unequal with a
reflection of the aliased type). Failure to do so often yields subtle
bugs.</p></li>
<li><p>While we would like for <code class="sourceCode cpp">RefTy</code>
to represent <code class="sourceCode cpp"><span class="kw">const</span> std<span class="op">::</span>string <span class="op">&amp;</span></code>,
it can only represent <code class="sourceCode cpp"><span class="kw">const</span> std<span class="op">::</span>basic_string<span class="op">&lt;</span><span class="dt">char</span>, std<span class="op">::</span>allocator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span> <span class="op">&amp;</span></code>.
Why? Because since
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
is only a “name” for <code class="sourceCode cpp">std<span class="op">::</span>basic_string<span class="op">&lt;</span><span class="dt">char</span>, std<span class="op">::</span>allocator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span></code>,
the language provides no semantic answer to what “<code class="sourceCode cpp"><span class="kw">const</span> std<span class="op">::</span>string <span class="op">&amp;</span></code>”
<em>is</em>. It is only a source-level “grammatical” construct: A
<em>type-id</em>. Reflecting type-ids is a brittle path, since it opens
questions like whether a reflection of <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">int</span></code>
is the same as a reflection of <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span></code>.
Furthermore, nothing currently requires an implementation to “remember”
that the type of <code class="sourceCode cpp">Ref</code> was “spelled”
with the alias
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
after parsing it, and we aren’t confident that all major implementations
do so today. Lastly, even if we <em>could</em> form a reflection of
<code class="sourceCode cpp"><span class="kw">const</span> std<span class="op">::</span>string <span class="op">&amp;</span></code>,
our existing metafunction and type-trait “machinery” gives no means of
unwrapping the cv-ref qualification to get <code class="sourceCode cpp"><span class="op">^^</span>std<span class="op">::</span>string</code>
without decaying all the way to <code class="sourceCode cpp"><span class="op">^^</span>std<span class="op">::</span>basic_string<span class="op">&lt;</span><span class="dt">char</span>, std<span class="op">::</span>allocator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span></code>.</p></li>
</ol>
<p>In light of the above, our position is that
<code class="sourceCode cpp">type_of</code> should never return aliases:
That is, <code class="sourceCode cpp">StrTy</code> represents <code class="sourceCode cpp">std<span class="op">::</span>basic_string<span class="op">&lt;</span><span class="dt">char</span>, std<span class="op">::</span>allocator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span></code>.
We believe that it would be desirable to in the future introduce an
<code class="sourceCode cpp">aliased_type_of</code> function capable of
returning representations of both
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
and <code class="sourceCode cpp"><span class="kw">const</span> std<span class="op">::</span>string <span class="op">&amp;</span></code>
for <code class="sourceCode cpp">Str</code> and
<code class="sourceCode cpp">Ref</code> respectively - but this requires
both discussions with implementers, and likely new wording technology
for the Standard. To avoid jeopardizing the goal declared by the title
of this paper, we are not proposing such a function at this time.</p>
<h3 data-number="4.4.5" id="reflecting-source-text"><span class="header-section-number">4.4.5</span> Reflecting source text<a href="#reflecting-source-text" class="self-link"></a></h3>
<p>One of the most “obvious” abilities of reflection — retrieving the
name of an entity — turns out to raise issues that aren’t obvious at
all: How do we represent source text in a C++ program?</p>
<p>Thanks to recent work originating in SG16 (the “Unicode” study group)
we can assume that all source code is ultimately representable as
Unicode code points. C++ now also has types to represent UTF-8-encoded
text
(incl. <code class="sourceCode cpp"><span class="dt">char8_t</span></code>,
<code class="sourceCode cpp">u8string</code>, and
<code class="sourceCode cpp">u8string_view</code>) and corresponding
literals like <code class="sourceCode cpp"><span class="st">u8&quot;Hi&quot;</span></code>.
Unfortunately, what can be done with those types is still limited at the
time of this writing. For example,</p>
<div class="std">
<blockquote>
<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><span class="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">u8&quot;こんにちは世界</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb75-4"><a href="#cb75-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>is not standard C++ because the standard output stream does not have
support for UTF-8 literals.</p>
<p>In practice ordinary strings encoded in the “ordinary literal
encoding” (which may or may not be UTF-8) are often used. We therefore
need mechanisms to produce the corresponding ordinary string types as
well.</p>
<p>Orthogonal to the character representation is the data structure used
to traffic in source text. An implementation can easily have at least
three potential representations of reflected source text:</p>
<ol type="a">
<li><p>the internal representation used, e.g., in the compiler front
end’s AST-like structures (persistent)</p></li>
<li><p>the representation of string literals in the AST
(persistent)</p></li>
<li><p>the representation of array of character values during
constant-evaluation (transient)</p></li>
</ol>
<p>(some compilers might share some of those representations). For
transient text during constant evaluation we’d like to use
<code class="sourceCode cpp">string</code>/<code class="sourceCode cpp">u8string</code>
values, but because of the limitations on non-transient allocation
during constant evaluation we cannot easily transfer such types to the
non-constant (i.e., run-time) environment. E.g., if
<code class="sourceCode cpp">identifier_of</code> were a (consteval)
metafunction returning a
<code class="sourceCode cpp">std<span class="op">::</span>string</code>
value, the following simple example would not work:</p>
<div class="std">
<blockquote>
<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="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb76-4"><a href="#cb76-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> hello_world <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb76-5"><a href="#cb76-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> identifier_of<span class="op">(^^</span>hello_world<span class="op">)</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;  <span class="co">// Doesn&#39;t work if identifier_of produces a std::string.</span></span>
<span id="cb76-6"><a href="#cb76-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We can instead return a <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>
or <code class="sourceCode cpp">std<span class="op">::</span>u8string_view</code>,
but that has the downside that it effectively makes all results of
querying source text persistent for the compilation.</p>
<p>For now, however, we propose that queries like
<code class="sourceCode cpp">identifier_of</code> do produce “string
view” results. For example:</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> std<span class="op">::</span>string_view identifier_of<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>u8string_view identifier_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>An alternative strategy that we considered is the introduction of a
“proxy type” for source text:</p>
<div class="std">
<blockquote>
<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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb78-2"><a href="#cb78-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> source_text_info <span class="op">{</span></span>
<span id="cb78-3"><a href="#cb78-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb78-4"><a href="#cb78-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="cb78-5"><a href="#cb78-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(^^</span>T <span class="op">==</span> dealias<span class="op">(^^</span>std<span class="op">::</span>string_view<span class="op">)</span> <span class="op">||</span> <span class="op">^^</span>T <span class="op">==</span> dealias<span class="op">(^^</span>std<span class="op">::</span>u8string_view<span class="op">)</span> <span class="op">||</span></span>
<span id="cb78-6"><a href="#cb78-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">^^</span>T <span class="op">==</span> dealias<span class="op">(^^</span>std<span class="op">::</span>string<span class="op">)</span> <span class="op">||</span> <span class="op">^^</span>T <span class="op">==</span> dealias<span class="op">(^^</span>std<span class="op">::</span>u8string<span class="op">))</span></span>
<span id="cb78-7"><a href="#cb78-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">consteval</span> T as<span class="op">()</span>;</span>
<span id="cb78-8"><a href="#cb78-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb78-9"><a href="#cb78-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb78-10"><a href="#cb78-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>where the <code class="sourceCode cpp">as<span class="op">&lt;...&gt;()</span></code>
member function produces a string-like type as desired. That idea was
dropped, however, because it became unwieldy in actual use cases.</p>
<p>With a source text query like <code class="sourceCode cpp">identifier_of<span class="op">(</span>refl<span class="op">)</span></code>
it is possible that the some source characters of the result are not
representable. We can then consider multiple options, including:</p>
<ol type="1">
<li><p>the query fails to evaluate,</p></li>
<li><p>any unrepresentable source characters are translated to a
different presentation, such as universal-character-names of the form
<code class="sourceCode cpp">\u<span class="op">{</span> <em>hex-number</em> <span class="op">}</span></code>,</p></li>
<li><p>any source characters not in the basic source character set are
translated to a different presentation (as in (2)).</p></li>
</ol>
<p>Following much discussion with SG16, we propose #1: The query fails
to evaluate if the identifier cannot be represented in the ordinary
literal encoding.</p>
<h3 data-number="4.4.6" id="reflecting-names"><span class="header-section-number">4.4.6</span> Reflecting names<a href="#reflecting-names" class="self-link"></a></h3>
<p>Earlier revisions of this proposal (and its predecessor, <span class="citation" data-cites="P1240R2"><a href="https://wg21.link/p1240r2" role="doc-biblioref">[P1240R2]</a></span>) included a metafunction
called <code class="sourceCode cpp">name_of</code>, which we defined to
return a <code class="sourceCode cpp">string_view</code> containing the
“name” of the reflected entity. As the paper evolved, it became
necessary to sharpen the specification of what this “name” contains.
Subsequent revisions (beginning with P2996R2, presented in Tokyo)
specified that <code class="sourceCode cpp">name_of</code> returns the
unqualified name, whereas a new
<code class="sourceCode cpp">qualified_name_of</code> would give the
fully qualified name.</p>
<p>Most would agree that <code class="sourceCode cpp">qualified_name_of<span class="op">(^^</span><span class="dt">size_t</span><span class="op">)</span></code>
might reasonably return <code class="sourceCode cpp"><span class="st">&quot;std::size_t&quot;</span></code>,
or that <code class="sourceCode cpp">qualified_name_of<span class="op">(^^</span>std<span class="op">::</span>any<span class="op">::</span>reset<span class="op">)</span></code>
could return <code class="sourceCode cpp"><span class="st">&quot;std::any::reset&quot;</span></code>.
But what about for local variables, or members of local classes? Should
inline and anonymous namespaces be rendered as a part of the qualified
name? Should we standardize the spelling of such scopes, or leave it
implementation defined?</p>
<p>The situation is possibly even less clear for unqualified names.
Should cv-qualified types be rendered as <code class="sourceCode cpp"><span class="kw">const</span> <span class="dt">int</span></code>
or <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span></code>?
Should the type for a function returning a pointer be rendered as
<code class="sourceCode cpp">T <span class="op">*(*)()</span></code>,
<code class="sourceCode cpp">T<span class="op">*</span> <span class="op">(*)()</span></code>,
or <code class="sourceCode cpp">T <span class="op">*</span> <span class="op">(*)()</span></code>?
Should such decisions be standardized, or left to implementations? But
the real kicker is when one considers non-type template arguments, which
can (and do) contain arbitrarily complex values of arbitrary structural
types (along with any complete object, or subobject thereof, which has
static storage duration).</p>
<p>The more that we tried to specify formatting behavior for just the
unqualified names of arbitrary types, the more convinced we became that
this did not feel like an algorithm that should be frozen in the
standard library - at least, not at this time. There are just too many
toggles that a programmer might reasonably want to flip (one need only
look at <a href="https://github.com/llvm/llvm-project/blob/248c53429427034f45705af60d47f3b1090c4799/clang/include/clang/AST/PrettyPrinter.h#L59-L80">Clang’s
<code class="sourceCode cpp">PrettyPrinter</code> class</a> for
inspiration). On the other hand, it is perfectly reasonable to ask that
implementations give <em>some</em> means of describing what it is that a
reflection contains - that is exactly the purpose of the
<code class="sourceCode cpp">display_string_of</code> function.</p>
<p>Our stance is therefore that reflection pretty printers, for now,
should be left to organically develop within the ecosystem of
open-source C++ libraries. To ensure that this is possible, the
Clang/P2996 fork has implemented its
<code class="sourceCode cpp">display_string_of</code> metafunction
entirely within the library. It is capable of printing type names, value
representations, template arguments, and much more. Best of all, it can
be extended without modifying the compiler.</p>
<p>What of <code class="sourceCode cpp">name_of</code> and
<code class="sourceCode cpp">qualified_name_of</code>? As of the R5
revision of this paper, we have removed them. In their stead is
<code class="sourceCode cpp">identifier_of</code>, which is only a
constant expression if the name of the represented construct is an
identifier, and <code class="sourceCode cpp">has_identifier</code> for
checking this condition. A few other metafunctions fill in some gaps:
<code class="sourceCode cpp">operator_of</code> determines the identity
of an overloaded operator, and predicates like
<code class="sourceCode cpp">is_operator_function</code> and
<code class="sourceCode cpp">is_conversion_function_template</code> let
printing libraries handle those unqualified names that are not
identifiers. <code class="sourceCode cpp">parent_of</code> supports
walking up the chain of functions, namespaces, and classes enclosing the
declaration of an entity, thus enabling homegrown implementations of
<code class="sourceCode cpp">qualified_name_of</code>. Meanwhile, the
prime real estate of <code class="sourceCode cpp">name_of</code> remains
available for future library extensions.</p>
<p>As a nice side-effect, the
<code class="sourceCode cpp">identifier_of</code> model altogether
dodges some contentious questions that arose during LEWG discussions in
St Louis: Should asking the “name” of an anonymous entity (e.g.,
anonymous unions) return the empty string, or fail to be a constant
expression? Since the C++ grammar requires that an
<code class="sourceCode cpp"><em>identifier</em></code> contain at least
one character, the <code class="sourceCode cpp">identifier_of</code>
function never returns an empty string: it is seen that the only
possibility is to fail to be a constant expression.</p>
<h3 data-number="4.4.7" id="reachability-and-injected-declarations"><span class="header-section-number">4.4.7</span> Reachability and injected
declarations<a href="#reachability-and-injected-declarations" class="self-link"></a></h3>
<p>Certain metafunctions (e.g.,
<code class="sourceCode cpp">members_of</code>) return reflections that
represent entities without ever naming those entities in source code
(i.e., eliding lookup). Although it is often clear which entities should
be returned from the perspective of a reader, or even the perspective of
an implementation, core wording has no notion that directly corresponds
to “compilation state”.</p>
<p>Lookup is rather defined in terms of “reachability”, which is roughly
a mapping from a “program point” to the set of declarations
<em>reachable</em> from that point. Lookup frequently occurs from a
single point, but template instantiation (and a few other niche
circumstances) can lead to lookup taking place from multiple points
(i.e., the point in a template from which a name is specified, and the
point from which the template was instantiated). The set of points from
which lookup takes place is the <em>instantiation context</em>
([module.context]).</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="dt">int</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="co">/*P1*/</span> T<span class="op">::</span>value;</span>
<span id="cb79-3"><a href="#cb79-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb79-4"><a href="#cb79-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-5"><a href="#cb79-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span> <span class="kw">static</span> <span class="kw">const</span> <span class="dt">int</span> value <span class="op">=</span> <span class="dv">42</span>; <span class="op">}</span></span>
<span id="cb79-6"><a href="#cb79-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-7"><a href="#cb79-7" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb79-8"><a href="#cb79-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="co">/*P2*/</span> fn<span class="op">&lt;</span>S<span class="op">&gt;()</span>;</span>
<span id="cb79-9"><a href="#cb79-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb79-10"><a href="#cb79-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-11"><a href="#cb79-11" aria-hidden="true" tabindex="-1"></a><span class="co">// The instantiation context when looking up &#39;S::value&#39; in &#39;fn&lt;T&gt;&#39; is {P1, P2}.</span></span>
<span id="cb79-12"><a href="#cb79-12" aria-hidden="true" tabindex="-1"></a><span class="co">// Even though &#39;S&#39; is not found from P1, it is found from P2; lookup succeeds.</span></span></code></pre></div>
</blockquote>
</div>
<p>This works because the notion of template instantiation is baked into
the definition of “instantiation context”, which is thereafter used to
define lookup. But we have no such benefit in the case of metafunctions
like <code class="sourceCode cpp">members_of</code>, which do not
utilize template instantiation.</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> <span class="dt">size_t</span> count_fields<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info Ty<span class="op">)</span> <span class="op">{</span></span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="co">/*P1*/</span> nonstatic_data_members_of<span class="op">(</span>Ty<span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb80-4"><a href="#cb80-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb80-5"><a href="#cb80-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span> <span class="dt">int</span> i, j, k; <span class="op">}</span></span>
<span id="cb80-6"><a href="#cb80-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="co">/*P2*/</span> count_fields<span class="op">(^^</span>S<span class="op">)</span> <span class="op">==</span> <span class="dv">3</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If we naively define
<code class="sourceCode cpp">nonstatic_data_members_of</code> to return
members reachable from the “point of call”, then the above code would
fail: after all, <code class="sourceCode cpp">S</code> is not reachable
from <code class="sourceCode cpp"><em>P1</em></code>. We instead must
define the declarations to be those reachable from where constant
evaluation begins (i.e.,
<code class="sourceCode cpp"><em>P2</em></code>). We encode this idea in
our definition of the <em>evaluation context</em>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">22</a></span>
During the evaluation of a manifestly constant-evaluated expression
<code class="sourceCode cpp"><em>M</em></code>, the evaluation context
of an expression <code class="sourceCode cpp"><em>E</em></code>
comprises […] the instantiation context of
<code class="sourceCode cpp"><em>M</em></code> ([module.context]), […]
.</p>
</div>
</blockquote>
</div>
<p>This gives the tool needed to define the declarations returned by
<code class="sourceCode cpp">members_of</code> to be (roughly) those
reachable from the <em>evaluation context</em>. However, a second
problem related to reachability is posed by
<code class="sourceCode cpp">define_aggregate</code>.</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info make_defn<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info Cls, std<span class="op">::</span>meta<span class="op">::</span>info Mem<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">// Synthesizes:</span></span>
<span id="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">//   struct Mem {};</span></span>
<span id="cb81-4"><a href="#cb81-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">//   struct Cls { Mem m; };</span></span>
<span id="cb81-5"><a href="#cb81-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="co">/*P1*/</span> define_aggregate<span class="op">(</span>Cls, <span class="op">{</span></span>
<span id="cb81-6"><a href="#cb81-6" aria-hidden="true" tabindex="-1"></a>    data_member_spec<span class="op">(</span><span class="co">/*P2*/</span> define_aggregate<span class="op">(</span>Mem, <span class="op">{})</span>, <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;m&quot;</span><span class="op">})</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>
<span id="cb81-9"><a href="#cb81-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-10"><a href="#cb81-10" aria-hidden="true" tabindex="-1"></a><span class="co">/* P3*/</span> <span class="kw">struct</span> C;</span>
<span id="cb81-11"><a href="#cb81-11" aria-hidden="true" tabindex="-1"></a><span class="co">/* P4*/</span> <span class="kw">struct</span> M;</span>
<span id="cb81-12"><a href="#cb81-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="co">/*P5*/</span> is_type<span class="op">(</span>make_defn<span class="op">(^^</span>C, <span class="op">^^</span>M<span class="op">))</span> <span class="co">/*P6*/</span><span class="op">)</span>;</span>
<span id="cb81-13"><a href="#cb81-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-14"><a href="#cb81-14" aria-hidden="true" tabindex="-1"></a><span class="co">/*P7*/</span> C obj;</span></code></pre></div>
</blockquote>
</div>
<p>Although we want this code to be valid, we have several obstacles to
navigate.</p>
<ol type="1">
<li>How can definitions for <code class="sourceCode cpp">C</code> and
<code class="sourceCode cpp">M</code> be defined from
<code class="sourceCode cpp"><em>P1</em></code> and
<code class="sourceCode cpp"><em>P2</em></code> when no declarations of
those classes are reachable from those program points?</li>
<li>Where are the points of declaration for the generated definitions of
<code class="sourceCode cpp">C</code> and
<code class="sourceCode cpp">M</code> (i.e., from what program points
will the generated definitions be reachable)?</li>
<li>How can we ensure that the definition of
<code class="sourceCode cpp">M</code> is reachable during the evaluation
of <code class="sourceCode cpp">define_aggregate</code> on
<code class="sourceCode cpp">C</code>?</li>
</ol>
<p>The prior discourse regarding
<code class="sourceCode cpp">members_of</code> gives a straightforward
answer to (1); the <code class="sourceCode cpp">define_aggregate</code>
function is defined in terms of the <em>evaluation context</em>, which
makes available all declarations reachable from
<code class="sourceCode cpp"><em>P5</em></code>.</p>
<p>An answer to (2) can be seen by considering the declarations at
<code class="sourceCode cpp"><em>P3</em></code>,
<code class="sourceCode cpp"><em>P4</em></code>, and
<code class="sourceCode cpp"><em>P7</em></code>: Since we want the
declaration of <code class="sourceCode cpp">obj</code> to be
well-formed, the generated definition of
<code class="sourceCode cpp">C</code> must precede
<code class="sourceCode cpp"><em>P7</em></code>. On the other hand,
placing the definition of <code class="sourceCode cpp"><em>C</em></code>
prior to <code class="sourceCode cpp"><em>P4</em></code> would weirdly
place the definition of the class <code class="sourceCode cpp">C</code>,
which contains a data member of type
<code class="sourceCode cpp">M</code>, prior to the declaration of
<code class="sourceCode cpp">M</code> itself. We propose that the point
of declaration for all definitions generated by
<code class="sourceCode cpp">define_aggregate</code> immediately follows
the end of the manifestly constant-evaluated expression that produces
the definition: In this case, just prior to
<code class="sourceCode cpp"><em>P6</em></code>.</p>
<p>This leaves one gap, and it is the question posed by (3): If the
definition of <code class="sourceCode cpp">M</code>, generated by
evaluation of <code class="sourceCode cpp">define_aggregate<span class="op">(</span>Mem, <span class="op">{})</span></code>,
is located just prior to
<code class="sourceCode cpp"><em>P6</em></code>, then the definition is
still not reachable from the evaluation context (such as we have defined
it) during evaluation of <code class="sourceCode cpp">define_aggregate<span class="op">(</span>Cls, <span class="op">...)</span></code>.</p>
<p>Circling back to “reachability” as a mapping from program points to
declarations, there are two clear paths forward: Either modify which
declarations are reachable from a program point, or modify the set of
program points in the evaluation context. We choose the later approach,
and attempt to provide some machinery that can be reused for future
“generative reflection” proposals.</p>
<p>We begin by specially indicating that the generated definitions of
<code class="sourceCode cpp">C</code> and
<code class="sourceCode cpp">M</code> are not just declarations, but
<em>injected declarations</em>, and that such injected declarations are
<em>produced</em> by an evaluation of an expression. The reachability of
these declarations is evidently different from other declarations: It
depends not only on a program point, but also on which compile-time
evaluations of expressions (which have no relation to lexical ordering)
are <em>sequenced after</em> the production of the injected
declarations.</p>
<p>To bridge the world of program points to the world of sequenced
evaluations, we introduce a notion dual to “injected declarations”: For
every injected declaration, there is a corresponding <em>synthesized
point</em>. Injected points have a special property: the <em>only</em>
declaration reachable from a synthesized point is its corresponding
injected declaration. Jumping back to our above example, joining the
synthesized point of the injected declaration of
<code class="sourceCode cpp">M</code> to our evaluation context gives
exactly what is needed for <code class="sourceCode cpp">M</code> to be
usable during the definition of <code class="sourceCode cpp">C</code>.
More precisely: <code class="sourceCode cpp">M</code> is reachable
during the definition of <code class="sourceCode cpp">C</code> because
the evaluation of the expression that produces the definition of
<code class="sourceCode cpp">M</code> is <em>sequenced before</em> the
evalauation of the expression that produces
<code class="sourceCode cpp">C</code>. This is captured by our full and
final definition of the evaluation context:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">22</a></span>
The <em>evaluation context</em> is a set of points within the program
that determines which declarations are found by certain expressions used
for reflection. During the evaluation of a manifestly constant-evaluated
expression <code class="sourceCode cpp"><em>M</em></code>, the
evaluation context of an expression
<code class="sourceCode cpp"><em>E</em></code> comprises the union
of</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(22.1)</a></span>
the instantiation context of
<code class="sourceCode cpp"><em>M</em></code> ([module.context]),
and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">(22.2)</a></span>
the synthesized points corresponding to any injected declarations
([expr.const]) produced by evaluations sequenced before the next
evaluation of <code class="sourceCode cpp"><em>E</em></code>.</li>
</ul>
</div>
</blockquote>
</div>
<p>Lastly, we clarify that during the definition of an <em>injected
declaration</em>, the instantiation context consists of the
<em>evaluation context</em> of the expression that is producing the
declaration. In our example above, this ensures that the definition of
<code class="sourceCode cpp"><em>M</em></code> is reachable not just
from the invocation of
<code class="sourceCode cpp">define_aggregate</code> for
<code class="sourceCode cpp">C</code>, but from within the actual
generated definition of
<code class="sourceCode cpp"><em>C</em></code>.</p>
<p>This machinery is “off in the weeds” of technicalities related to
modules, lookup, etc., but we believe (hope?) that it provides a sound
basis upon which to build generative reflection within the framework
provided by core language wording: not only for P2996, but for future
papers as well.</p>
<h3 data-number="4.4.8" id="restrictions-on-injected-declarations"><span class="header-section-number">4.4.8</span> Restrictions on injected
declarations<a href="#restrictions-on-injected-declarations" class="self-link"></a></h3>
<p>The advancement of this proposal through WG21 has naturally led to
increased scrutiny of the mechanisms here proposed. One such area is the
possibility of leveraging injected declarations to observe failed
template substitutions. Consider the following example:</p>
<div class="std">
<blockquote>
<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="kw">struct</span> S;</span>
<span id="cb82-2"><a href="#cb82-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-3"><a href="#cb82-3" 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 class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb82-4"><a href="#cb82-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> sfn<span class="op">()</span>  <span class="co">// #1</span></span>
<span id="cb82-5"><a href="#cb82-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">([]</span> <span class="op">{</span></span>
<span id="cb82-6"><a href="#cb82-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb82-7"><a href="#cb82-7" aria-hidden="true" tabindex="-1"></a>          define_aggregate<span class="op">(^^</span>S, <span class="op">{})</span>;</span>
<span id="cb82-8"><a href="#cb82-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb82-9"><a href="#cb82-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">}()</span>, <span class="kw">false</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb82-10"><a href="#cb82-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;  <span class="co">// never selected</span></span>
<span id="cb82-11"><a href="#cb82-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb82-12"><a href="#cb82-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-13"><a href="#cb82-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> sfn<span class="op">()</span>  <span class="co">// #2</span></span>
<span id="cb82-14"><a href="#cb82-14" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb82-15"><a href="#cb82-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">true</span>;   <span class="co">// always selected</span></span>
<span id="cb82-16"><a href="#cb82-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb82-17"><a href="#cb82-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb82-18"><a href="#cb82-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-19"><a href="#cb82-19" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>TCls<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;::</span>sfn<span class="op">())</span>;</span>
<span id="cb82-20"><a href="#cb82-20" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_complete_type<span class="op">(^^</span>S<span class="op">))</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The above example observes the effects of the failed substitution of
<code class="sourceCode cpp"><span class="pp">#1</span></code> by way of
the completeness of <code class="sourceCode cpp">S</code>. Such tricks
can be used to observe implementation details, like the order in which
overloads are checked, that may be unportable (and which implementations
might desire to change over time).</p>
<p>Our proposed solution, specified in [expr.const]/23.2, is to make it
ill-formed to produce an injected declaration from a manifestly
constant-evaluated expression <em>inside of</em> an instantiation to
<em>outside of</em> that instantiation, or visa versa. Because that
expression in the example above (<code class="sourceCode cpp">define_aggregate<span class="op">(^^</span>S, <span class="op">{})</span></code>)
is within the instantiation of the requires clause of <code class="sourceCode cpp">TCls<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;::</span>sfn</code>,
and the target scope of the injected declaration is outside of that same
instantiaton, the example becomes ill-formed (diagnostic required). Note
that this does not prevent writing
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
function templates that wrap
<code class="sourceCode cpp">define_aggregate</code>:</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="kw">consteval</span> <span class="dt">bool</span> tfn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb83-2"><a href="#cb83-2" aria-hidden="true" tabindex="-1"></a>  define_aggregate<span class="op">(</span>R, <span class="op">{})</span>;</span>
<span id="cb83-3"><a href="#cb83-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb83-4"><a href="#cb83-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb83-5"><a href="#cb83-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb83-6"><a href="#cb83-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S;</span>
<span id="cb83-7"><a href="#cb83-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> b <span class="op">=</span> tfn<span class="op">&lt;^^</span>S<span class="op">&gt;()</span>;</span>
<span id="cb83-8"><a href="#cb83-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, both manifestly constant-evaluated expression tfn&lt;^^S&gt;() and target scope of</span></span>
<span id="cb83-9"><a href="#cb83-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// injected declaration for &#39;S&#39; are in the global namespace</span></span></code></pre></div>
</blockquote>
</div>
<p>Nor does this rule prevent a class template from producing a
declaration whose target scope is the same specialization.</p>
<div class="std">
<blockquote>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">&gt;</span> <span class="kw">struct</span> TCls1 <span class="op">{</span></span>
<span id="cb84-2"><a href="#cb84-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Incomplete;</span>
<span id="cb84-3"><a href="#cb84-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-4"><a href="#cb84-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb84-5"><a href="#cb84-5" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(^^</span>Incomplete, <span class="op">{})</span>;</span>
<span id="cb84-6"><a href="#cb84-6" aria-hidden="true" tabindex="-1"></a>      <span class="co">// OK, Incomplete is in the same instantiation as the define_aggregate call</span></span>
<span id="cb84-7"><a href="#cb84-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb84-8"><a href="#cb84-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-9"><a href="#cb84-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> b <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb84-10"><a href="#cb84-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb84-11"><a href="#cb84-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-12"><a href="#cb84-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 class="kw">struct</span> TCls2 <span class="op">{</span></span>
<span id="cb84-13"><a href="#cb84-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> sfn<span class="op">()</span>  <span class="co">// #1</span></span>
<span id="cb84-14"><a href="#cb84-14" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span>TCls1<span class="op">&lt;</span>T<span class="op">&gt;::</span>b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb84-15"><a href="#cb84-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;  <span class="co">// never selected</span></span>
<span id="cb84-16"><a href="#cb84-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb84-17"><a href="#cb84-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-18"><a href="#cb84-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> sfn<span class="op">()</span>  <span class="co">// #2</span></span>
<span id="cb84-19"><a href="#cb84-19" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb84-20"><a href="#cb84-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">true</span>;   <span class="co">// always selected</span></span>
<span id="cb84-21"><a href="#cb84-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb84-22"><a href="#cb84-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb84-23"><a href="#cb84-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-24"><a href="#cb84-24" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>TCls<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;::</span>sfn<span class="op">())</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Athough the instantiation of <code class="sourceCode cpp">TCls1<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;</span></code>
in the requires-clause of
<code class="sourceCode cpp"><span class="pp">#1</span></code> causes an
injected declaration to be produced, it is not discernibly a side-effect
of the failed substitution: Observing the side effect will first require
one to write (some moral equivalent of) <code class="sourceCode cpp">TCLs1<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;::</span>Incomplete</code>,
the act of which would otherwise itself trigger the same
side-effect.</p>
<p>Although this rule constrains the manner with which
<code class="sourceCode cpp">define_aggregate</code> can be used, we are
not aware of any motivating use cases for P2996 that are harmed. Worth
mentioning, however: the rule has more dire implications for other code
injection papers being considered by WG21, most notably <span class="citation" data-cites="P3294R2"><a href="https://wg21.link/p3294r2" role="doc-biblioref">[P3294R2]</a></span> (“<em>Code Injection With
Token Sequences</em>”). With this rule as it is, it becomes impossible
for e.g., the instantiation of a class template specialization <code class="sourceCode cpp">TCls<span class="op">&lt;</span>Foo<span class="op">&gt;</span></code>
to produce an injected declaration of <code class="sourceCode cpp">std<span class="op">::</span>formatter<span class="op">&lt;</span>TCls<span class="op">&lt;</span>Foo<span class="op">&gt;&gt;</span></code>
(since the target scope would be the global namespace).</p>
<p>In this context, we do believe that relaxations of the rule can be
considered: For instance, we ought to be able to say that the
instantiation of <code class="sourceCode cpp">std<span class="op">::</span>formatter<span class="op">&lt;</span>TCls<span class="op">&lt;</span>Foo<span class="op">&gt;&gt;</span></code>
is sequenced strictly after the instantiation of <code class="sourceCode cpp">TCls<span class="op">&lt;</span>Foo<span class="op">&gt;</span></code>,
and observations such as these might make it possible to permit such
injections without making it “discernible” whether they resulted from
failed substitutions. The key to such an approach would be to define a
partial order over the instantiations of a program, and to allow
constructs to be injected <em>across</em> instantiations when the
relative order of their respective instantiations is defined.</p>
<p>All of that said, these relaxations are not needed for the code
injection introduced by this proposal, and we do not seek to introduce
them at this time.</p>
<h3 data-number="4.4.9" id="freestanding-implementations"><span class="header-section-number">4.4.9</span> Freestanding
implementations<a href="#freestanding-implementations" class="self-link"></a></h3>
<p>Several important metafunctions, such as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of</code>,
return a
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
value. Unfortunately, that means that they are currently not usable in a
freestanding environment, but <span class="title"><span class="citation" data-cites="P3295R0"><a href="https://wg21.link/p3295r0" role="doc-biblioref">[P3295R0] (Freestanding constexpr containers and
constexpr exception types)</a></span></span> currently proposes
freestanding
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>,
<code class="sourceCode cpp">std<span class="op">::</span>string</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> in
constant evaluated contexts, explicitly to make the facilities proposed
by this paper work in freestanding.</p>
<h3 data-number="4.4.10" id="synopsis"><span class="header-section-number">4.4.10</span> Synopsis<a href="#synopsis" class="self-link"></a></h3>
<p>Here is a synopsis for the proposed library API. The functions will
be explained below.</p>
<div class="std">
<blockquote>
<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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> info <span class="op">=</span> <span class="kw">decltype</span><span class="op">(^^::)</span>;</span>
<span id="cb85-3"><a href="#cb85-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-4"><a href="#cb85-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb85-5"><a href="#cb85-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> reflection_range <span class="op">=</span> <span class="co">/* <em>see <a href="#range-based-metafunctions">above</a></em> */</span>;</span>
<span id="cb85-6"><a href="#cb85-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-7"><a href="#cb85-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#name-loc">name and location</a></span></span>
<span id="cb85-8"><a href="#cb85-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> identifier_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb85-9"><a href="#cb85-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8identifier_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb85-10"><a href="#cb85-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-11"><a href="#cb85-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> display_string_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb85-12"><a href="#cb85-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8display_string_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb85-13"><a href="#cb85-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-14"><a href="#cb85-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> source_location_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> source_location;</span>
<span id="cb85-15"><a href="#cb85-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-16"><a href="#cb85-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#type_of-parent_of-dealias">type queries</a></span></span>
<span id="cb85-17"><a href="#cb85-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> type_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-18"><a href="#cb85-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> parent_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-19"><a href="#cb85-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> dealias<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-20"><a href="#cb85-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-21"><a href="#cb85-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#object_of-constant_of">object and constant queries</a></span></span>
<span id="cb85-22"><a href="#cb85-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> object_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-23"><a href="#cb85-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> constant_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-24"><a href="#cb85-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-25"><a href="#cb85-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#template_of-template_arguments_of">template queries</a></span></span>
<span id="cb85-26"><a href="#cb85-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> template_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-27"><a href="#cb85-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> template_arguments_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-28"><a href="#cb85-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-29"><a href="#cb85-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#member-queries">member queries</a></span></span>
<span id="cb85-30"><a href="#cb85-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> members_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-31"><a href="#cb85-31" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bases_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-32"><a href="#cb85-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> static_data_members_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-33"><a href="#cb85-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> nonstatic_data_members_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-34"><a href="#cb85-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> enumerators_of<span class="op">(</span>info type_enum<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb85-35"><a href="#cb85-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-36"><a href="#cb85-36" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#substitute">substitute</a></span></span>
<span id="cb85-37"><a href="#cb85-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb85-38"><a href="#cb85-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> can_substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-39"><a href="#cb85-39" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb85-40"><a href="#cb85-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-41"><a href="#cb85-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-42"><a href="#cb85-42" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#reflect-expression-results">reflect expression results</a></span></span>
<span id="cb85-43"><a href="#cb85-43" 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="cb85-44"><a href="#cb85-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> reflect_constant<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-45"><a href="#cb85-45" 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="cb85-46"><a href="#cb85-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> reflect_object<span class="op">(</span>T<span class="op">&amp;</span> value<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-47"><a href="#cb85-47" 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="cb85-48"><a href="#cb85-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> reflect_function<span class="op">(</span>T<span class="op">&amp;</span> value<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-49"><a href="#cb85-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-50"><a href="#cb85-50" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#extractt">extract<T></a></span></span>
<span id="cb85-51"><a href="#cb85-51" 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="cb85-52"><a href="#cb85-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> extract<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> T;</span>
<span id="cb85-53"><a href="#cb85-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-54"><a href="#cb85-54" aria-hidden="true" tabindex="-1"></a>  <span class="co">// other type predicates (see <a href="#meta.reflection.queries-reflection-queries">the wording</a>)</span></span>
<span id="cb85-55"><a href="#cb85-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_public<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-56"><a href="#cb85-56" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_protected<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-57"><a href="#cb85-57" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_private<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-58"><a href="#cb85-58" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_virtual<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-59"><a href="#cb85-59" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_pure_virtual<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-60"><a href="#cb85-60" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_override<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-61"><a href="#cb85-61" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_final<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-62"><a href="#cb85-62" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_deleted<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-63"><a href="#cb85-63" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_defaulted<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-64"><a href="#cb85-64" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_explicit<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-65"><a href="#cb85-65" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_noexcept<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-66"><a href="#cb85-66" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_bit_field<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-67"><a href="#cb85-67" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_enumerator<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-68"><a href="#cb85-68" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_const<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-69"><a href="#cb85-69" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_volatile<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-70"><a href="#cb85-70" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_mutable_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-71"><a href="#cb85-71" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_lvalue_reference_qualified<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-72"><a href="#cb85-72" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_rvalue_reference_qualified<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-73"><a href="#cb85-73" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_static_storage_duration<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-74"><a href="#cb85-74" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_thread_storage_duration<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-75"><a href="#cb85-75" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_automatic_storage_duration<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-76"><a href="#cb85-76" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_internal_linkage<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-77"><a href="#cb85-77" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_module_linkage<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-78"><a href="#cb85-78" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_external_linkage<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-79"><a href="#cb85-79" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_linkage<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-80"><a href="#cb85-80" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_class_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-81"><a href="#cb85-81" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_namespace_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-82"><a href="#cb85-82" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_nonstatic_data_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-83"><a href="#cb85-83" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_static_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-84"><a href="#cb85-84" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_base<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-85"><a href="#cb85-85" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_data_member_spec<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-86"><a href="#cb85-86" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_namespace<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-87"><a href="#cb85-87" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_function<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-88"><a href="#cb85-88" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_variable<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-89"><a href="#cb85-89" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_type<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-90"><a href="#cb85-90" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_type_alias<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-91"><a href="#cb85-91" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_namespace_alias<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-92"><a href="#cb85-92" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_complete_type<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-93"><a href="#cb85-93" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_enumerable_type<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-94"><a href="#cb85-94" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-95"><a href="#cb85-95" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_function_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-96"><a href="#cb85-96" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_variable_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-97"><a href="#cb85-97" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_class_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-98"><a href="#cb85-98" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_alias_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-99"><a href="#cb85-99" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_conversion_function_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-100"><a href="#cb85-100" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_operator_function_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-101"><a href="#cb85-101" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_literal_operator_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-102"><a href="#cb85-102" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_constructor_template<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-103"><a href="#cb85-103" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_concept<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-104"><a href="#cb85-104" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_structured_binding<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-105"><a href="#cb85-105" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_value<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-106"><a href="#cb85-106" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_object<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-107"><a href="#cb85-107" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_template_arguments<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-108"><a href="#cb85-108" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_default_member_initializer<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-109"><a href="#cb85-109" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-110"><a href="#cb85-110" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_special_member_function<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-111"><a href="#cb85-111" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_conversion_function<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-112"><a href="#cb85-112" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_operator_function<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-113"><a href="#cb85-113" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_literal_operator<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-114"><a href="#cb85-114" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_constructor<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-115"><a href="#cb85-115" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_default_constructor<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-116"><a href="#cb85-116" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_copy_constructor<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-117"><a href="#cb85-117" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_move_constructor<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-118"><a href="#cb85-118" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_assignment<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-119"><a href="#cb85-119" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_copy_assignment<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-120"><a href="#cb85-120" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_move_assignment<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-121"><a href="#cb85-121" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_destructor<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-122"><a href="#cb85-122" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_user_provided<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-123"><a href="#cb85-123" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_user_declared<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb85-124"><a href="#cb85-124" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-125"><a href="#cb85-125" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#data_member_spec-define_aggregate">define_aggregate</a></span></span>
<span id="cb85-126"><a href="#cb85-126" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> data_member_options;</span>
<span id="cb85-127"><a href="#cb85-127" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> data_member_spec<span class="op">(</span>info type_class,</span>
<span id="cb85-128"><a href="#cb85-128" aria-hidden="true" tabindex="-1"></a>                                  data_member_options options<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-129"><a href="#cb85-129" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb85-130"><a href="#cb85-130" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> define_aggregate<span class="op">(</span>info type_class, R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb85-131"><a href="#cb85-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-132"><a href="#cb85-132" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#data-layout-reflection">data layout</a></span></span>
<span id="cb85-133"><a href="#cb85-133" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> member_offset <span class="op">{</span></span>
<span id="cb85-134"><a href="#cb85-134" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ptrdiff_t</span> bytes;</span>
<span id="cb85-135"><a href="#cb85-135" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ptrdiff_t</span> bits;</span>
<span id="cb85-136"><a href="#cb85-136" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> total_bits<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">ptrdiff_t</span>;</span>
<span id="cb85-137"><a href="#cb85-137" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>member_offset <span class="kw">const</span><span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb85-138"><a href="#cb85-138" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb85-139"><a href="#cb85-139" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-140"><a href="#cb85-140" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> offset_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> member_offset;</span>
<span id="cb85-141"><a href="#cb85-141" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> size_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb85-142"><a href="#cb85-142" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> alignment_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb85-143"><a href="#cb85-143" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_size_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb85-144"><a href="#cb85-144" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-145"><a href="#cb85-145" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.11" id="name-loc"><span class="header-section-number">4.4.11</span>
<code class="sourceCode cpp">identifier_of</code>,
<code class="sourceCode cpp">display_string_of</code>,
<code class="sourceCode cpp">source_location_of</code><a href="#name-loc" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb86-2"><a href="#cb86-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> identifier_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8identifier_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> display_string_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb86-6"><a href="#cb86-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8display_string_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb86-7"><a href="#cb86-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-8"><a href="#cb86-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> has_identifier<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb86-9"><a href="#cb86-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-10"><a href="#cb86-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> source_location_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> source_location;</span>
<span id="cb86-11"><a href="#cb86-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Given a reflection <code class="sourceCode cpp">r</code> representing
a language construct <code class="sourceCode cpp">X</code> whose
declaration introduces an identifier, and if that identifier is
representable using the ordinary literal encoding, then <code class="sourceCode cpp">identifier_of<span class="op">(</span>r<span class="op">)</span></code>
returns a non-empty <code class="sourceCode cpp">string_view</code>
containing that identifier. Otherwise, it is not a constant expression.
Whether a reflected construct has an identifier can be checked with the
<code class="sourceCode cpp">has_identifier</code> metafunction.</p>
<p>The function <code class="sourceCode cpp">u8identifier_of</code>
returns the same identifier but as a
<code class="sourceCode cpp">u8string_view</code>. Note that since all
identifiers can be represented as UTF-8 string literals,
<code class="sourceCode cpp">u8identifier_of</code> never fails to be a
constant expression because of representability concerns.</p>
<p>Given any reflection <code class="sourceCode cpp">r</code>, <code class="sourceCode cpp">display_string_of<span class="op">(</span>r<span class="op">)</span></code>
and <code class="sourceCode cpp">u8display_string_of<span class="op">(</span>r<span class="op">)</span></code>
return an unspecified non-empty
<code class="sourceCode cpp">string_view</code> and
<code class="sourceCode cpp">u8string_view</code>, respectively.
Implementations are encouraged to produce text that is helpful in
identifying the reflected construct (note: as an exercise, the Clang
implementation of this proposal implements a pretty-printing
<code class="sourceCode cpp">display_string_of</code> <a href="https://github.com/bloomberg/clang-p2996/blob/8ce6449538510a2330f7227f53b40be7671b0b91/libcxx/include/experimental/meta#L2088-L2731">as
a non-intrinsic library function</a>).</p>
<p>Given a reflection <code class="sourceCode cpp">r</code>, <code class="sourceCode cpp">source_location_of<span class="op">(</span>r<span class="op">)</span></code>
returns an unspecified
<code class="sourceCode cpp">source_location</code>. Implementations are
encouraged to produce the correct source location of the item designated
by the reflection.</p>
<h3 data-number="4.4.12" id="type_of-parent_of-dealias"><span class="header-section-number">4.4.12</span>
<code class="sourceCode cpp">type_of</code>,
<code class="sourceCode cpp">parent_of</code>,
<code class="sourceCode cpp">dealias</code><a href="#type_of-parent_of-dealias" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> type_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> parent_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb87-4"><a href="#cb87-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> dealias<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb87-5"><a href="#cb87-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">r</code> is a reflection designating
a typed entity, <code class="sourceCode cpp">type_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection designating its type. If
<code class="sourceCode cpp">r</code> is already a type, <code class="sourceCode cpp">type_of<span class="op">(</span>r<span class="op">)</span></code>
is not a constant expression. This can be used to implement the C
<code class="sourceCode cpp"><span class="ex">typeof</span></code>
feature (which works on both types and expressions and strips
qualifiers):</p>
<div class="std">
<blockquote>
<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="kw">consteval</span> <span class="kw">auto</span> type_doof<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> remove_cvref<span class="op">(</span>is_type<span class="op">(</span>r<span class="op">)</span> <span class="op">?</span> r <span class="op">:</span> type_of<span class="op">(</span>r<span class="op">))</span>;</span>
<span id="cb88-3"><a href="#cb88-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb88-4"><a href="#cb88-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb88-5"><a href="#cb88-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define typeof</span><span class="op">(</span>e<span class="op">)</span><span class="pp"> </span><span class="op">[:</span><span class="pp"> </span>type_doof<span class="op">(^^</span>e<span class="op">)</span><span class="pp"> </span><span class="op">:]</span></span></code></pre></div>
</blockquote>
</div>
<p><code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection designating its immediately enclosing class, function,
or (possibly inline or anonymous) namespace.</p>
<p>If <code class="sourceCode cpp">r</code> represents an alias, <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents the underlying entity. Otherwise, <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
produces <code class="sourceCode cpp">r</code>.
<code class="sourceCode cpp">dealias</code> is recursive - it strips all
aliases:</p>
<div class="std">
<blockquote>
<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">using</span> X <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb89-2"><a href="#cb89-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Y <span class="op">=</span> X;</span>
<span id="cb89-3"><a href="#cb89-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>dealias<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb89-4"><a href="#cb89-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>dealias<span class="op">(^^</span>X<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb89-5"><a href="#cb89-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>dealias<span class="op">(^^</span>Y<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.13" id="object_of-constant_of"><span class="header-section-number">4.4.13</span>
<code class="sourceCode cpp">object_of</code>,
<code class="sourceCode cpp">constant_of</code><a href="#object_of-constant_of" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> object_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> constant_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb90-4"><a href="#cb90-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">r</code> is a reflection of a
variable denoting an object with static storage duration, then <code class="sourceCode cpp">object_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of the object designated by the variable. If
<code class="sourceCode cpp">r</code> is already a reflection of an
object, <code class="sourceCode cpp">object_of<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp">r</code>. For all other inputs, <code class="sourceCode cpp">object_of<span class="op">(</span>r<span class="op">)</span></code>
is not a constant expression.</p>
<div class="std">
<blockquote>
<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><span class="dt">int</span> x;</span>
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> <span class="op">&amp;</span>y <span class="op">=</span> x;</span>
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>x <span class="op">!=</span> <span class="op">^^</span>y<span class="op">)</span>;</span>
<span id="cb91-5"><a href="#cb91-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>object_of<span class="op">(^^</span>x<span class="op">)</span> <span class="op">==</span> object_of<span class="op">(^^</span>y<span class="op">))</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">r</code> is a reflection of an
enumerator, then <code class="sourceCode cpp">constant_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of the value of the enumerator. Otherwise, if
<code class="sourceCode cpp">r</code> is a reflection of an object
<em>usable in constant expressions</em>, then:</p>
<ul>
<li>if <code class="sourceCode cpp">r</code> has scalar type, then <code class="sourceCode cpp">constant_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of the value of the object.</li>
<li>otherwise, <code class="sourceCode cpp">constant_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of the object.</li>
</ul>
<p>For all other inputs, <code class="sourceCode cpp">constant_of<span class="op">(</span>r<span class="op">)</span></code>
is not a constant expression. For more, see <a href="#reflect-expression-results"><code class="sourceCode cpp">reflect_constant</code></a>.</p>
<h3 data-number="4.4.14" id="template_of-template_arguments_of"><span class="header-section-number">4.4.14</span>
<code class="sourceCode cpp">template_of</code>,
<code class="sourceCode cpp">template_arguments_of</code><a href="#template_of-template_arguments_of" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> template_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> template_arguments_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb92-4"><a href="#cb92-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">r</code> is a reflection designating
a specialization of some template, then <code class="sourceCode cpp">template_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of that template and <code class="sourceCode cpp">template_arguments_of<span class="op">(</span>r<span class="op">)</span></code>
is a vector of the reflections of the template arguments. In other
words, the preconditions on both is that <code class="sourceCode cpp">has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p>For example:</p>
<div class="std">
<blockquote>
<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>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> v <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb93-2"><a href="#cb93-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>template_of<span class="op">(</span>type_of<span class="op">(^^</span>v<span class="op">))</span> <span class="op">==</span> <span class="op">^^</span>std<span class="op">::</span>vector<span class="op">)</span>;</span>
<span id="cb93-3"><a href="#cb93-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>template_arguments_of<span class="op">(</span>type_of<span class="op">(^^</span>v<span class="op">))[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.15" id="member-queries"><span class="header-section-number">4.4.15</span>
<code class="sourceCode cpp">members_of</code>,
<code class="sourceCode cpp">static_data_members_of</code>,
<code class="sourceCode cpp">nonstatic_data_members_of</code>,
<code class="sourceCode cpp">bases_of</code>,
<code class="sourceCode cpp">enumerators_of</code><a href="#member-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> members_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb94-3"><a href="#cb94-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bases_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb94-4"><a href="#cb94-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb94-5"><a href="#cb94-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> static_data_members_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb94-6"><a href="#cb94-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> nonstatic_data_members_of<span class="op">(</span>info type_class<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb94-7"><a href="#cb94-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb94-8"><a href="#cb94-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> enumerators_of<span class="op">(</span>info type_enum<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb94-9"><a href="#cb94-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The template <code class="sourceCode cpp">members_of</code> returns a
vector of reflections representing the direct members of the class type
or namespace represented by its first argument. Any non-static data
members appear in declaration order within that vector. Anonymous unions
appear as a non-static data member of corresponding union type.
Reflections of structured bindings shall not appear in the returned
vector.</p>
<p>The template <code class="sourceCode cpp">bases_of</code> returns the
direct base classes of the class type represented by its first argument,
in declaration order.</p>
<p><code class="sourceCode cpp">static_data_members_of</code> and
<code class="sourceCode cpp">nonstatic_data_members_of</code> return
reflections of the static and non-static data members, preserving their
order, respectively.</p>
<p><code class="sourceCode cpp">enumerators_of</code> returns the
enumerator constants of the indicated enumeration type in declaration
order.</p>
<h3 data-number="4.4.16" id="substitute"><span class="header-section-number">4.4.16</span>
<code class="sourceCode cpp">substitute</code><a href="#substitute" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb95-2"><a href="#cb95-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb95-3"><a href="#cb95-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> can_substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb95-4"><a href="#cb95-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb95-5"><a href="#cb95-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb95-6"><a href="#cb95-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Given a reflection for a template and reflections for template
arguments that match that template,
<code class="sourceCode cpp">substitute</code> returns a reflection for
the entity obtained by substituting the given arguments in the template.
If the template is a concept template, the result is a reflection of a
constant of type
<code class="sourceCode cpp"><span class="dt">bool</span></code>.</p>
<p>For example:</p>
<div class="std">
<blockquote>
<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">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> substitute<span class="op">(^^</span>std<span class="op">::</span>vector, std<span class="op">::</span>vector<span class="op">{^^</span><span class="dt">int</span><span class="op">})</span>;</span>
<span id="cb96-2"><a href="#cb96-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> T <span class="op">=</span> <span class="op">[:</span>r<span class="op">:]</span>; <span class="co">// Ok, T is std::vector&lt;int&gt;</span></span></code></pre></div>
</blockquote>
</div>
<p>This process might kick off instantiations outside the immediate
context, which can lead to the program being ill-formed.</p>
<p>Note that the template is only substituted, not instantiated. For
example:</p>
<div class="std">
<blockquote>
<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> T<span class="op">&gt;</span> <span class="kw">struct</span> S <span class="op">{</span> <span class="kw">typename</span> T<span class="op">::</span>X x; <span class="op">}</span>;</span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-3"><a href="#cb97-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> substitute<span class="op">(^^</span>S, std<span class="op">::</span>vector<span class="op">{^^</span><span class="dt">int</span><span class="op">})</span>;  <span class="co">// Okay.</span></span>
<span id="cb97-4"><a href="#cb97-4" aria-hidden="true" tabindex="-1"></a><span class="kw">typename</span><span class="op">[:</span>r<span class="op">:]</span> si;  <span class="co">// Error: T::X is invalid for T = int.</span></span></code></pre></div>
</blockquote>
</div>
<p><code class="sourceCode cpp">can_substitute<span class="op">(</span>templ, args<span class="op">)</span></code>
simply checks if the substitution can succeed (with the same caveat
about instantiations outside of the immediate context). If <code class="sourceCode cpp">can_substitute<span class="op">(</span>templ, args<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>,
then <code class="sourceCode cpp">substitute<span class="op">(</span>templ, args<span class="op">)</span></code>
will be ill-formed.</p>
<h3 data-number="4.4.17" id="reflect-expression-results"><span class="header-section-number">4.4.17</span>
<code class="sourceCode cpp">reflect_constant</code>,
<code class="sourceCode cpp">reflect_object</code>,
<code class="sourceCode cpp">reflect_function</code><a href="#reflect-expression-results" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb98-2"><a href="#cb98-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 class="kw">consteval</span> <span class="kw">auto</span> reflect_constant<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> expr<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb98-3"><a href="#cb98-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="op">&gt;</span> <span class="kw">consteval</span> <span class="kw">auto</span> reflect_object<span class="op">(</span>T<span class="op">&amp;</span> expr<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb98-4"><a href="#cb98-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 class="kw">consteval</span> <span class="kw">auto</span> reflect_function<span class="op">(</span>T<span class="op">&amp;</span> expr<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb98-5"><a href="#cb98-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>These metafunctions produce a reflection of the <em>result</em> from
evaluating the provided expression. One of the most common use-cases for
such reflections is to specify the template arguments with which to
build a specialization using <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>substitute</code>.</p>
<p><code class="sourceCode cpp">reflect_constant<span class="op">(</span>expr<span class="op">)</span></code>
can best be understood from the equivalence that given the template</p>
<div class="std">
<blockquote>
<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">auto</span> P<span class="op">&gt;</span> <span class="kw">struct</span> C <span class="op">{</span> <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>that:</p>
<div class="std">
<blockquote>
<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>reflect_constant<span class="op">(</span>V<span class="op">)</span> <span class="op">==</span> template_arguments_of<span class="op">(^^</span>C<span class="op">&lt;</span>V<span class="op">&gt;)[</span><span class="dv">0</span><span class="op">]</span></span></code></pre></div>
</blockquote>
</div>
<p>In other words, letting <code class="sourceCode cpp">T</code> be the
cv-unqualified, de-aliased type of
<code class="sourceCode cpp">expr</code>.</p>
<ul>
<li>if <code class="sourceCode cpp">expr</code> has scalar type, then
<code class="sourceCode cpp">reflect_constant<span class="op">(</span>expr<span class="op">)</span></code>
is a reflection of the value of
<code class="sourceCode cpp">expr</code>, whose type is
<code class="sourceCode cpp">T</code>.</li>
<li>if <code class="sourceCode cpp">expr</code> has class type, then
<code class="sourceCode cpp">reflect_constant<span class="op">(</span>expr<span class="op">)</span></code>
is a reflection of the template parameter object that is
template-argument-equivalent to an object of type
<code class="sourceCode cpp">T</code> copy-initialized from
<code class="sourceCode cpp">expr</code>.</li>
</ul>
<p>Either way, the result needs to be a permitted result of a constant
expression. Notably, <code class="sourceCode cpp">reflect_constant<span class="op">(</span>e<span class="op">)</span></code>
can be either a reflection of a value or a reflection of an object,
depending on the type of <code class="sourceCode cpp">e</code>. This
seeming inconsistence is actually useful for two reasons:</p>
<ol type="1">
<li>As mentioned above, it allows an equivalence with template arguments
— where the argument is already either a value or an object.</li>
<li>It avoids having to invest complexity into defining what it means to
have a reflection of a value of class type. Particularly with regards to
when/if copies happen.</li>
</ol>
<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="kw">static_assert</span><span class="op">(</span>substitute<span class="op">(^^</span>std<span class="op">::</span>array, <span class="op">{^^</span><span class="dt">int</span>, std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span><span class="dv">5</span><span class="op">)})</span> <span class="op">==</span></span>
<span id="cb101-2"><a href="#cb101-2" aria-hidden="true" tabindex="-1"></a>              <span class="op">^^</span>std<span class="op">::</span>array<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">5</span><span class="op">&gt;)</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">reflect_object<span class="op">(</span>expr<span class="op">)</span></code>
produces a reflection of the object designated by
<code class="sourceCode cpp">expr</code>. This is frequently used to
obtain a reflection of a subobject, which might then be used as a
template argument for a non-type template parameter of reference
type.</p>
<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="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span> <span class="op">&amp;&gt;</span> <span class="dt">void</span> fn<span class="op">()</span>;</span>
<span id="cb102-2"><a href="#cb102-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb102-3"><a href="#cb102-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> p<span class="op">[</span><span class="dv">2</span><span class="op">]</span>;</span>
<span id="cb102-4"><a href="#cb102-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> substitute<span class="op">(^^</span>fn, <span class="op">{</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_object<span class="op">(</span>p<span class="op">[</span><span class="dv">1</span><span class="op">])})</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">reflect_function<span class="op">(</span>expr<span class="op">)</span></code>
produces a reflection of the function designated by
<code class="sourceCode cpp">expr</code>. It can be useful for
reflecting on the properties of a function for which only a reference is
available.</p>
<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="kw">consteval</span> <span class="dt">bool</span> is_global_with_external_linkage<span class="op">(</span><span class="dt">void</span><span class="op">(*</span>fn<span class="op">)())</span> <span class="op">{</span></span>
<span id="cb103-2"><a href="#cb103-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>meta<span class="op">::</span>info rfn <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_function<span class="op">(*</span>fn<span class="op">)</span>;</span>
<span id="cb103-3"><a href="#cb103-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb103-4"><a href="#cb103-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">(</span>has_external_linkage<span class="op">(</span>rfn<span class="op">)</span> <span class="op">&amp;&amp;</span> parent_of<span class="op">(</span>rfn<span class="op">)</span> <span class="op">==</span> <span class="op">^^::)</span>;</span>
<span id="cb103-5"><a href="#cb103-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.4.18" id="extractt"><span class="header-section-number">4.4.18</span> <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;</span></code><a href="#extractt" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb104-2"><a href="#cb104-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 class="kw">consteval</span> <span class="kw">auto</span> extract<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> T;</span>
<span id="cb104-3"><a href="#cb104-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">r</code> is a reflection for a value
of type <code class="sourceCode cpp">T</code>, <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span></code>
is a prvalue whose evaluation computes the reflected value.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for an
object of non-reference type <code class="sourceCode cpp">T</code>,
<code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&amp;&gt;(</span>r<span class="op">)</span></code>
and <code class="sourceCode cpp">extract<span class="op">&lt;</span>T <span class="kw">const</span><span class="op">&amp;&gt;(</span>r<span class="op">)</span></code>
are lvalues referring to that object. If the object is usable in
constant expressions [expr.const], <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span></code>
evaluates to its value.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for an
object of reference type <code class="sourceCode cpp">T</code> usable in
constant-expressions, <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span></code>
evaluates to that reference.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for a
function of type <code class="sourceCode cpp">F</code>, <code class="sourceCode cpp">extract<span class="op">&lt;</span>F<span class="op">*&gt;(</span>r<span class="op">)</span></code>
evaluates to a pointer to that function.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for a
non-static member function and <code class="sourceCode cpp">T</code> is
the type for a pointer to the reflected member function, <code class="sourceCode cpp">extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span></code>
evaluates to a pointer to the member function.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for an
enumerator constant of type <code class="sourceCode cpp">E</code>, <code class="sourceCode cpp">extract<span class="op">&lt;</span>E<span class="op">&gt;(</span>r<span class="op">)</span></code>
evaluates to the value of that enumerator.</p>
<p>If <code class="sourceCode cpp">r</code> is a reflection for a
non-bit-field non-reference non-static member of type
<code class="sourceCode cpp">M</code> in a class
<code class="sourceCode cpp">C</code>, <code class="sourceCode cpp">extract<span class="op">&lt;</span>M C<span class="op">::*&gt;(</span>r<span class="op">)</span></code>
is the pointer-to-member value for that non-static member.</p>
<p>For other reflection values <code class="sourceCode cpp">r</code>,
<code class="sourceCode cpp">extrace<span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span></code>
is ill-formed.</p>
<p>The function template <code class="sourceCode cpp">extract</code> may
feel similar to splicers, but unlike splicers it does not require its
operand to be a constant-expression itself. Also unlike splicers, it
requires knowledge of the type associated with the entity represented by
its operand.</p>
<h3 data-number="4.4.19" id="data_member_spec-define_aggregate"><span class="header-section-number">4.4.19</span>
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_aggregate</code><a href="#data_member_spec-define_aggregate" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb105-2"><a href="#cb105-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> data_member_options <span class="op">{</span></span>
<span id="cb105-3"><a href="#cb105-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> name_type <span class="op">{</span></span>
<span id="cb105-4"><a href="#cb105-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 class="kw">requires</span> constructible_from<span class="op">&lt;</span>u8string, T<span class="op">&gt;</span></span>
<span id="cb105-5"><a href="#cb105-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> name_type<span class="op">(</span>T <span class="op">&amp;&amp;)</span>;</span>
<span id="cb105-6"><a href="#cb105-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb105-7"><a href="#cb105-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 class="kw">requires</span> constructible_from<span class="op">&lt;</span>string, T<span class="op">&gt;</span></span>
<span id="cb105-8"><a href="#cb105-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> name_type<span class="op">(</span>T <span class="op">&amp;&amp;)</span>;</span>
<span id="cb105-9"><a href="#cb105-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb105-10"><a href="#cb105-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb105-11"><a href="#cb105-11" aria-hidden="true" tabindex="-1"></a>    optional<span class="op">&lt;</span>name_type<span class="op">&gt;</span> name;</span>
<span id="cb105-12"><a href="#cb105-12" aria-hidden="true" tabindex="-1"></a>    optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> alignment;</span>
<span id="cb105-13"><a href="#cb105-13" aria-hidden="true" tabindex="-1"></a>    optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> bit_width;</span>
<span id="cb105-14"><a href="#cb105-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> no_unique_address <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb105-15"><a href="#cb105-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb105-16"><a href="#cb105-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> data_member_spec<span class="op">(</span>info type,</span>
<span id="cb105-17"><a href="#cb105-17" aria-hidden="true" tabindex="-1"></a>                                  data_member_options options<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb105-18"><a href="#cb105-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb105-19"><a href="#cb105-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> define_aggregate<span class="op">(</span>info type_class, R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb105-20"><a href="#cb105-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p><code class="sourceCode cpp">data_member_spec</code> returns a
reflection of a data member description for a data member of given type.
Optional alignment, bit-field-width, and name can be provided as well.
An inner class <code class="sourceCode cpp">name_type</code>, which may
be implicitly constructed from any of several “string-like” types (e.g.,
<code class="sourceCode cpp">string_view</code>,
<code class="sourceCode cpp">u8string_view</code>, <code class="sourceCode cpp"><span class="dt">char8_t</span><span class="op">[]</span></code>,
<code class="sourceCode cpp">char_t<span class="op">[]</span></code>),
is used to represent the name. If a
<code class="sourceCode cpp">name</code> is provided, it must be a valid
identifier when interpreted as a sequence of code-units. Otherwise, the
name of the data member is unspecified.</p>
<p><code class="sourceCode cpp">define_aggregate</code> takes the
reflection of an incomplete class/struct/union type and a range of
reflections of data member descriptions and completes the given class
type with data members as described (in the given order). The given
reflection is returned. For now, only data member reflections are
supported (via <code class="sourceCode cpp">data_member_spec</code>) but
the API takes in a range of <code class="sourceCode cpp">info</code>
anticipating expanding this in the near future.</p>
<p>For example:</p>
<div class="std">
<blockquote>
<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="kw">union</span> U;</span>
<span id="cb106-2"><a href="#cb106-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb106-3"><a href="#cb106-3" aria-hidden="true" tabindex="-1"></a>  define_aggregate<span class="op">(^^</span>U, <span class="op">{</span></span>
<span id="cb106-4"><a href="#cb106-4" aria-hidden="true" tabindex="-1"></a>  data_member_spec<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span>,</span>
<span id="cb106-5"><a href="#cb106-5" aria-hidden="true" tabindex="-1"></a>  data_member_spec<span class="op">(^^</span><span class="dt">char</span><span class="op">)</span>,</span>
<span id="cb106-6"><a href="#cb106-6" aria-hidden="true" tabindex="-1"></a>  data_member_spec<span class="op">(^^</span><span class="dt">double</span><span class="op">)</span>,</span>
<span id="cb106-7"><a href="#cb106-7" aria-hidden="true" tabindex="-1"></a><span class="op">})</span>;</span>
<span id="cb106-8"><a href="#cb106-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb106-9"><a href="#cb106-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb106-10"><a href="#cb106-10" aria-hidden="true" tabindex="-1"></a><span class="co">// U is now defined to the equivalent of</span></span>
<span id="cb106-11"><a href="#cb106-11" aria-hidden="true" tabindex="-1"></a><span class="co">// union U {</span></span>
<span id="cb106-12"><a href="#cb106-12" aria-hidden="true" tabindex="-1"></a><span class="co">//   int <em>_0</em>;</span></span>
<span id="cb106-13"><a href="#cb106-13" aria-hidden="true" tabindex="-1"></a><span class="co">//   char <em>_1</em>;</span></span>
<span id="cb106-14"><a href="#cb106-14" aria-hidden="true" tabindex="-1"></a><span class="co">//   double <em>_2</em>;</span></span>
<span id="cb106-15"><a href="#cb106-15" aria-hidden="true" tabindex="-1"></a><span class="co">// };</span></span>
<span id="cb106-16"><a href="#cb106-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb106-17"><a href="#cb106-17" 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 class="kw">struct</span> S;</span>
<span id="cb106-18"><a href="#cb106-18" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> s_int_refl <span class="op">=</span> define_aggregate<span class="op">(^^</span>S<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>, <span class="op">{</span></span>
<span id="cb106-19"><a href="#cb106-19" aria-hidden="true" tabindex="-1"></a>  data_member_spec<span class="op">(^^</span><span class="dt">int</span>, <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;i&quot;</span>, <span class="op">.</span>alignment<span class="op">=</span><span class="dv">64</span><span class="op">})</span>,</span>
<span id="cb106-20"><a href="#cb106-20" aria-hidden="true" tabindex="-1"></a>  data_member_spec<span class="op">(^^</span><span class="dt">int</span>, <span class="op">{.</span>name<span class="op">=</span><span class="st">u8&quot;こんにち&quot;</span><span class="op">})</span>,</span>
<span id="cb106-21"><a href="#cb106-21" aria-hidden="true" tabindex="-1"></a><span class="op">})</span>;</span>
<span id="cb106-22"><a href="#cb106-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb106-23"><a href="#cb106-23" aria-hidden="true" tabindex="-1"></a><span class="co">// S&lt;int&gt; is now defined to the equivalent of</span></span>
<span id="cb106-24"><a href="#cb106-24" aria-hidden="true" tabindex="-1"></a><span class="co">// template&lt;&gt; struct S&lt;int&gt; {</span></span>
<span id="cb106-25"><a href="#cb106-25" aria-hidden="true" tabindex="-1"></a><span class="co">//   alignas(64) int i;</span></span>
<span id="cb106-26"><a href="#cb106-26" aria-hidden="true" tabindex="-1"></a><span class="co">//               int こんにち;</span></span>
<span id="cb106-27"><a href="#cb106-27" aria-hidden="true" tabindex="-1"></a><span class="co">// };</span></span></code></pre></div>
</blockquote>
</div>
<p>When defining a
<code class="sourceCode cpp"><span class="kw">union</span></code>, if
one of the alternatives has a non-trivial destructor, the defined union
will <em>still</em> have a destructor provided - that simply does
nothing. This allows implementing <a href="#a-simple-variant-type">variant</a> without having to further
extend support in <code class="sourceCode cpp">define_aggregate</code>
for member functions.</p>
<p>If <code class="sourceCode cpp">define_aggregate</code> is called
multiple times with the same arguments, all calls after the first will
have no effect. Calling
<code class="sourceCode cpp">define_aggregate</code> for a type that was
defined using other arguments, defined through other means, or is in the
process of being defined, is not a constant expression.</p>
<p>Revisions of this paper prior to P2996R8 named this function
<code class="sourceCode cpp">define_class</code>. We find
<code class="sourceCode cpp">define_aggregate</code> to be a better name
for a few reasons:</p>
<ol type="1">
<li>The capabilities of the function are quite limited, and are mostly
good for constructing aggregate types.</li>
<li>The new name provides good cause for forcing all data members to be
public. Private data members created through such an interface are of
very limited utility.</li>
<li>The name <code class="sourceCode cpp">define_class</code> is left
available for a future, more fully-featured API.</li>
</ol>
<h3 data-number="4.4.20" id="data-layout-reflection"><span class="header-section-number">4.4.20</span> Data Layout Reflection<a href="#data-layout-reflection" class="self-link"></a></h3>
<div class="std">
<blockquote>
<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><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb107-2"><a href="#cb107-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> member_offset <span class="op">{</span></span>
<span id="cb107-3"><a href="#cb107-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ptrdiff_t</span> bytes;</span>
<span id="cb107-4"><a href="#cb107-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ptrdiff_t</span> bits;</span>
<span id="cb107-5"><a href="#cb107-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-6"><a href="#cb107-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> total_bits<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">ptrdiff_t</span> <span class="op">{</span></span>
<span id="cb107-7"><a href="#cb107-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> CHAR_BIT <span class="op">*</span> bytes <span class="op">+</span> bits;</span>
<span id="cb107-8"><a href="#cb107-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb107-9"><a href="#cb107-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-10"><a href="#cb107-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>member_offset <span class="kw">const</span><span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb107-11"><a href="#cb107-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb107-12"><a href="#cb107-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-13"><a href="#cb107-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> offset_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> member_offset;</span>
<span id="cb107-14"><a href="#cb107-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> size_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb107-15"><a href="#cb107-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> alignment_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb107-16"><a href="#cb107-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_size_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb107-17"><a href="#cb107-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-18"><a href="#cb107-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>These are generalized versions of some facilities we already have in
the language.</p>
<ul>
<li><code class="sourceCode cpp">offset_of</code> takes a reflection of
a non-static data member or a base class subobject and returns the
offset of it - in bytes and then leftover bits (always between
<code class="sourceCode cpp"><span class="dv">0</span></code> and
<code class="sourceCode cpp"><span class="dv">7</span></code>
inclusive).</li>
<li><code class="sourceCode cpp">size_of</code> takes the reflection of
a type, object, variable, non-static data member, or base class
subobject and returns its size.</li>
<li><code class="sourceCode cpp">alignment_of</code> takes the
reflection of a type, non-static data member, or base class subobject
and returns its alignment.</li>
<li><code class="sourceCode cpp">bit_size_of</code> gives the size of a
base class subobject or non-static data member, except in bits.</li>
</ul>
<div class="std">
<blockquote>
<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="kw">struct</span> Msg <span class="op">{</span></span>
<span id="cb108-2"><a href="#cb108-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">uint64_t</span> a <span class="op">:</span> <span class="dv">10</span>;</span>
<span id="cb108-3"><a href="#cb108-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">uint64_t</span> b <span class="op">:</span>  <span class="dv">8</span>;</span>
<span id="cb108-4"><a href="#cb108-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">uint64_t</span> c <span class="op">:</span> <span class="dv">25</span>;</span>
<span id="cb108-5"><a href="#cb108-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">uint64_t</span> d <span class="op">:</span> <span class="dv">21</span>;</span>
<span id="cb108-6"><a href="#cb108-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb108-7"><a href="#cb108-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb108-8"><a href="#cb108-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>a<span class="op">)</span> <span class="op">==</span> member_offset<span class="op">{</span><span class="dv">0</span>, <span class="dv">0</span><span class="op">})</span>;</span>
<span id="cb108-9"><a href="#cb108-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>b<span class="op">)</span> <span class="op">==</span> member_offset<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">})</span>;</span>
<span id="cb108-10"><a href="#cb108-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>c<span class="op">)</span> <span class="op">==</span> member_offset<span class="op">{</span><span class="dv">2</span>, <span class="dv">2</span><span class="op">})</span>;</span>
<span id="cb108-11"><a href="#cb108-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>d<span class="op">)</span> <span class="op">==</span> member_offset<span class="op">{</span><span class="dv">5</span>, <span class="dv">3</span><span class="op">})</span>;</span>
<span id="cb108-12"><a href="#cb108-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb108-13"><a href="#cb108-13" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_size_of<span class="op">(^^</span>Msg<span class="op">::</span>a<span class="op">)</span> <span class="op">==</span> <span class="dv">10</span><span class="op">)</span>;</span>
<span id="cb108-14"><a href="#cb108-14" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_size_of<span class="op">(^^</span>Msg<span class="op">::</span>b<span class="op">)</span> <span class="op">==</span> <span class="dv">8</span><span class="op">)</span>;</span>
<span id="cb108-15"><a href="#cb108-15" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_size_of<span class="op">(^^</span>Msg<span class="op">::</span>c<span class="op">)</span> <span class="op">==</span> <span class="dv">25</span><span class="op">)</span>;</span>
<span id="cb108-16"><a href="#cb108-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_size_of<span class="op">(^^</span>Msg<span class="op">::</span>d<span class="op">)</span> <span class="op">==</span> <span class="dv">21</span><span class="op">)</span>;</span>
<span id="cb108-17"><a href="#cb108-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb108-18"><a href="#cb108-18" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>a<span class="op">).</span>total_bits<span class="op">()</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb108-19"><a href="#cb108-19" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>b<span class="op">).</span>total_bits<span class="op">()</span> <span class="op">==</span> <span class="dv">10</span><span class="op">)</span>;</span>
<span id="cb108-20"><a href="#cb108-20" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>c<span class="op">).</span>total_bits<span class="op">()</span> <span class="op">==</span> <span class="dv">18</span><span class="op">)</span>;</span>
<span id="cb108-21"><a href="#cb108-21" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>offset_of<span class="op">(^^</span>Msg<span class="op">::</span>d<span class="op">).</span>total_bits<span class="op">()</span> <span class="op">==</span> <span class="dv">43</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.21" id="other-type-traits"><span class="header-section-number">4.4.21</span> Other Type Traits<a href="#other-type-traits" class="self-link"></a></h3>
<p>There is a question of whether all the type traits should be provided
in
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>.
For instance, a few examples in this paper use <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>remove_cvref<span class="op">(</span>t<span class="op">)</span></code>
as if that exists. Technically, the functionality isn’t strictly
necessary - since it can be provided indirectly:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Direct</strong>
</div></th>
<th><div style="text-align:center">
<strong>Indirect</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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>remove_cvref<span class="op">(</span>type<span class="op">)</span></span></code></pre></div>

</div></td>
<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>dealias<span class="op">(</span>substitute<span class="op">(^^</span>std<span class="op">::</span>remove_cvref_t, <span class="op">{</span>type<span class="op">}))</span></span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<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>is_const_type<span class="op">(</span>type<span class="op">)</span></span></code></pre></div>

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

<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>extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>substitute<span class="op">(^^</span>std<span class="op">::</span>is_const_v, <span class="op">{</span>type<span class="op">}))</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The indirect approach is a lot more typing, and you have to remember
to <code class="sourceCode cpp">dealias</code> the result of the type
traits as well (because <code class="sourceCode cpp">substitute<span class="op">(^^</span>std<span class="op">::</span>remove_cvref_t, <span class="op">{^^</span><span class="dt">int</span> <span class="kw">const</span><span class="op">})</span></code>
gives you a reflection of an alias to
<code class="sourceCode cpp"><span class="dt">int</span></code>, not a
reflection of
<code class="sourceCode cpp"><span class="dt">int</span></code>), so
it’s both more tedious and more error prone.</p>
<p>Having <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>meow</code>
for every trait
<code class="sourceCode cpp">std<span class="op">::</span>meow</code> is
more straightforward and will likely be faster to compile, though means
we will have a much larger library API. There are quite a few traits in
<span>21 <a href="https://wg21.link/meta">[meta]</a></span> - but it
should be easy enough to specify all of them. So we’re doing it.</p>
<p>Now, one thing that came up is that the straightforward thing we want
to do is to simply add a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>meow</code>
for every trait
<code class="sourceCode cpp">std<span class="op">::</span>meow</code>
and word it appropriately. That’s what we initially tried to do.
However, we’ve run into some conflicts.</p>
<p>The standard library type traits are all <em>type</em> traits - they
only accept types. As such, their names are simply things like <code class="sourceCode cpp">std<span class="op">::</span>is_pointer</code>,
<code class="sourceCode cpp">std<span class="op">::</span>is_const</code>,
<code class="sourceCode cpp">std<span class="op">::</span>is_lvalue_reference</code>,
and so forth. Renaming it to <code class="sourceCode cpp">std<span class="op">::</span>type_is_pointer</code>,
for instance, would be a waste of characters since there’s nothing else
the argument could be save for a type.</p>
<p>But this is no longer the case. Consider the name
<code class="sourceCode cpp">is_function</code>. It could be:</p>
<ol type="1">
<li><p>A consteval function equivalent of the type trait <code class="sourceCode cpp">std<span class="op">::</span>is_function<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
such that <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_function<span class="op">(</span>e<span class="op">)</span></code>
mandates that <code class="sourceCode cpp">e</code> represents a type
and checks if that type is a function type.</p></li>
<li><p>A new kind of reflection query <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_function<span class="op">(</span>e<span class="op">)</span></code>
which asks if <code class="sourceCode cpp">e</code> is the reflection of
a function (as opposed to a type or a namespace or a template, etc.).
This is the same category of query as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_template</code>
or <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_concept</code>
or <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_namespace</code>.</p></li>
</ol>
<p>Both of these are useful, yet they mean different things entirely -
the first is ill-formed when passed a reflection of a function (as
opposed to a function type), and the second would simply answer
<code class="sourceCode cpp"><span class="kw">false</span></code> for
the reflection of <em>any</em> type (function type or otherwise).</p>
<p>Moreover, in this case it’s actually important that the reflection
query <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_function</code>
does <em>not</em> return
<code class="sourceCode cpp"><span class="kw">true</span></code> for a
function type so that using
<code class="sourceCode cpp">is_function</code> as a filter for
<code class="sourceCode cpp">members_of</code> does the expected thing —
only giving you back functions, rather than also types.</p>
<p>A similar kind of clash could occur with other functions — for
instance, we don’t have an <code class="sourceCode cpp">is_array<span class="op">(</span>r<span class="op">)</span></code>
right now that would check if <code class="sourceCode cpp">r</code> were
the reflection of an array (as opposed to an array type), but we could
in the future.</p>
<p>There are a few other examples of name clashes where we want the
reflection query to apply to more inputs than simply types. For example,
the type trait <code class="sourceCode cpp">std<span class="op">::</span>is_final</code> can
only ask if a type is a final class type, but the metafunction <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_final</code>
can ask if a member function is a final member function. Likewise <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_const</code>
can apply to objects or types too, and so forth.</p>
<p>The question becomes — how can we incorporate the type traits into
the consteval metafunction domain while avoiding these name clash
issues. We know of a few approaches.</p>
<ol type="1">
<li><p>Put all the type traits in their own namespace, like <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>traits<span class="op">::</span>meow</code>.
This has the benefit that we preserve the existing name, but now we lose
ADL. We can’t write <code class="sourceCode cpp">traits<span class="op">::</span>remove_cvref<span class="op">(</span>type<span class="op">)</span></code>
unless we bring in <code class="sourceCode cpp">traits</code> as a
namespace alias for <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>traits</code>,
and if we bring in the entire namespace then we’re back to the name
clash problem (it’s just that now the calls become ambiguous).</p></li>
<li><p>Add a prefix or suffix to every type trait. This preserves the
ability to use ADL and makes the new names easy to remember (since <code class="sourceCode cpp">std<span class="op">::</span>meow_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
just directly translates into <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_meow<span class="op">(</span>type<span class="op">)</span></code>
for all <code class="sourceCode cpp">meow</code>), at the cost of worse
names.</p></li>
<li><p>Do something more tailored on a case-by-case basis.</p></li>
</ol>
<p>We don’t think the nested namespace approach (#1) is a good idea
because of the loss of ADL and the more inconvenient call syntax.</p>
<p>Previous revisions of this proposal used the
<code class="sourceCode cpp">type_</code> prefix (#2) uniformly. This
had the downside that some type traits end up reading awkwardly
(<code class="sourceCode cpp">type_is_pointer</code> as opposed to
<code class="sourceCode cpp">is_pointer_type</code>) but several others
do read much better
(<code class="sourceCode cpp">type_has_virtual_destructor</code> as
opposed to
<code class="sourceCode cpp">has_virtual_destructor_type</code>). Some
type traits look equally ridiculous with either a prefix or suffix
(<code class="sourceCode cpp">type_common_type</code> vs
<code class="sourceCode cpp">common_type_type</code>).</p>
<p>A more bespoke approach (#3) would be to do something based on the
grammar of the existing type traits:</p>
<ul>
<li>All the type traits of the form
<code class="sourceCode cpp">is_meow</code> can become
<code class="sourceCode cpp">is_meow_type</code>. This reads quite
nicely for most of them
(<code class="sourceCode cpp">is_pointer_type</code>,
<code class="sourceCode cpp">is_trivially_copyable_type</code>,
<code class="sourceCode cpp">is_void_type</code>, etc.).
<code class="sourceCode cpp">is_swappable_with_type</code> or
<code class="sourceCode cpp">is_pointer_convertible_base_of_type</code>
or <code class="sourceCode cpp">is_invocable_type</code> maybe aren’t
amazing, but they’re not terrible either. There are 76 of these and
having a uniform transformation is valuable. We could even simply
special case the few that are known to conflict (or, in the case of
<code class="sourceCode cpp">is_array</code>, might conflict in the
future, but that’s a little harder to internalize).</li>
<li>The remaining ones could potentially keep their current name in
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span></code>
form as well. There are a few things to point out with these remaining
traits though:
<ul>
<li>a couple type transformations like
<code class="sourceCode cpp">add_const</code> could potentially also
apply to member functions for the purposes of generating code (although
some of these, like
<code class="sourceCode cpp">add_lvalue_reference</code>, we’d want to
spell in terms of the qualifier, so those wouldn’t conflict). It’d
probably be okay to start with an
<code class="sourceCode cpp">add_const</code> that only applies to types
and eventually extend it, if we go that route though.</li>
<li><code class="sourceCode cpp">alignment_of</code> goes away entirely
(since we already have <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>alignment_of</code>).
Nobody will notice.</li>
<li>a couple of these could meaningfully apply to objects as well as
types, like <code class="sourceCode cpp">has_virtual_destructor</code>,
but we would still only apply to types.</li>
</ul></li>
</ul>
<p>Note that either way, we’re also including a few common traits that
aren’t defined in the same places — those are the tuple traits
(<code class="sourceCode cpp">tuple_size</code>/<code class="sourceCode cpp">tuple_element</code>)
and the variant traits
(<code class="sourceCode cpp">variant_size</code>/<code class="sourceCode cpp">variant_alternative</code>).</p>
<p>Starting from R8, this paper uses option #3. That is: every type
trait
<code class="sourceCode cpp">std<span class="op">::</span>is_meow</code>
is introduced as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_meow_type</code>,
while all other type traits
<code class="sourceCode cpp">std<span class="op">::</span>meow</code>
are introduced as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>meow</code>.</p>
<h2 data-number="4.5" id="odr-concerns"><span class="header-section-number">4.5</span> ODR Concerns<a href="#odr-concerns" class="self-link"></a></h2>
<p>Static reflection invariably brings new ways to violate ODR.</p>
<div class="std">
<blockquote>
<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><span class="co">// File &#39;cls.h&#39;</span></span>
<span id="cb113-2"><a href="#cb113-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Cls <span class="op">{</span></span>
<span id="cb113-3"><a href="#cb113-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> odr_violator<span class="op">()</span> <span class="op">{</span></span>
<span id="cb113-4"><a href="#cb113-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>members_of<span class="op">(</span>parent_of<span class="op">(^^</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)).</span>size<span class="op">()</span> <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb113-5"><a href="#cb113-5" aria-hidden="true" tabindex="-1"></a>      branch_1<span class="op">()</span>;</span>
<span id="cb113-6"><a href="#cb113-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span></span>
<span id="cb113-7"><a href="#cb113-7" aria-hidden="true" tabindex="-1"></a>      branch_2<span class="op">()</span>;</span>
<span id="cb113-8"><a href="#cb113-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb113-9"><a href="#cb113-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Two translation units including
<code class="sourceCode cpp">cls<span class="op">.</span>h</code> can
generate different definitions of <code class="sourceCode cpp">Cls<span class="op">::</span>odr_violator<span class="op">()</span></code>
based on whether an odd or even number of declarations have been
imported from <code class="sourceCode cpp">std</code>. Branching on the
members of a namespace is dangerous because namespaces may be redeclared
and reopened: the set of contained declarations can differ between
program points.</p>
<p>The creative programmer will find no difficulty coming up with other
predicates which would be similarly dangerous if substituted into the
same <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span></code>
condition: for instance, given a branch on <code class="sourceCode cpp">is_complete_type<span class="op">(^^</span>T<span class="op">)</span></code>,
if one translation unit
<code class="sourceCode cpp"><span class="pp">#include</span></code>s a
forward declaration of <code class="sourceCode cpp">T</code>, another
<code class="sourceCode cpp"><span class="pp">#include</span></code>s a
complete definition of <code class="sourceCode cpp">T</code>, and they
both afterwards <code class="sourceCode cpp"><span class="pp">#include </span><span class="im">&quot;cls.h&quot;</span></code>,
the result will be an ODR violation.</p>
<p>Additional papers are already in flight proposing additional
metafunctions that pose similar dangers. For instance, <span class="citation" data-cites="P3096R2"><a href="https://wg21.link/p3096r2" role="doc-biblioref">[P3096R2]</a></span> proposes the
<code class="sourceCode cpp">parameters_of</code> metafunction. This
feature is important for generating language bindings (e.g., Python,
JavaScript), but since parameter names can differ between declarations,
it would be dangerous for a member function defined in a header file to
branch on the name of a parameter.</p>
<p>These cases are not difficult to identify: Given an entity
<code class="sourceCode cpp">E</code> and two program points
<code class="sourceCode cpp">P1</code> and
<code class="sourceCode cpp">P2</code> from which a reflection of
<code class="sourceCode cpp">E</code> may be optained, it is unsafe to
branch runtime code generation on any property of
<code class="sourceCode cpp">E</code> (e.g., namespace members,
parameter names, completeness of a class) that can be modified between
<code class="sourceCode cpp">P1</code> and
<code class="sourceCode cpp">P2</code>. Worth noting as well, these
sharp edges are not unique (or new) to reflection: It is already
possible to build an ODR trap based on the completeness of a class using
C++23.</p>
<p>Education and training are important to help C++ users avoid such
sharp edges, but we do not find them sufficiently concerning to give
pause to our enthusiasm for the features proposed by this paper.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="proposed-wording"><span class="header-section-number">5</span>
Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note:
Throughout the wording, we say that a reflection (an object of type
<code class="sourceCode default">std::meta::info</code>)
<em>represents</em> some source construct, while splicing that
reflection <em>designates</em> that source construct. For instance,
<code class="sourceCode default">^^int</code> represents the type
<code class="sourceCode default">int</code> and
<code class="sourceCode default">[: ^^int :]</code> designates the type
<code class="sourceCode default">int</code>. ]</span></p>
<h2 data-number="5.1" id="language"><span class="header-section-number">5.1</span> Language<a href="#language" class="self-link"></a></h2>
<h3 class="unnumbered" id="intro.defs-terms-and-definitions"><span>3 <a href="https://wg21.link/intro.defs">[intro.defs]</a></span> Terms and
definitions<a href="#intro.defs-terms-and-definitions" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>splice-specifier</em></code> to
the list of template argument forms in definition 3.5.</p>
<div class="std">
<blockquote>
<p><strong><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">(3.5)</a></span>
argument</strong></p>
<p>⟨template instantiation⟩
<code class="sourceCode cpp"><em>constant-expression</em></code>,
<code class="sourceCode cpp"><em>type-id</em></code>, <span class="rm" style="color: #bf0303"><del>or</del></span>
<code class="sourceCode cpp"><em>id-expression</em></code><span class="addu">, or
<code class="sourceCode cpp"><em>splice-specifier</em></code></span> in
the comma-separated list bounded by the angle brackets</p>
</blockquote>
</div>
<h3 class="unnumbered" id="lex.phases-phases-of-translation"><span>5.2
<a href="https://wg21.link/lex.phases">[lex.phases]</a></span> Phases of
translation<a href="#lex.phases-phases-of-translation" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
addition to changes necessary for this proposal, we are applying the
“drive-by fix” of merging phases 7/8, in order to clarify that template
instantiation is interleaved with translation. In so doing, we replace
the notion of “instantiation units” with a partial ordering among all
program constructs in a translation unit. ]</span></p>
<p>Modify the wording for phases 7-8 of <span>5.2 <a href="https://wg21.link/lex.phases">[lex.phases]</a></span> as
follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">7-8</a></span>
Each preprocessing token is converted into a token (<span>5.10 <a href="https://wg21.link/lex.token">[lex.token]</a></span>). Whitespace
characters separating tokens are no longer significant. The resulting
tokens constitute a <em>translation unit</em> and are syntactically and
semantically analyzed as a
<code class="sourceCode cpp"><em>translation-unit</em></code>
([basic.link]) and translated.</p>
<p><span class="note3"><span>[ <em>Note 3:</em> </span>The process of
analyzing and translating the tokens can occasionally result in one
token being replaced by a sequence of other tokens ([temp.names])<span>
— <em>end note</em> ]</span></span></p>
<p>It is implementation-defined whether the sources for module-units and
header units on which the current translation unit has an interface
dependency (<span>10.1 <a href="https://wg21.link/module.unit">[module.unit]</a></span>,
<span>10.3 <a href="https://wg21.link/module.import">[module.import]</a></span>) are
required to be available.</p>
<p><span class="note"><span>[ <em>Note 4:</em> </span>Source files,
translation units and translated translation units need not necessarily
be stored as files, nor need there be any one-to-one correspondence
between these entities and any external representation. The description
is conceptual only, and does not specify any particular
implementation.<span> — <em>end note</em> ]</span></span></p>
<p><span class="rm" style="color: #bf0303"><del>Translated translation
units and instantiation units are combined as follows:</del></span></p>
<p><span class="rm" style="color: #bf0303"><del><span class="note5"><span>[ <em>Note 5:</em> </span>Some or all of these can
be supplied from a library.<span> — <em>end
note</em> ]</span></span></del></span></p>
<p><span class="rm" style="color: #bf0303"><del>Each translated
translation unit is examined to produce a list of required
instantiations.</del></span></p>
<p><span class="addu">While the tokens constituting translation units
are being analyzed and translated, required instantiations are
performed.</span></p>
<p><span class="note5"><span>[ <em>Note 5:</em> </span>This can include
instantiations which have been explicitly requested
([temp.explicit]).<span> — <em>end note</em> ]</span></span></p>
<p><span class="addu">The contexts from which instantiations may be
performed are determined by their respective points of instantiation
(<span>13.8.4.1 <a href="https://wg21.link/temp.point">[temp.point]</a></span>).</span></p>
<p><span class="addu"><span class="note"><span>[ <em>Note 6:</em>
</span>Other requirements in this document can further constrain the
context from which an instantiation can be performed. For example, a
constexpr function template specialization might have a point of
instantation at the end of a translation unit, but its use in certain
constant expressions could require that it be instantiated at an earlier
point ([temp.inst]).<span> — <em>end
note</em> ]</span></span></span></p>
<p><span class="rm" style="color: #bf0303"><del>The definitions of the
required templates are located. It is implementation-defined whether the
source of the translation units containing these definitions is required
to be available.</del></span></p>
<p><span class="rm" style="color: #bf0303"><del><span class="note"><span>[ <em>Note 7:</em> </span>An implementation can
choose to encode sufficient information into the translated translation
unit so as to ensure the source is not required here.<span> — <em>end
note</em> ]</span></span></del></span></p>
<p><span class="rm" style="color: #bf0303"><del>All required
instantiations are perfomed to produce <em>instantiation
units</em>.</del></span></p>
<p><span class="rm" style="color: #bf0303"><del><span class="note"><span>[ <em>Note 8:</em> </span>These are similar to
translated translation units, but contain no references to
uninstantiated templates and no template definitions.<span> — <em>end
note</em> ]</span></span></del></span></p>
<p><span class="addu">Each instantiation results in new program
constructs.</span> The program is ill-formed if any instantiation
fails.</p>
<div class="addu">
<p>During the analysis and translation of tokens, certain expressions
are evaluated ([expr.const]). Constructs appearing at a program point
<code class="sourceCode cpp"><em>P</em></code> are analyzed in a context
where each side effect of evaluating an expression
<code class="sourceCode cpp"><em>E</em></code> as a full-expression is
complete if and only if</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(7-8.1)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is the expression
corresponding to a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
([dcl.pre]), and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">(7-8.2)</a></span>
either that
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
or the template definition from which it is instantiated is reachable
from</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(7-8.2.1)</a></span>
<code class="sourceCode cpp"><em>P</em></code>, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(7-8.2.2)</a></span>
the point immediately following the
<code class="sourceCode cpp"><em>class-specifier</em></code> of the
outermost class for which <code class="sourceCode cpp"><em>P</em></code>
is in a complete-class context.</li>
</ul></li>
</ul>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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="kw">class</span> S <span class="op">{</span></span>
<span id="cb114-2"><a href="#cb114-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> Incomplete;</span>
<span id="cb114-3"><a href="#cb114-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb114-4"><a href="#cb114-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> Inner <span class="op">{</span></span>
<span id="cb114-5"><a href="#cb114-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb114-6"><a href="#cb114-6" aria-hidden="true" tabindex="-1"></a>      <span class="co">/* p1 */</span> Incomplete i; <span class="co">// OK, constructs at P1 are analyzed in a context where the side effect of</span></span>
<span id="cb114-7"><a href="#cb114-7" aria-hidden="true" tabindex="-1"></a>                             <span class="co">// the call to define_aggregate is evaluated because:</span></span>
<span id="cb114-8"><a href="#cb114-8" aria-hidden="true" tabindex="-1"></a>                             <span class="co">// * E is the expression corresponding to a consteval block, and</span></span>
<span id="cb114-9"><a href="#cb114-9" aria-hidden="true" tabindex="-1"></a>                             <span class="co">// * P1 is in a complete-class context of S and the consteval block</span></span>
<span id="cb114-10"><a href="#cb114-10" aria-hidden="true" tabindex="-1"></a>                             <span class="co">//   is reachable from P3.</span></span>
<span id="cb114-11"><a href="#cb114-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb114-12"><a href="#cb114-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>; <span class="co">/* p2 */</span></span>
<span id="cb114-13"><a href="#cb114-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb114-14"><a href="#cb114-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb114-15"><a href="#cb114-15" aria-hidden="true" tabindex="-1"></a>    define_aggregate<span class="op">(^^</span>Incomplete, <span class="op">{})</span>;</span>
<span id="cb114-16"><a href="#cb114-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb114-17"><a href="#cb114-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>; <span class="co">/* p3 */</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">8</a></span>
<span class="rm" style="color: #bf0303"><del>All</del></span> <span class="addu">Translated translation units are combined and all</span>
external entity references are resolved. Library components are linked
to satisfy external references to entities not defined in the current
translation. All such translator output is collected into a program
image which contains information needed for execution in its execution
environment.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="lex.pptoken-preprocessing-tokens"><span>5.5
<a href="https://wg21.link/lex.pptoken">[lex.pptoken]</a></span>
Preprocessing tokens<a href="#lex.pptoken-preprocessing-tokens" class="self-link"></a></h3>
<p>Add a bullet after bullet (4.2):</p>
<div class="std">
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">4</a></span>
If the input stream has been parsed into preprocessing tokens up to a
given character:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">(4.1)</a></span>
…</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(4.2)</a></span>
Otherwise, if the next three characters are
<code class="sourceCode cpp"><span class="op">&lt;::</span></code> and
the subsequent character is neither
<code class="sourceCode cpp"><span class="op">:</span></code> nor
<code class="sourceCode cpp"><span class="op">&gt;</span></code>, the
<code class="sourceCode cpp"><span class="op">&lt;</span></code> is
treated as a preprocessing token by itself and not as the first
character of the alternative token
<code class="sourceCode cpp"><span class="op">&lt;:</span></code>.</p></li>
<li><p><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(4.3)</a></span>
Otherwise, if the next three characters are
<code class="sourceCode cpp"><span class="op">[::</span></code> and the
subsequent character is not
<code class="sourceCode cpp"><span class="op">:</span></code>, or if the
next three characters are
<code class="sourceCode cpp"><span class="op">[:&gt;</span></code>, the
<code class="sourceCode cpp"><span class="op">[</span></code> is treated
as a preprocessing token by itself and not as the first character of the
preprocessing token
<code class="sourceCode cpp"><span class="op">[:</span></code>.</span></p>
<p><span class="addu"><span class="note"><span>[ <em>Note 1:</em>
</span>The tokens
<code class="sourceCode cpp"><span class="op">[:</span></code> and
<code class="sourceCode cpp"><span class="op">:]</span></code> cannot be
composed from digraphs.<span> — <em>end
note</em> ]</span></span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(4.4)</a></span>
…</p></li>
</ul></li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="lex.operators-operators-and-punctuators"><span>5.8 <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>Change the grammar for
<code class="sourceCode cpp"><em>operator-or-punctuator</em></code> in
paragraph 1 of <span>5.8 <a href="https://wg21.link/lex.operators">[lex.operators]</a></span> to
include the reflection operator and the
<code class="sourceCode cpp"><em>splice-specifier</em></code>
delimiters:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb115"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb115-1"><a href="#cb115-1" aria-hidden="true" tabindex="-1"></a>  <em>operator-or-punctuator</em>: <em>one of</em></span>
<span id="cb115-2"><a href="#cb115-2" aria-hidden="true" tabindex="-1"></a>         {        }        [        ]        (        )        <span class="addu"><code class="sourceCode cpp"><span class="op">[:</span>        <span class="op">:]</span></code></span></span>
<span id="cb115-3"><a href="#cb115-3" aria-hidden="true" tabindex="-1"></a>         &lt;:       :&gt;       &lt;%       %&gt;       ;        :        ...</span>
<span id="cb115-4"><a href="#cb115-4" aria-hidden="true" tabindex="-1"></a>         ?        ::       .       .*        -&gt;       -&gt;*      ~</span>
<span id="cb115-5"><a href="#cb115-5" aria-hidden="true" tabindex="-1"></a>         !        +        -        *        /        %        ^        <span class="addu"><code class="sourceCode cpp"><span class="op">^^</span></code></span>       &amp;</span>
<span id="cb115-6"><a href="#cb115-6" aria-hidden="true" tabindex="-1"></a>         |        =        +=       -=       *=       /=       %=       ^=       &amp;=</span>
<span id="cb115-7"><a href="#cb115-7" aria-hidden="true" tabindex="-1"></a>         |=       ==       !=       &lt;        &gt;        &lt;=       &gt;=       &lt;=&gt;      &amp;&amp;</span>
<span id="cb115-8"><a href="#cb115-8" aria-hidden="true" tabindex="-1"></a>         ||       &lt;&lt;       &gt;&gt;       &lt;&lt;=      &gt;&gt;=      ++       --       ,</span>
<span id="cb115-9"><a href="#cb115-9" aria-hidden="true" tabindex="-1"></a>         and      or       xor      not      bitand   bitor    compl</span>
<span id="cb115-10"><a href="#cb115-10" aria-hidden="true" tabindex="-1"></a>         and_eq   or_eq    xor_eq   not_eq</span></code></pre></div>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.pre-preamble"><span>6.1 <a href="https://wg21.link/basic.pre">[basic.pre]</a></span> Preamble<a href="#basic.pre-preamble" class="self-link"></a></h3>
<p>Modify paragraph 7 such that denoting a variable by its name finds
the variable, not the associated object.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">7</a></span>
A <em>variable</em> is introduced by the declaration of a reference
other than a non-static data member or of an object. <span class="rm" style="color: #bf0303"><del>The variable’s name, if any, denotes the
reference or object.</del></span></p>
</blockquote>
</div>
<p>Add type aliases and namespace aliases to the list of entities in
paragraph 8. As drive-by fixes, remove “value”, “object”, “reference”,
and “template specialization”; replace “class member” with “non-static
data member”, since all other cases are subsumed by existing one. Add
“template parameters” and
“<code class="sourceCode cpp"><em>init-capture</em></code>s”, which
collectively subsume “packs”. Introduce a notion of an “underlying
entity” in the same paragraph, and utilize it for the definition of a
name “denoting” an entity. Type aliases are now entities, so also modify
accordingly.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">8</a></span>
An <em>entity</em> is a <span class="rm" style="color: #bf0303"><del>value, object, reference</del></span> <span class="addu">variable,</span> structured binding, result binding,
function, enumerator, type, <span class="addu">type alias</span>, <span class="rm" style="color: #bf0303"><del>class</del></span> <span class="addu">non-static data</span> member, bit-field, template, <span class="rm" style="color: #bf0303"><del>template
specialization,</del></span> namespace, <span class="addu">namespace
alias, template parameter, function parameter</span>, or <span class="addu"><code class="sourceCode cpp"><em>init-capture</em></code></span>
<span class="rm" style="color: #bf0303"><del>pack</del></span>. <span class="addu">The <em>underlying entity</em> of an entity is that entity
unless otherwise specified. A name <em>denotes</em> the underlying
entity of the entity declared by each declaration that introduces the
name.</span> <span class="rm" style="color: #bf0303"><del>An entity
<span><code class="sourceCode default"><em>E</em></code></span> is
denoted by the name (if any) that is introduced by a declaration of
<span><code class="sourceCode default"><em>E</em></code></span> or by a
<span><code class="sourceCode default"><em>typedef-name</em></code></span>
introduced by a declaration specifying
<span><code class="sourceCode default"><em>E</em></code></span>.</del></span></p>
<p><span class="addu"><span class="note"><span>[ <em>Note 1:</em>
</span>Type aliases and namespace aliases have underlying entities that
are distinct from themselves.<span> — <em>end
note</em> ]</span></span></span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.def-declarations-and-definitions"><span>6.2 <a href="https://wg21.link/basic.def">[basic.def]</a></span> Declarations
and definitions<a href="#basic.def-declarations-and-definitions" class="self-link"></a></h3>
<p>Modify the third sentence of paragraph 1 to clarify that type aliases
are now entities.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">1</a></span>
[…] A declaration of an entity <span class="rm" style="color: #bf0303"><del>or
<span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<code class="sourceCode cpp"><em>X</em></code> is a redeclaration of
<code class="sourceCode cpp"><em>X</em></code> if another declaration of
<code class="sourceCode cpp"><em>X</em></code> is reachable from it
(<span>10.7 <a href="https://wg21.link/module.reach">[module.reach]</a></span>);
otherwise, it is a <em>first declaration</em>. […]</p>
</blockquote>
</div>
<p>Since namespace aliases are now entities but their declarations are
not definitions, add
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
to the list of declarations in paragraph 2, just before
<code class="sourceCode cpp"><em>using-declaration</em></code>. Also
replace
<code class="sourceCode cpp"><em>static_assert-declaration</em></code>
with <code class="sourceCode cpp"><em>vacuous-decalaration</em></code>,
which also encompasses consteval blocks:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">2</a></span>
Each entity declared by a
<code class="sourceCode cpp"><em>declaration</em></code> is also
<em>defined</em> by that declaration unless:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">(2.1)</a></span>
it declares a function without specifying the function’s body
([dcl.fct.def]),</li>
</ul>
<p>[…]</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">(2.10)</a></span>
it is an <code class="sourceCode cpp"><em>alias-declaration</em></code>
([dcl.typedef]),</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_23" id="pnum_23">(2.11-)</a></span>
it is a
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
([namespace.alias]),</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">(2.11)</a></span>
it is a <code class="sourceCode cpp"><em>using-declaration</em></code>
([namespace.udecl]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">(2.12)</a></span>
it is a <code class="sourceCode cpp"><em>deduction-guide</em></code>
([temp.deduct.guide]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">(2.13)</a></span>
it is a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>static_assert-declaration</em></code></span></del></span>
<span class="addu"><code class="sourceCode cpp"><em>vacuous-declaration</em></code></span>
([dcl.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">(2.14)</a></span>
it is an
<code class="sourceCode cpp"><em>attribute-declaration</em></code>
([dcl.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">(2.15)</a></span>
it is an <code class="sourceCode cpp"><em>empty-declaration</em></code>
([dcl.pre]){.rm},</li>
</ul>
<p>[…]</p>
</blockquote>
</div>
<p>Also modify the example that follows:</p>
<div class="example">
<p><span>[ <em>Example 1:</em> </span>All but one of the following are
definitions:</p>
<div>
<div class="sourceCode" id="cb116"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb116-1"><a href="#cb116-1" aria-hidden="true" tabindex="-1"></a>  int a;                          // defines a</span>
<span id="cb116-2"><a href="#cb116-2" aria-hidden="true" tabindex="-1"></a>  extern const int c = 1;         // defines c</span>
<span id="cb116-3"><a href="#cb116-3" aria-hidden="true" tabindex="-1"></a>  int f(int x) { return x+a; }    // defines f and defines x</span>
<span id="cb116-4"><a href="#cb116-4" aria-hidden="true" tabindex="-1"></a>  struct S { int a; int b; };     // defines S, S::a, and S::b</span>
<span id="cb116-5"><a href="#cb116-5" aria-hidden="true" tabindex="-1"></a>  struct X {                      // defines X</span>
<span id="cb116-6"><a href="#cb116-6" aria-hidden="true" tabindex="-1"></a>    int x;                        // defines non-static data member x</span>
<span id="cb116-7"><a href="#cb116-7" aria-hidden="true" tabindex="-1"></a>    static int y;                 // declares static data member y</span>
<span id="cb116-8"><a href="#cb116-8" aria-hidden="true" tabindex="-1"></a>    X() : x(0) { }                // defines a constructor of X</span>
<span id="cb116-9"><a href="#cb116-9" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb116-10"><a href="#cb116-10" aria-hidden="true" tabindex="-1"></a>  int X::y = 1;                   // defines X::y</span>
<span id="cb116-11"><a href="#cb116-11" aria-hidden="true" tabindex="-1"></a>  enum { up, down };              // defines up and down</span>
<span id="cb116-12"><a href="#cb116-12" aria-hidden="true" tabindex="-1"></a>  namespace N {int d; }           // defines N and N::d</span>
<span id="cb116-13"><a href="#cb116-13" aria-hidden="true" tabindex="-1"></a><span class="st">- namespace N1 = N;               // defines N1</span></span>
<span id="cb116-14"><a href="#cb116-14" aria-hidden="true" tabindex="-1"></a>  X anX;                          // defines anX</span></code></pre></div>
</div>
<p>whereas these are just declarations:</p>
<div>
<div class="sourceCode" id="cb117"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb117-1"><a href="#cb117-1" aria-hidden="true" tabindex="-1"></a>  extern int a;                   // declares a</span>
<span id="cb117-2"><a href="#cb117-2" aria-hidden="true" tabindex="-1"></a>  extern const int c;             // declares c</span>
<span id="cb117-3"><a href="#cb117-3" aria-hidden="true" tabindex="-1"></a>  int f(int);                     // declares f</span>
<span id="cb117-4"><a href="#cb117-4" aria-hidden="true" tabindex="-1"></a>  struct S;                       // declares S</span>
<span id="cb117-5"><a href="#cb117-5" aria-hidden="true" tabindex="-1"></a>  typedef int Int;                // declares Int</span>
<span id="cb117-6"><a href="#cb117-6" aria-hidden="true" tabindex="-1"></a><span class="va">+ namespace N1 = N;               // declares N1</span></span>
<span id="cb117-7"><a href="#cb117-7" aria-hidden="true" tabindex="-1"></a>  extern X anotherX;              // declares anotherX</span>
<span id="cb117-8"><a href="#cb117-8" aria-hidden="true" tabindex="-1"></a>  using N::d;                     // declares d</span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
<h3 class="unnumbered" id="basic.def.odr-one-definition-rule"><span>6.3
<a href="https://wg21.link/basic.def.odr">[basic.def.odr]</a></span>
One-definition rule<a href="#basic.def.odr-one-definition-rule" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>splice-expression</em></code>s
to the set of potential results of an expression in paragraph 3.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_29" id="pnum_29">3</a></span>
An expression or conversion is <em>potentially evaluated</em> unless it
is an unevaluated operand ([expr.context]), a subexpression thereof, or
a conversion in an initialization or conversion sequence in such a
context. The set of <em>potential results</em> of an expression
<code class="sourceCode cpp"><em>E</em></code> is defined as
follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_30" id="pnum_30">(3.1)</a></span>
If <code class="sourceCode cpp"><em>E</em></code> is an
<code class="sourceCode cpp"><em>id-expression</em></code> (<span>7.5.5
<a href="https://wg21.link/expr.prim.id">[expr.prim.id]</a></span>)
<span class="addu">or a
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice])</span>, the set contains only
<code class="sourceCode cpp"><em>E</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_31" id="pnum_31">(3.2)</a></span>
[…]</li>
</ul>
<p><span class="note"><span>[ <em>Note 1:</em> </span>This set is a
(possibly-empty) set of
<code class="sourceCode cpp"><em>id-expression</em></code>s <span class="addu">and
<code class="sourceCode cpp"><em>splice-expression</em></code>s</span>,
each of which is either <code class="sourceCode cpp"><em>E</em></code>
or a subexpression of
<code class="sourceCode cpp"><em>E</em></code>.<span> — <em>end
note</em> ]</span></span></p>
<div class="example">
<p><span>[ <em>Example 1:</em> </span>In the following example, the set
of potential results of the initializer of
<code class="sourceCode cpp">n</code> contains the first
<code class="sourceCode cpp">S<span class="op">::</span>x</code>
subexpression, but not the second
<code class="sourceCode cpp">S<span class="op">::</span>x</code>
subexpression. <span class="addu">The set of potential results of the
initializer of <code class="sourceCode cpp">o</code> contains the <code class="sourceCode cpp"><span class="op">[:^^</span>S<span class="op">::</span>x<span class="op">:]</span></code>
subexpression.</span></p>
<div>
<div class="sourceCode" id="cb118"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb118-1"><a href="#cb118-1" aria-hidden="true" tabindex="-1"></a>  struct S { static const int x = 0; };</span>
<span id="cb118-2"><a href="#cb118-2" aria-hidden="true" tabindex="-1"></a>  const int &amp;f(const int &amp;r);</span>
<span id="cb118-3"><a href="#cb118-3" aria-hidden="true" tabindex="-1"></a>  int n = b ? (1, S::x)           // S::x is not odr-used here</span>
<span id="cb118-4"><a href="#cb118-4" aria-hidden="true" tabindex="-1"></a>            : f(S::x);            // S::x is odr-used here, so a definition is required</span>
<span id="cb118-5"><a href="#cb118-5" aria-hidden="true" tabindex="-1"></a><span class="va">+ int o = [:^^S::x:];</span></span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<p>Break bullet 4.1 into sub-bullets and modify it to cover splicing of
functions:</p>
<div class="std">
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_32" id="pnum_32">(4.1)</a></span>
A function is named by an expression or conversion <span class="addu"><code class="sourceCode cpp"><em>E</em></code></span> if it
is the selected member of an overload set ([basic.lookup], [over.match],
[over.over]) in an overload resolution performed as part of forming that
expression or conversion, unless it is a pure virtual function and <span class="rm" style="color: #bf0303"><del>either the
expression</del></span><span class="addu"> </span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_33" id="pnum_33">(4.1.1)</a></span>
<span class="addu"><code class="sourceCode cpp"><em>E</em></code></span>
is not an <code class="sourceCode cpp"><em>id-expression</em></code>
naming the function with an explicitly qualified name<span class="addu">,</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_34" id="pnum_34">(4.1.2)</a></span>
<span class="addu"><code class="sourceCode cpp"><em>E</em></code></span>
is a
<code class="sourceCode cpp"><em>splice-expression</em></code>,</span>
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_35" id="pnum_35">(4.1.3)</a></span>
<span class="rm" style="color: #bf0303"><del>the expression</del></span>
<span class="addu"><code class="sourceCode cpp"><em>E</em></code></span>
forms a pointer to member ([expr.unary.op]).</li>
</ul></li>
</ul>
</blockquote>
</div>
<p>Modify the first sentence of paragraph 5 to cover splicing of
variables:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_36" id="pnum_36">5</a></span>
A variable is named by an expression if the expression is an
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice])</span> that <span class="rm" style="color: #bf0303"><del>denotes</del></span> <span class="addu">designates</span> it.</p>
</blockquote>
</div>
<p>Modify paragraph 6 to cover splicing of structured bindings:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_37" id="pnum_37">6</a></span>
A structured binding is <span class="rm" style="color: #bf0303"><del>odr-used if it appears as a
potentially-evaluated</del></span> <span class="addu">named by an</span>
expression <span class="addu">if that expression is either an</span>
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or a
<code class="sourceCode cpp"><em>splice-expression</em></code> that
designates that structured binding. A structured binding is odr-used if
it is named by a potentially-evaluated expression.</span></p>
</blockquote>
</div>
<p>Prepend before paragraph 15 of <span>6.3 <a href="https://wg21.link/basic.def.odr">[basic.def.odr]</a></span>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_38" id="pnum_38">15pre</a></span>
If a class <code class="sourceCode cpp">C</code> is defined in a
translation unit as a result of a call to a specialization of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_aggregate</code>
and another translation unit contains a definition of
<code class="sourceCode cpp">C</code> that is not a result of calling
the same specialization with the same function arguments, the program is
ill-formed; a diagnostic is required only if
<code class="sourceCode cpp">C</code> is attached to a named module and
a prior definition is reachable at the point where a later definition
occurs.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_39" id="pnum_39">15</a></span>
For any <span class="addu">other</span> definable item
<code class="sourceCode cpp">D</code> with definitions in multiple
translation units,</p>
<ul>
<li>if <code class="sourceCode cpp">D</code> is a non-inline
non-templated function or variable, or</li>
<li>if the definitions in different translation units do not satisfy the
following requirements,</li>
</ul>
<p>the program is ill-formed; a diagnostic is required only if the
definable item is attached to a named module and a prior definition is
reachable at the point where a later definition occurs. […]</p>
</blockquote>
</div>
<p>Prefer the verb “denote” in bullet 15.5 to emphasize that ODR “looks
through” aliases, and clarify that objects are not entities in bullet
15.5.2.</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_40" id="pnum_40">(15.5)</a></span>
In each such definition, corresponding names, looked up according to
[basic.lookup], shall <span class="rm" style="color: #bf0303"><del>refer
to</del></span> <span class="addu">denote</span> the same entity, after
overload resolution ([over.match]) and after matching of partial
template specialization ([temp.over]), except that a name can refer to
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_41" id="pnum_41">(15.5.1)</a></span>
a non-volatile const object […], or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_42" id="pnum_42">(15.5.2)</a></span>
a reference with internal or no linkage initialized with a constant
expression such that the reference refers to the same <span class="rm" style="color: #bf0303"><del>entity</del></span> <span class="addu">object or function</span> in all definitions of
<code class="sourceCode cpp"><em>D</em></code>.</li>
</ul></li>
</ul>
</blockquote>
</div>
<p>Clarify in bullet 15.11 that default template-arguments in
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s
also factor into ODR:</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_43" id="pnum_43">(15.11)</a></span>
In each such definition, a default argument used by an (implicit or
explicit) function call or a default template argument used by an
(implicit or explicit)
<code class="sourceCode cpp"><em>template-id</em></code><span class="addu">,</span> <span class="rm" style="color: #bf0303"><del>or</del></span>
<code class="sourceCode cpp"><em>simple-template-id</em></code><span class="addu">, or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
is treated as if its token sequence were present in the definition of
<code class="sourceCode cpp"><em>D</em></code>; that is, the default
argument or default template argument is subject to the requirements
described in this paragraph (recursively).</li>
</ul>
</blockquote>
</div>
<p>And add a bullet thereafter that factors the result of a
<code class="sourceCode cpp"><em>reflect-expression</em></code> into
ODR.</p>
<div class="std">
<blockquote>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_44" id="pnum_44">(15.11+)</a></span>
In each such definition, corresponding
<code class="sourceCode cpp"><em>reflect-expression</em></code>s
([expr.reflect]) compute equivalent values ([expr.eq]).</li>
</ul>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.scope.scope-general"><span>6.4.1 <a href="https://wg21.link/basic.scope.scope">[basic.scope.scope]</a></span>
General<a href="#basic.scope.scope-general" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
introduction of a “host scope” in paragraph 2 is part of the resolution
to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span>. ]</span></p>
<p>Define the “host scope” of a declaration in paragraph 2:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_45" id="pnum_45">2</a></span>
Unless otherwise specified:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_46" id="pnum_46">(2.1)</a></span>
The smallest scope that contains a scope
<code class="sourceCode cpp"><em>S</em></code> is the <em>parent
scope</em> of <code class="sourceCode cpp"><em>S</em></code>.</li>
</ul>
<p>[…]</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_47" id="pnum_47">(2.5)</a></span>
Any names (re)introduced by a declaration are <em>bound</em> to it in
its target scope.</li>
</ul>
<p><span class="addu">The <em>host scope</em> of a declaration is the
inhabited scope if that scope is a block scope and the target scope
otherwise.</span> An entity <em>belongs</em> to a scope
<code class="sourceCode cpp"><em>S</em></code> if
<code class="sourceCode cpp"><em>S</em></code> is the target scope of a
declaration of the entity.</p>
</blockquote>
</div>
<p>Change bullet 4.2 to refer to the declaration of a “type alias”
instead of a
<code class="sourceCode cpp"><em>typedef-name</em></code>.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_48" id="pnum_48">(4.2)</a></span>
one declares a type (not a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span>) and the other declares a variable,
non-static data member other than an anonymous union
([class.union.anon]), enumerator, function, or function template, or</p>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.lookup.general-general"><span>6.5.1 <a href="https://wg21.link/basic.lookup.general">[basic.lookup.general]</a></span>
General<a href="#basic.lookup.general-general" class="self-link"></a></h3>
<p>Adjust paragraph 4 since type aliases are now entities.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_49" id="pnum_49">4</a></span>
In certain contexts, only certain kinds of declarations are included.
After any such restriction, any declarations of classes or enumerations
are discarded if any other declarations are found.</p>
<p><span class="note4"><span>[ <em>Note 4:</em> </span>A type (but not a
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span> or template) is therefore hidden by
any other entity in its scope.<span> — <em>end
note</em> ]</span></span></p>
<p>However, if lookup is <em>type-only</em>, only declarations of types
and templates whose specializations are types are considered;
furthermore, if declarations of a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span> and of <span class="rm" style="color: #bf0303"><del>the type to which it refers</del></span>
<span class="addu">its underlying entity</span> are found, the
declaration of the <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span> is discarded instead of the type
declaration.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.lookup.argdep-argument-dependent-name-lookup"><span>6.5.4 <a href="https://wg21.link/basic.lookup.argdep">[basic.lookup.argdep]</a></span>
Argument-dependent name lookup<a href="#basic.lookup.argdep-argument-dependent-name-lookup" class="self-link"></a></h3>
<p>Modify the first bullet of paragraph 3 of <span>6.5.4 <a href="https://wg21.link/basic.lookup.argdep">[basic.lookup.argdep]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_50" id="pnum_50">3</a></span>
… Any <code class="sourceCode cpp"><em>typedef-name</em></code>s and
<code class="sourceCode cpp"><em>using-declaration</em></code>s used to
specify the types do not contribute to this set. The set of entities is
determined in the following way:</p>
<ul>
<li><p><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_51" id="pnum_51">(3.1-)</a></span>
If <code class="sourceCode cpp">T</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
([meta.reflection.synop]), its associated set of entities is the
singleton containing the enumeration type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>operators</code>
([meta.reflection.operators]).</span></p>
<p><span class="addu"><span class="note"><span>[ <em>Note 1:</em>
</span>The <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
type is a type alias, so an explicit rule is needed to associate calls
whose arguments are reflections with the namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>.<span>
— <em>end note</em> ]</span></span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_52" id="pnum_52">(3.1)</a></span>
If <code class="sourceCode cpp">T</code> is <span class="rm" style="color: #bf0303"><del>a</del></span> <span class="addu">any
other</span> fundamental type, its associated set of entities is
empty.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_53" id="pnum_53">(3.2)</a></span>
If <code class="sourceCode cpp">T</code> is a class type …</p></li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.lookup.qual.general-general"><span>6.5.5.1 <a href="https://wg21.link/basic.lookup.qual.general">[basic.lookup.qual.general]</a></span>
General<a href="#basic.lookup.qual.general-general" class="self-link"></a></h3>
<p>Extend paragraph 1 to cover
<code class="sourceCode cpp"><em>splice-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_54" id="pnum_54">1</a></span>
Lookup of an <em>identifier</em> followed by a
<code class="sourceCode cpp"><span class="op">::</span></code> scope
resolution operator considers only namespaces, types, and templates
whose specializations are types. If a name,
<code class="sourceCode cpp"><em>template-id</em></code>, <span class="addu"><code class="sourceCode cpp"><em>splice-scope-specifier</em></code>,</span>
or <code class="sourceCode cpp"><em>computed-type-specifier</em></code>
is followed by a
<code class="sourceCode cpp"><span class="op">::</span></code>, it shall
<span class="addu">either be a dependent
<code class="sourceCode cpp"><em>splice-scope-specifier</em></code>
([temp.dep.splice]) or it shall</span> designate a namespace, class,
enumeration, or dependent type, and the
<code class="sourceCode cpp"><span class="op">::</span></code> is never
interpreted as a complete
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>.</p>
</blockquote>
</div>
<p>Add
<code class="sourceCode cpp"><em>qualified-reflection-name</em></code>
([expr.reflect]) to the list of non-terminals in bullet 2.4.5 that are
“qualified names” in the presence of a
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_55" id="pnum_55">2</a></span>
[…] A <em>qualified name</em> is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_56" id="pnum_56">(2.3)</a></span>
a member-qualified name or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_57" id="pnum_57">(2.4)</a></span>
the terminal name of
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_58" id="pnum_58">(2.4.1)</a></span>
a <code class="sourceCode cpp"><em>qualified-id</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_59" id="pnum_59">(2.4.2)</a></span>
a <code class="sourceCode cpp"><em>using-declarator</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_60" id="pnum_60">(2.4.3)</a></span>
a <code class="sourceCode cpp"><em>typename-specifier</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_61" id="pnum_61">(2.4.4)</a></span>
a
<code class="sourceCode cpp"><em>qualified-namespace-specifier</em></code>,
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_62" id="pnum_62">(2.4.5)</a></span>
a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<span class="addu"><code class="sourceCode cpp"><em>qualified-reflection-name</em></code>,</span>
<code class="sourceCode cpp"><em>elaborated-type-specifier</em></code>,
or <code class="sourceCode cpp"><em>class-or-decltype</em></code> that
has a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
([expr.prim.id.qual]).</li>
</ul></li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.splice-splice-specifiers">6.5+
[basic.splice] Splice specifiers<a href="#basic.splice-splice-specifiers" class="self-link"></a></h3>
<p>Add a new subsection after <span>6.5 <a href="https://wg21.link/basic.lookup">[basic.lookup]</a></span>, and
renumber accordingly:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Splice specifiers [basic.splice]</strong></p>
<div class="sourceCode" id="cb119"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb119-1"><a href="#cb119-1" aria-hidden="true" tabindex="-1"></a><em>splice-specifier</em>:</span>
<span id="cb119-2"><a href="#cb119-2" aria-hidden="true" tabindex="-1"></a>  [: <em>constant-expression</em> :]</span>
<span id="cb119-3"><a href="#cb119-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb119-4"><a href="#cb119-4" aria-hidden="true" tabindex="-1"></a><em>splice-specialization-specifier</em>:</span>
<span id="cb119-5"><a href="#cb119-5" aria-hidden="true" tabindex="-1"></a>  <em>splice-specifier</em> &lt; <em>template-argument-list</em><sub><em>opt</em></sub> &gt;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_63" id="pnum_63">1</a></span>
The <code class="sourceCode cpp"><em>constant-expression</em></code> of
a <code class="sourceCode cpp"><em>splice-specifier</em></code> shall be
a converted constant expression of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
(<span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span>). A
<code class="sourceCode cpp"><em>splice-specifier</em></code> whose
converted
<code class="sourceCode cpp"><em>constant-expression</em></code>
represents a construct <code class="sourceCode cpp"><em>X</em></code> is
said to <em>designate</em> either</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_64" id="pnum_64">(1.1)</a></span>
the underlying entity of <code class="sourceCode cpp"><em>X</em></code>
if <code class="sourceCode cpp"><em>X</em></code> is an entity
(<span>6.1 <a href="https://wg21.link/basic.pre">[basic.pre]</a></span>), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_65" id="pnum_65">(1.2)</a></span>
<code class="sourceCode cpp"><em>X</em></code> otherwise.</li>
</ul>
<p><span class="note"><span>[ <em>Note 1:</em> </span>A
<code class="sourceCode cpp"><em>splice-specifier</em></code> is
dependent if the converted
<code class="sourceCode cpp"><em>constant-expression</em></code> is
value-dependent ([temp.dep.splice]).<span> — <em>end
note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_66" id="pnum_66">2</a></span>
The <code class="sourceCode cpp"><em>splice-specifier</em></code> of a
non-dependent
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
shall designate a template.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_67" id="pnum_67">3</a></span>
<span class="note"><span>[ <em>Note 2:</em> </span>A
<code class="sourceCode cpp"><span class="op">&lt;</span></code>
following a
<code class="sourceCode cpp"><em>splice-specifier</em></code> is
interpreted as the delimiter of a
<code class="sourceCode cpp"><em>template-argument-list</em></code> when
the <code class="sourceCode cpp"><em>splice-specifier</em></code> is
preceded by
<code class="sourceCode cpp"><span class="kw">typename</span></code> or
<code class="sourceCode cpp"><span class="kw">template</span></code>, or
when it appears in a type-only context (<span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span>).<span>
— <em>end note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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="kw">constexpr</span> <span class="dt">int</span> v <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb120-2"><a href="#cb120-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span> V<span class="op">&gt;</span> <span class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb120-3"><a href="#cb120-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> s <span class="op">=</span> V <span class="op">+</span> <span class="dv">1</span>;</span>
<span id="cb120-4"><a href="#cb120-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb120-5"><a href="#cb120-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb120-6"><a href="#cb120-6" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> alias <span class="op">=</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;[:^^</span>v<span class="op">:]&gt;</span>;</span>
<span id="cb120-7"><a href="#cb120-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, a splice-specialization-specifier with a splice-specifier</span></span>
<span id="cb120-8"><a href="#cb120-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// as a template argument</span></span>
<span id="cb120-9"><a href="#cb120-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb120-10"><a href="#cb120-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>alias<span class="op">::</span>s <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb120-11"><a href="#cb120-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb120-12"><a href="#cb120-12" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> o1 <span class="op">=</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;[:^^</span>v<span class="op">:]&gt;()</span>;          <span class="co">// error: &lt; means less than</span></span>
<span id="cb120-13"><a href="#cb120-13" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> o2 <span class="op">=</span> <span class="kw">typename</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;[:^^</span>v<span class="op">:]&gt;()</span>; <span class="co">// ok, o2 is an object of type TCls&lt;1&gt;</span></span>
<span id="cb120-14"><a href="#cb120-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb120-15"><a href="#cb120-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">int</span> bad_splice<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb120-16"><a href="#cb120-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">[:</span>v<span class="op">:]</span>; <span class="co">// error: v is not constant</span></span>
<span id="cb120-17"><a href="#cb120-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.link-program-and-linkage"><span>6.6 <a href="https://wg21.link/basic.link">[basic.link]</a></span> Program and
Linkage<a href="#basic.link-program-and-linkage" class="self-link"></a></h3>
<p>Add a bullet to paragraph 13 and handle
<code class="sourceCode cpp"><em>splice-expression</em></code>s in the
existing bullets:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_68" id="pnum_68">13</a></span>
A declaration <code class="sourceCode cpp"><em>D</em></code>
<em>names</em> an entity <code class="sourceCode cpp"><em>E</em></code>
if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_69" id="pnum_69">(13.1)</a></span>
<code class="sourceCode cpp"><em>D</em></code> contains a
<code class="sourceCode cpp"><em>lambda-expression</em></code> whose
closure type is <code class="sourceCode cpp"><em>E</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_70" id="pnum_70">(13.1+)</a></span>
<span class="addu"><code class="sourceCode cpp"><em>D</em></code>
contains a manifestly constant-evaluated expression of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
that represents
<code class="sourceCode cpp"><em>E</em></code>,</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_71" id="pnum_71">(13.2)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is not a function or
function template and <code class="sourceCode cpp"><em>D</em></code>
contains an <code class="sourceCode cpp"><em>id-expression</em></code>,
<code class="sourceCode cpp"><em>type-specifier</em></code>,
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<code class="sourceCode cpp"><em>template-name</em></code>, or
<code class="sourceCode cpp"><em>concept-name</em></code> denoting
<code class="sourceCode cpp"><em>E</em></code> <span class="addu">or a
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-expression</em></code>
designating <code class="sourceCode cpp"><em>E</em></code></span>,
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_72" id="pnum_72">(13.3)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is a function or function
template and <code class="sourceCode cpp"><em>D</em></code> contains an
expression that names <code class="sourceCode cpp"><em>E</em></code>
([basic.def.odr]) or an
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
that refers to a set of overloads that contains
<code class="sourceCode cpp"><em>E</em></code>.</li>
</ul>
</blockquote>
</div>
<p>Modify paragraph 15 to make all type aliases and namespace aliases
explicitly TU-local.</p>
<div class="std">
<blockquote>
<p>An entity is <em>TU-local</em> if it is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_73" id="pnum_73">(15.1)</a></span>
a type, function, variable, or template that […]</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_74" id="pnum_74">(15.1+)</a></span>
a type alias or a namespace alias,</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_75" id="pnum_75">(15.2)</a></span>
[…]</li>
</ul>
</blockquote>
</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
below addition of “value or object of a TU-local type” is in part a
drive-by fix to make sure that enumerators in a TU-local enumeration are
also TU-local ]</span></p>
<p>Extend the definition of <em>TU-local</em> values and objects in p16
to include reflections:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_76" id="pnum_76">16</a></span>
A value or object is <em>TU-local</em> if</p>
<ul>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_77" id="pnum_77">(16.0)</a></span>
it is of TU-local type,</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_78" id="pnum_78">(16.1)</a></span>
it is, or is a pointer to, a TU-local function or the object associated
with a TU-local variable, <span class="rm" style="color: #bf0303"><del>or</del></span></li>
</ul>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_79" id="pnum_79">(16.1+)</a></span>
it is a reflection representing either
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_80" id="pnum_80">(16.1+.1)</a></span>
an entity, value, or object that is TU-local, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_81" id="pnum_81">(16.1+.2)</a></span>
a direct base class relationship introduced by an exposure, or</li>
</ul></li>
</ul>
</div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_82" id="pnum_82">(16.2)</a></span>
it is an object of class or array type and any of its subobjects or any
of the objects or functions to which its non-static data members of
reference type refer is TU-local and is usable in constant
expressions.</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.types.general-general"><span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>
General<a href="#basic.types.general-general" class="self-link"></a></h3>
<p>Change the first sentence in paragraph 9 of <span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_83" id="pnum_83">9</a></span>
Arithmetic types (<span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>),
enumeration types, pointer types, pointer-to-member types (<span>6.8.4
<a href="https://wg21.link/basic.compound">[basic.compound]</a></span>),
<span class="addu"><code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,</span>
<code class="sourceCode cpp">std<span class="op">::</span>nullptr_t</code>,
and cv-qualified versions of these types are collectively called
<em>scalar types</em>. …</p>
</blockquote>
</div>
<p>Add a new paragraph at the end of <span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_84" id="pnum_84">12</a></span>
A type is <em>consteval-only</em> if it is either <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
or a type compounded from a consteval-only type ([basic.compound]).
Every object of consteval-only type shall be</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_85" id="pnum_85">(12.1)</a></span>
the object associated with a constexpr variable or a subobject
thereof,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_86" id="pnum_86">(12.2)</a></span>
a template parameter object (<span>13.2 <a href="https://wg21.link/temp.param">[temp.param]</a></span>) or a
subobject thereof, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_87" id="pnum_87">(12.3)</a></span>
an object whose lifetime begins and ends during the evaluation of a core
constant expression.</li>
</ul>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.fundamental-fundamental-types"><span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>
Fundamental types<a href="#basic.fundamental-fundamental-types" class="self-link"></a></h3>
<p>Add new paragraphs before the last paragraph of <span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_88" id="pnum_88">16</a></span>
The types denoted by <code class="sourceCode cpp"><em>cv</em> std​<span class="op">::</span>​nullptr_t</code>
are distinct types. […]</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_89" id="pnum_89">x</a></span>
A value of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
is called a <em>reflection</em>. There exists a unique <em>null
reflection</em>; every other reflection is a representation of</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_90" id="pnum_90">(x.1)</a></span>
a value of scalar type ([temp.param]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_91" id="pnum_91">(x.2)</a></span>
an object with static storage duration ([basic.stc]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_92" id="pnum_92">(x.3)</a></span>
a variable ([basic.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_93" id="pnum_93">(x.4)</a></span>
a structured binding ([dcl.struct.bind]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_94" id="pnum_94">(x.5)</a></span>
a function ([dcl.fct]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_95" id="pnum_95">(x.6)</a></span>
an enumerator ([dcl.enum]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_96" id="pnum_96">(x.7)</a></span>
a type alias ([dcl.typedef]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_97" id="pnum_97">(x.8)</a></span>
a type ([basic.types]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_98" id="pnum_98">(x.9)</a></span>
a class member ([class.mem]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_99" id="pnum_99">(x.10)</a></span>
an unnamed bit-field ([class.bit]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_100" id="pnum_100">(x.11)</a></span>
a primary class template ([temp.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_101" id="pnum_101">(x.12)</a></span>
a function template ([temp.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_102" id="pnum_102">(x.13)</a></span>
a primary variable template ([temp.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_103" id="pnum_103">(x.14)</a></span>
an alias template ([temp.alias]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_104" id="pnum_104">(x.15)</a></span>
a concept ([temp.concept]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_105" id="pnum_105">(x.16)</a></span>
a namespace alias ([namespace.alias]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_106" id="pnum_106">(x.17)</a></span>
a namespace ([basic.namespace.general]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_107" id="pnum_107">(x.18)</a></span>
a direct base class relationship ([class.derived.general]), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_108" id="pnum_108">(x.19)</a></span>
a data member description ([class.mem.general]).</li>
</ul>
<p>A reflection is said to <em>represent</em> the corresponding
construct.</p>
<p><span class="note"><span>[ <em>Note 1:</em> </span>A reflection of a
value can be produced by library functions such as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>constant_of</code>
and <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_constant</code><span>
— <em>end note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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><span class="dt">int</span> arr<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb121-2"><a href="#cb121-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="op">[</span>a1, a2, a3<span class="op">]</span> <span class="op">=</span> arr;</span>
<span id="cb121-3"><a href="#cb121-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fn<span class="op">()</span>;</span>
<span id="cb121-4"><a href="#cb121-4" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Enum <span class="op">{</span> A <span class="op">}</span>;</span>
<span id="cb121-5"><a href="#cb121-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Alias <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb121-6"><a href="#cb121-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">{}</span>;</span>
<span id="cb121-7"><a href="#cb121-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">:</span> B <span class="op">{</span></span>
<span id="cb121-8"><a href="#cb121-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> mem;</span>
<span id="cb121-9"><a href="#cb121-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> <span class="op">:</span> <span class="dv">0</span>;</span>
<span id="cb121-10"><a href="#cb121-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb121-11"><a href="#cb121-11" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span><span class="op">&gt;</span> <span class="kw">struct</span> TCls <span class="op">{}</span>;</span>
<span id="cb121-12"><a href="#cb121-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span><span class="op">&gt;</span> <span class="dt">void</span> TFn<span class="op">()</span>;</span>
<span id="cb121-13"><a href="#cb121-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span><span class="op">&gt;</span> <span class="dt">int</span> TVar;</span>
<span id="cb121-14"><a href="#cb121-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span><span class="op">&gt;</span> <span class="kw">concept</span> Concept <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">true</span>; <span class="op">}</span>;</span>
<span id="cb121-15"><a href="#cb121-15" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> NS <span class="op">{}</span>;</span>
<span id="cb121-16"><a href="#cb121-16" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> NSAlias <span class="op">=</span> NS;</span>
<span id="cb121-17"><a href="#cb121-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-18"><a href="#cb121-18" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb121-19"><a href="#cb121-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-20"><a href="#cb121-20" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_constant<span class="op">(</span><span class="dv">42</span><span class="op">)</span>;  <span class="co">// represents int value of 42</span></span>
<span id="cb121-21"><a href="#cb121-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-22"><a href="#cb121-22" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_object<span class="op">(</span>arr<span class="op">[</span><span class="dv">1</span><span class="op">])</span>;  <span class="co">// represents int object</span></span>
<span id="cb121-23"><a href="#cb121-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-24"><a href="#cb121-24" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r3 <span class="op">=</span> <span class="op">^^</span>arr;      <span class="co">// represents a variable</span></span>
<span id="cb121-25"><a href="#cb121-25" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r4 <span class="op">=</span> <span class="op">^^</span>a3;       <span class="co">// represents a structured binding</span></span>
<span id="cb121-26"><a href="#cb121-26" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r5 <span class="op">=</span> <span class="op">^^</span>fn;       <span class="co">// represents a function</span></span>
<span id="cb121-27"><a href="#cb121-27" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r6 <span class="op">=</span> <span class="op">^^</span>Enum<span class="op">::</span>A;  <span class="co">// represents an enumerator</span></span>
<span id="cb121-28"><a href="#cb121-28" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r7 <span class="op">=</span> <span class="op">^^</span>Alias;    <span class="co">// represents a type alias</span></span>
<span id="cb121-29"><a href="#cb121-29" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r8 <span class="op">=</span> <span class="op">^^</span>S;        <span class="co">// represents a type</span></span>
<span id="cb121-30"><a href="#cb121-30" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r9 <span class="op">=</span> <span class="op">^^</span>S<span class="op">::</span>mem;   <span class="co">// represents a class member</span></span>
<span id="cb121-31"><a href="#cb121-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-32"><a href="#cb121-32" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r10 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>members_of<span class="op">(^^</span>S, ctx<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb121-33"><a href="#cb121-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// represents an unnamed bit-field</span></span>
<span id="cb121-34"><a href="#cb121-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-35"><a href="#cb121-35" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r11 <span class="op">=</span> <span class="op">^^</span>TCls;     <span class="co">// represents a class template</span></span>
<span id="cb121-36"><a href="#cb121-36" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r12 <span class="op">=</span> <span class="op">^^</span>TFn;      <span class="co">// represents a function template</span></span>
<span id="cb121-37"><a href="#cb121-37" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r13 <span class="op">=</span> <span class="op">^^</span>TVar;     <span class="co">// represents a variable template</span></span>
<span id="cb121-38"><a href="#cb121-38" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r14 <span class="op">=</span> <span class="op">^^</span>Concept;  <span class="co">// represents a concept</span></span>
<span id="cb121-39"><a href="#cb121-39" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r15 <span class="op">=</span> <span class="op">^^</span>NSAlias;  <span class="co">// represents a namespace alias</span></span>
<span id="cb121-40"><a href="#cb121-40" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r16 <span class="op">=</span> <span class="op">^^</span>NS;       <span class="co">// represents a namespace</span></span>
<span id="cb121-41"><a href="#cb121-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-42"><a href="#cb121-42" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r17 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>bases_of<span class="op">(^^</span>S, ctx<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb121-43"><a href="#cb121-43" aria-hidden="true" tabindex="-1"></a>    <span class="co">// represents a direct base class relationship</span></span>
<span id="cb121-44"><a href="#cb121-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb121-45"><a href="#cb121-45" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r18 <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>data_member_spec<span class="op">(^^</span><span class="dt">int</span>, <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;member&quot;</span><span class="op">})</span>;</span>
<span id="cb121-46"><a href="#cb121-46" aria-hidden="true" tabindex="-1"></a>    <span class="co">// represents a data member description</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_109" id="pnum_109">y</a></span>
<em>Recommended practice</em>: Implementations should not represent
other constructs specified in this document, such as partial template
specializations, attributes, placeholder types, statements, or
expressions, as values of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_110" id="pnum_110">z</a></span>
<span class="note"><span>[ <em>Note 2:</em> </span>Future revisions of
this document can specify semantics for reflections representing any
such constructs.<span> — <em>end note</em> ]</span></span></p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_111" id="pnum_111">17</a></span>
The types described in this subclause are called <em>fundamental
types</em>.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="intro.execution-sequential-execution"><span>6.9.1 <a href="https://wg21.link/intro.execution">[intro.execution]</a></span>
Sequential execution<a href="#intro.execution-sequential-execution" class="self-link"></a></h3>
<p>Introduce a new kind of side effect in paragraph 7 (i.e., injecting a
declaration).</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_112" id="pnum_112">7</a></span>
Reading an object designated by a
<code class="sourceCode cpp"><span class="kw">volatile</span></code>
glvalue ([basic.lval]), modifying an object, <span class="addu">producing an injected declaration ([expr.const]),</span>
calling a library I/O function, or calling a function that does any of
those operations are all <em>side effects</em>, which are changes in the
state of the execution <span class="addu">or translation</span>
environment. <em>Evaluation</em> of an expression (or a subexpression)
in general includes both value computations (including determining the
identity of an object for glvalue evaluation and fetching a value
previously assigned to an object for prvalue evaluation) and initiation
of side effects. When a call to a library I/O function returns or an
access through a volatile glvalue is evaluated, the side effect is
considered complete, even though some external actions implied by the
call (such as the I/O itself) or by the
<code class="sourceCode cpp"><span class="kw">volatile</span></code>
access may not have completed yet.</p>
</blockquote>
</div>
<p>Add a new paragraph to the end of [intro.execution] specifying a
stronger sequencing during constant evaluation.</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_113" id="pnum_113">15+</a></span>
During the evaluation of an expression as a core constant expression
([expr.const]), evaluations of operands of individual operators and of
subexpressions of individual expresssions that are otherwise either
unsequenced or indeterminately sequenced are evaluated in lexical
order.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.lval-value-category"><span>7.2.1 <a href="https://wg21.link/basic.lval">[basic.lval]</a></span> Value
category<a href="#basic.lval-value-category" class="self-link"></a></h3>
<p>Apply a drive-by fix to bullet 1.1 clarifying that a glvalue can also
determine the identity of a non-static data member.</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_114" id="pnum_114">(1.1)</a></span>
A <em>glvalue</em> is an expression whose evaluation determines the
identity of an object<span class="addu">,</span> <span class="rm" style="color: #bf0303"><del>or</del></span> function<span class="addu">,
or non-static data member</span>.</li>
</ul>
</blockquote>
</div>
<p>Account for move-eligible
<code class="sourceCode cpp"><em>splice-expression</em></code>s in
bullet 4.1 of Note 3.</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_115" id="pnum_115">(4.1)</a></span>
a move-eligible
<code class="sourceCode cpp"><em>id-expression</em></code>
([expr.prim.id.unqual]) <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice])</span>,</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.context-context-dependence"><span>7.2.3
<a href="https://wg21.link/expr.context">[expr.context]</a></span>
Context dependence<a href="#expr.context-context-dependence" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>reflect-expression</em></code>s
to the list of unevaluated operands in paragraph 1.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_116" id="pnum_116">1</a></span>
In some contexts, <em>unevaluated operands</em> appear ([expr.prim.req],
[expr.typeid], [expr.sizeof], [expr.unary.noexcept], <span class="addu">[expr.reflect],</span> [dcl.type.decltype], [temp.pre],
[temp.concept]). An unevaluated operand is not evaluated.</p>
</blockquote>
</div>
<p>Add <code class="sourceCode cpp"><em>splice-expression</em></code> to
the list of expressions in paragraph 2.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_117" id="pnum_117">2</a></span>
In some contexts, an expression only appears for its side effects. Such
an expression is called a <em>discarded-value expression</em>. The
array-to-pointer and function-to-pointer standard conversions are not
applied. The lvalue-to-rvalue conversion is applied if and only if the
expression is a glvalue of volatile-qualified type and it is one of the
following:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_118" id="pnum_118">(2.1)</a></span>
<code class="sourceCode cpp"><span class="op">(</span> <em>expression</em> <span class="op">)</span></code>,
where <code class="sourceCode cpp"><em>expression</em></code> is one of
these expressions,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_119" id="pnum_119">(2.2)</a></span>
<code class="sourceCode cpp"><em>id-expression</em></code>
([expr.prim.id]),</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_120" id="pnum_120">(2.2+)</a></span>
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice]),</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_121" id="pnum_121">(2.3)</a></span>
[…]</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim-primary-expressions"><span>7.5 <a href="https://wg21.link/expr.prim">[expr.prim]</a></span> Primary
expressions<a href="#expr.prim-primary-expressions" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>splice-expression</em></code> to
the grammar for
<code class="sourceCode cpp"><em>primary-expression</em></code>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb122"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb122-1"><a href="#cb122-1" aria-hidden="true" tabindex="-1"></a>  <em>primary-expression</em>:</span>
<span id="cb122-2"><a href="#cb122-2" aria-hidden="true" tabindex="-1"></a>     <em>literal</em></span>
<span id="cb122-3"><a href="#cb122-3" aria-hidden="true" tabindex="-1"></a>     this</span>
<span id="cb122-4"><a href="#cb122-4" aria-hidden="true" tabindex="-1"></a>     ( <em>expression</em> )</span>
<span id="cb122-5"><a href="#cb122-5" aria-hidden="true" tabindex="-1"></a>     <em>id-expression</em></span>
<span id="cb122-6"><a href="#cb122-6" aria-hidden="true" tabindex="-1"></a>     <em>lambda-expression</em></span>
<span id="cb122-7"><a href="#cb122-7" aria-hidden="true" tabindex="-1"></a>     <em>fold-expression</em></span>
<span id="cb122-8"><a href="#cb122-8" aria-hidden="true" tabindex="-1"></a>     <em>requires-expression</em></span>
<span id="cb122-9"><a href="#cb122-9" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-expression</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.id.general-general"><span>7.5.5.1
<a href="https://wg21.link/expr.prim.id.general">[expr.prim.id.general]</a></span>
General<a href="#expr.prim.id.general-general" class="self-link"></a></h3>
<p>Modify paragraph 2 to avoid transforming non-static members into
implicit member accesses when named as operands to
<code class="sourceCode cpp"><em>reflect-expression</em></code>s.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_122" id="pnum_122">2</a></span>
If an <code class="sourceCode cpp"><em>id-expression</em></code>
<code class="sourceCode cpp"><em>E</em></code> denotes a non-static
non-type member of some class <code class="sourceCode cpp">C</code> at a
point where the current class (<span>7.5.3 <a href="https://wg21.link/expr.prim.this">[expr.prim.this]</a></span>) is
<code class="sourceCode cpp">X</code> and</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_123" id="pnum_123">(2.1)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is potentially evaluated
or <code class="sourceCode cpp">C</code> is
<code class="sourceCode cpp">X</code> or a base class of
<code class="sourceCode cpp">X</code>, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_124" id="pnum_124">(2.2)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is not the
<code class="sourceCode cpp"><em>id-expression</em></code> of a class
member access expression (<span>7.6.1.5 <a href="https://wg21.link/expr.ref">[expr.ref]</a></span>), and</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_125" id="pnum_125">(2.2+)</a></span>
<code class="sourceCode cpp"><em>E</em></code> is not the
<code class="sourceCode cpp"><em>id-expression</em></code> of a
<code class="sourceCode cpp"><em>reflect-expression</em></code>
([expr.reflect]), and</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_126" id="pnum_126">(2.3)</a></span>
if <code class="sourceCode cpp"><em>E</em></code> is a
<code class="sourceCode cpp"><em>qualified-id</em></code>,
<code class="sourceCode cpp"><em>E</em></code> is not the
un-parenthesized operand of the unary
<code class="sourceCode cpp"><span class="op">&amp;</span></code>
operator (<span>7.6.2.2 <a href="https://wg21.link/expr.unary.op">[expr.unary.op]</a></span>),</li>
</ul>
<p>the <code class="sourceCode cpp"><em>id-expression</em></code> is
transformed into a class member access expression using <code class="sourceCode cpp"><span class="op">(*</span><span class="kw">this</span><span class="op">)</span></code>
as the object expression.</p>
</blockquote>
</div>
<p>And extend paragraph 4 to account for splices:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_127" id="pnum_127">4</a></span>
An <code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
that denotes a non-static data member or implicit object member function
of a class can only be used:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_128" id="pnum_128">(4.1)</a></span>
as part of a class member access (after any implicit transformation (see
above)) in which the object expression refers to the member’s class or a
class derived from that class, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_129" id="pnum_129">(4.2)</a></span>
to form a pointer to member ([expr.unary.op]), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_130" id="pnum_130">(4.3)</a></span>
if that <code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code>
designates</span> <span class="rm" style="color: #bf0303"><del>denotes</del></span> a non-static data
member and it appears in an unevaluated operand.</li>
</ul>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div>
<div class="sourceCode" id="cb123"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb123-1"><a href="#cb123-1" aria-hidden="true" tabindex="-1"></a>  struct S {</span>
<span id="cb123-2"><a href="#cb123-2" aria-hidden="true" tabindex="-1"></a>    int m;</span>
<span id="cb123-3"><a href="#cb123-3" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb123-4"><a href="#cb123-4" aria-hidden="true" tabindex="-1"></a>  int i     = sizeof(S::m);       // OK</span>
<span id="cb123-5"><a href="#cb123-5" aria-hidden="true" tabindex="-1"></a>  int j     = sizeof(S::m + 42);  // OK</span>
<span id="cb123-6"><a href="#cb123-6" aria-hidden="true" tabindex="-1"></a><span class="va">+ int S::*k = &amp;[:^^S::m:];        // OK</span></span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.id.unqual-unqualified-names"><span>7.5.5.2 <a href="https://wg21.link/expr.prim.id.unqual">[expr.prim.id.unqual]</a></span>
Unqualified names<a href="#expr.prim.id.unqual-unqualified-names" class="self-link"></a></h3>
<p>Modify paragraph 15 to allow
<code class="sourceCode cpp"><em>splice-expression</em></code>s to be
move-eligible:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_131" id="pnum_131">15</a></span>
An <em>implicitly movable entity</em> is a variable with automatic
storage duration that is either a non-volatile object or an rvalue
reference to a non-volatile object type. An
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice])</span> is <em>move-eligible</em> if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_132" id="pnum_132">(15.1)</a></span>
it <span class="rm" style="color: #bf0303"><del>names</del></span> <span class="addu">designates</span> an implicitly movable entity,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_133" id="pnum_133">(15.2)</a></span>
it is the (possibly parenthesized) operand of a
<code class="sourceCode cpp"><span class="cf">return</span></code>
([stmt.return]) or
<code class="sourceCode cpp"><span class="kw">co_return</span></code>
([stmt.return.coroutine]) statement or of a
<code class="sourceCode cpp"><em>throw-expression</em></code>
([expr.throw]), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_134" id="pnum_134">(15.3)</a></span>
each intervening scope between the declaration of the entity and the
innermost enclosing scope of the <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>id-expression</em></code></span></del></span>
<span class="addu">expression</span> is a block scope and, for a
<code class="sourceCode cpp"><em>throw-expression</em></code>, is not
the block scope of a
<code class="sourceCode cpp"><em>try-block</em></code> or
<code class="sourceCode cpp"><em>function-try-block</em></code>.</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.id.qual-qualified-names"><span>7.5.5.3 <a href="https://wg21.link/expr.prim.id.qual">[expr.prim.id.qual]</a></span>
Qualified names<a href="#expr.prim.id.qual-qualified-names" class="self-link"></a></h3>
<p>Extend the grammar for
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> as
follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb124"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb124-1"><a href="#cb124-1" aria-hidden="true" tabindex="-1"></a>  <em>nested-name-specifier</em>:</span>
<span id="cb124-2"><a href="#cb124-2" aria-hidden="true" tabindex="-1"></a>      ::</span>
<span id="cb124-3"><a href="#cb124-3" aria-hidden="true" tabindex="-1"></a>      <em>type-name</em> ::</span>
<span id="cb124-4"><a href="#cb124-4" aria-hidden="true" tabindex="-1"></a>      <em>namespace-name</em> ::</span>
<span id="cb124-5"><a href="#cb124-5" aria-hidden="true" tabindex="-1"></a>      <em>computed-type-specifier</em> ::</span>
<span id="cb124-6"><a href="#cb124-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-scope-specifier</em> ::</span></span>
<span id="cb124-7"><a href="#cb124-7" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em> <em>identifier</em> ::</span>
<span id="cb124-8"><a href="#cb124-8" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em> template<sub><em>opt</em></sub> <em>simple-template-id</em> ::</span>
<span id="cb124-9"><a href="#cb124-9" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb124-10"><a href="#cb124-10" aria-hidden="true" tabindex="-1"></a><span class="va">+  <em>splice-scope-specifier</em>:</span></span>
<span id="cb124-11"><a href="#cb124-11" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-specifier</em></span></span>
<span id="cb124-12"><a href="#cb124-12" aria-hidden="true" tabindex="-1"></a><span class="va">+     template<sub><em>opt</em></sub> <em>splice-specialization-specifier</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add a paragraph after paragraph 1 specifying the rules for parsing a
<code class="sourceCode cpp"><em>splice-scope-specifier</em></code>, as
well as an example:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_135" id="pnum_135">1+</a></span>
A <code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
that is not followed by
<code class="sourceCode cpp"><span class="op">::</span></code> is never
interpreted as part of a
<code class="sourceCode cpp"><em>splice-scope-specifier</em></code>. The
<code class="sourceCode cpp"><span class="kw">template</span></code> may
only be omitted from the form <code class="sourceCode cpp">template<sub><em>opt</em></sub> <em>splice-specialization-specifier</em> <span class="op">::</span></code>
when the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is preceded by
<code class="sourceCode cpp"><span class="kw">typename</span></code>.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb125"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb125-1"><a href="#cb125-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span> V<span class="op">&gt;</span></span>
<span id="cb125-2"><a href="#cb125-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb125-3"><a href="#cb125-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> s <span class="op">=</span> V;</span>
<span id="cb125-4"><a href="#cb125-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb125-5"><a href="#cb125-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb125-6"><a href="#cb125-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb125-7"><a href="#cb125-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> v1 <span class="op">=</span> <span class="op">[:^^</span>TCls<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;:]::</span>s;</span>
<span id="cb125-8"><a href="#cb125-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> v2 <span class="op">=</span> <span class="kw">template</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;</span><span class="dv">2</span><span class="op">&gt;::</span>s;</span>
<span id="cb125-9"><a href="#cb125-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, template binds to splice-scope-specifier</span></span>
<span id="cb125-10"><a href="#cb125-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb125-11"><a href="#cb125-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">typename</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;</span><span class="dv">3</span><span class="op">&gt;::</span>type v3 <span class="op">=</span> <span class="dv">3</span>;</span>
<span id="cb125-12"><a href="#cb125-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, typename binds to the qualified name</span></span>
<span id="cb125-13"><a href="#cb125-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb125-14"><a href="#cb125-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;</span><span class="dv">3</span><span class="op">&gt;::</span>type v4 <span class="op">=</span> <span class="dv">4</span>;</span>
<span id="cb125-15"><a href="#cb125-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, template binds to the splice-scope-specifier</span></span>
<span id="cb125-16"><a href="#cb125-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb125-17"><a href="#cb125-17" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb125-18"><a href="#cb125-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;</span><span class="dv">3</span><span class="op">&gt;::</span>type v5 <span class="op">=</span> <span class="dv">5</span>;</span>
<span id="cb125-19"><a href="#cb125-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// error: &lt; means less than</span></span>
<span id="cb125-20"><a href="#cb125-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<p>Clarify in paragraph 2 that a splice cannot appear in a declarative
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_136" id="pnum_136">2</a></span>
A <code class="sourceCode cpp"><em>nested-name-specifier</em></code> is
<em>declarative</em> if it is part of</p>
<ul>
<li>a <code class="sourceCode cpp"><em>class-head-name</em></code>,</li>
<li>an <code class="sourceCode cpp"><em>enum-head-name</em></code>,</li>
<li>a <code class="sourceCode cpp"><em>qualified-id</em></code> that is
the <code class="sourceCode cpp"><em>id-expression</em></code> of a
<code class="sourceCode cpp"><em>declarator-id</em></code>, or</li>
<li>a declarative
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>.</li>
</ul>
<p>A declarative
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> shall
not have a
<code class="sourceCode cpp"><em>computed-type-specifier</em></code>
<span class="addu">or a
<code class="sourceCode cpp"><em>splice-scope-specifier</em></code></span>.
A declaration that uses a declarative
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> shall
be a friend declaration or inhabit a scope that contains the entity
being redeclared or specialized.</p>
</blockquote>
</div>
<p>Break the next paragraph into a bulleted list, extend it to also
cover splices, and prefer the verb “designate” over “nominate”:</p>
<p><span class="draftnote" style="color: #01796F">[ Drafting note: Here
and in a few other places, the wording for the entity represented by a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is complicated. This is primarily because the possibility that such a
construct might form a
<code class="sourceCode cpp"><em>concept-id</em></code> (which is a
prvalue) precludes us from generically saying that a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
designates an entity. ]</span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_137" id="pnum_137">3</a></span>
<span class="addu">The entity designated by a
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> is
determined as follows:</span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_138" id="pnum_138">(3.1)</a></span>
The <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
<code class="sourceCode cpp"><span class="op">::</span></code> <span class="rm" style="color: #bf0303"><del>nominates</del></span> <span class="addu">designates</span> the global namespace.<span class="addu"> </span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_139" id="pnum_139">(3.2)</a></span>
A <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
with a
<code class="sourceCode cpp"><em>computed-type-specifier</em></code>
<span class="rm" style="color: #bf0303"><del>nominates</del></span>
<span class="addu">designates</span> the <span class="addu">same</span>
type <span class="rm" style="color: #bf0303"><del>denoted</del></span>
<span class="addu">designated</span> by the
<code class="sourceCode cpp"><em>computed-type-specifier</em></code>,
which shall be a class or enumeration type.<span class="addu"> </span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_140" id="pnum_140">(3.3)</a></span>
For a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
of the form <code class="sourceCode cpp"><em>splice-specifier</em> <span class="op">::</span></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> shall
designate a class or enumeration type or a namespace. The
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>
designates the same entity as the
<code class="sourceCode cpp"><em>splice-specifier</em></code>.</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_141" id="pnum_141">(3.4)</a></span>
For a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
of the form <code class="sourceCode cpp">template<sub><em>opt</em></sub> <em>splice-specialization-specifier</em> <span class="op">::</span></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
shall designate a primary class template or an alias template
<code class="sourceCode cpp"><em>T</em></code>. Letting
<code class="sourceCode cpp"><em>S</em></code> be the specialization of
<code class="sourceCode cpp"><em>T</em></code> corresponding to the
<code class="sourceCode cpp"><em>template-argument-list</em></code> (if
any) of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>,
<code class="sourceCode cpp"><em>S</em></code> shall either be a class
template specialization or an alias template specialization that denotes
a class or enumeration type. The
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>
designates <code class="sourceCode cpp"><em>S</em></code> if
<code class="sourceCode cpp"><em>T</em></code> is a class template or
the type denoted by <code class="sourceCode cpp"><em>S</em></code> if
<code class="sourceCode cpp"><em>T</em></code> is an alias
template.</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_142" id="pnum_142">(3.5)</a></span>
If a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
<em>N</em> is declarative and has a
<code class="sourceCode cpp"><em>simple-template-id</em></code> with a
template argument list <em>A</em> that involves a template parameter,
let <em>T</em> be the template <span class="rm" style="color: #bf0303"><del>nominated</del></span> <span class="addu">designated</span> by <em>N</em> without <em>A</em>.
<em>T</em> shall be a class template.
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_143" id="pnum_143">(3.5.1)</a></span>
If <code class="sourceCode cpp"><em>A</em></code> is the template
argument list (<span>13.4 <a href="https://wg21.link/temp.arg">[temp.arg]</a></span>) of the
corresponding <code class="sourceCode cpp"><em>template-head</em></code>
<code class="sourceCode cpp"><em>H</em></code> (<span>13.7.3 <a href="https://wg21.link/temp.mem">[temp.mem]</a></span>),
<code class="sourceCode cpp"><em>N</em></code> <span class="rm" style="color: #bf0303"><del>nominates</del></span> <span class="addu">designates</span> the primary template of
<code class="sourceCode cpp"><em>T</em></code>;
<code class="sourceCode cpp"><em>H</em></code> shall be equivalent to
the <code class="sourceCode cpp"><em>template-head</em></code> of
<code class="sourceCode cpp"><em>T</em></code> (<span>13.7.7.2 <a href="https://wg21.link/temp.over.link">[temp.over.link]</a></span>).</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_144" id="pnum_144">(3.5.2)</a></span>
Otherwise, <code class="sourceCode cpp"><em>N</em></code> <span class="rm" style="color: #bf0303"><del>nominates</del></span> <span class="addu">designates</span> the partial specialization (<span>13.7.6
<a href="https://wg21.link/temp.spec.partial">[temp.spec.partial]</a></span>)
of <code class="sourceCode cpp"><em>T</em></code> whose template
argument list is equivalent to
<code class="sourceCode cpp"><em>A</em></code> (<span>13.7.7.2 <a href="https://wg21.link/temp.over.link">[temp.over.link]</a></span>);
the program is ill-formed if no such partial specialization exists.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_145" id="pnum_145">(3.6)</a></span>
Any other
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> <span class="rm" style="color: #bf0303"><del>nominates</del></span> <span class="addu">designates</span> the entity <span class="rm" style="color: #bf0303"><del>denoted</del></span> <span class="addu">designated</span> by its
<code class="sourceCode cpp"><em>type-name</em></code>,
<code class="sourceCode cpp"><em>namespace-name</em></code>,
<code class="sourceCode cpp"><em>identifier</em></code>, or
<code class="sourceCode cpp"><em>simple-template-id</em></code>. If the
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> is
not declarative, the entity shall not be a template.</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.lambda.closure-closure-types"><span>7.5.6.2 <a href="https://wg21.link/expr.prim.lambda.closure">[expr.prim.lambda.closure]</a></span>
Closure types<a href="#expr.prim.lambda.closure-closure-types" class="self-link"></a></h3>
<p>We have to say that a closure type is not complete until the
<code class="sourceCode cpp"><span class="op">}</span></code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_146" id="pnum_146">1</a></span>
The type of a lambda-expression (which is also the type of the closure
object) is a unique, unnamed non-union class type, called the closure
type, whose properties are described below.</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_147" id="pnum_147">x</a></span>
The closure type is not complete until the end of its corresponding
<code class="sourceCode cpp"><em>compound-statement</em></code>.</p>
</div>
</blockquote>
</div>
<p>And say that the call operator is a direct member:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_148" id="pnum_148">4</a></span>
The closure type for a <em>lambda-expression</em> has a public inline
function call operator (for a non-generic lambda) or function call
operator template (for a generic lambda) ([over.call]) whose parameters
and return type are those of the lambda-expression’s
parameter-declaration-clause and trailing-return-type respectively, and
whose template-parameter-list consists of the specified
template-parameter-list, if any. <span class="addu">The function call
operator or the function call operator template are direct members of
the closure type.</span> The <em>requires-clause</em> of the function
call operator template […]</p>
</blockquote>
</div>
<p>And that the conversion function is:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_149" id="pnum_149">10</a></span>
The closure type for a non-generic lambda-expression with no
lambda-capture and no explicit object parameter ([dcl.fct]) whose
constraints (if any) are satisfied has a conversion function to pointer
to function with C++ language linkage having the same parameter and
return types as the closure type’s function call operator. <span class="addu">The conversion function is a direct member of the closure
type.</span> The conversion is to “pointer to noexcept function” if the
function call operator has a non-throwing exception specification.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_150" id="pnum_150">11</a></span>
For a generic lambda with no lambda-capture and no explicit object
parameter ([dcl.fct]), the closure type has a conversion function
template to pointer to function. <span class="addu">The conversion
function template is a direct member of the closure type.</span> The
conversion function template has the same invented template parameter
list, […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.req.type-type-requirements"><span>7.5.8.3 <a href="https://wg21.link/expr.prim.req.type">[expr.prim.req.type]</a></span>
Type requirements<a href="#expr.prim.req.type-type-requirements" class="self-link"></a></h3>
<p>Allow splices in type requirements:</p>
<div class="std">
<blockquote>
<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>type-requirement</em>:</span>
<span id="cb126-2"><a href="#cb126-2" aria-hidden="true" tabindex="-1"></a>    typename <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>type-name</em> ;</span>
<span id="cb126-3"><a href="#cb126-3" aria-hidden="true" tabindex="-1"></a><span class="va">+   typename <em>splice-specifier</em></span></span>
<span id="cb126-4"><a href="#cb126-4" aria-hidden="true" tabindex="-1"></a><span class="va">+   typename <em>splice-specialization-specifier</em></span></span></code></pre></div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_151" id="pnum_151">1</a></span>
A <code class="sourceCode cpp"><em>type-requirement</em></code> asserts
the validity of a type. The component names <span class="addu">(if
any)</span> of a
<code class="sourceCode cpp"><em>type-requirement</em></code> are those
of its
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> <span class="rm" style="color: #bf0303"><del>(if any)</del></span> and
<code class="sourceCode cpp"><em>type-name</em></code>.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div>
<div class="sourceCode" id="cb127"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb127-1"><a href="#cb127-1" aria-hidden="true" tabindex="-1"></a>template&lt;typename  T, typename T::type = 0&gt; struct S;</span>
<span id="cb127-2"><a href="#cb127-2" aria-hidden="true" tabindex="-1"></a>template&lt;typename T&gt; using Ref = T&amp;;</span>
<span id="cb127-3"><a href="#cb127-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb127-4"><a href="#cb127-4" aria-hidden="true" tabindex="-1"></a>template&lt;typename T&gt; concept C = requires {</span>
<span id="cb127-5"><a href="#cb127-5" aria-hidden="true" tabindex="-1"></a>  typename T::inner;        // required nested member name</span>
<span id="cb127-6"><a href="#cb127-6" aria-hidden="true" tabindex="-1"></a>  typename S&lt;T&gt;;            // required valid ([temp.names]) template-id;</span>
<span id="cb127-7"><a href="#cb127-7" aria-hidden="true" tabindex="-1"></a>                            // fails if T::type does not exist as a type to which 0 can be implicitly converted</span>
<span id="cb127-8"><a href="#cb127-8" aria-hidden="true" tabindex="-1"></a>  typename Ref&lt;T&gt;;          // required alias template substitution, fails if T is void</span>
<span id="cb127-9"><a href="#cb127-9" aria-hidden="true" tabindex="-1"></a><span class="va">+ typename [:T::r1:];       // fails if T::r1 is not a reflection of a type</span></span>
<span id="cb127-10"><a href="#cb127-10" aria-hidden="true" tabindex="-1"></a><span class="va">+ typename [:T::r2:]&lt;int&gt;;  // fails if T::r2 is not a reflection of a template T for</span></span>
<span id="cb127-11"><a href="#cb127-11" aria-hidden="true" tabindex="-1"></a><span class="va">+                           // which T&lt;int&gt; is a type</span></span>
<span id="cb127-12"><a href="#cb127-12" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.splice-expression-splicing">7.5.8*
[expr.prim.splice] Expression splicing<a href="#expr.prim.splice-expression-splicing" class="self-link"></a></h3>
<p>Add a new subsection of <span>7.5 <a href="https://wg21.link/expr.prim">[expr.prim]</a></span> following
<span>7.5.8 <a href="https://wg21.link/expr.prim.req">[expr.prim.req]</a></span></p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Expression Splicing [expr.prim.splice]</strong></p>
<div class="sourceCode" id="cb128"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb128-1"><a href="#cb128-1" aria-hidden="true" tabindex="-1"></a><em>splice-expression</em>:</span>
<span id="cb128-2"><a href="#cb128-2" aria-hidden="true" tabindex="-1"></a>   <em>splice-specifier</em></span>
<span id="cb128-3"><a href="#cb128-3" aria-hidden="true" tabindex="-1"></a>   template <em>splice-specifier</em></span>
<span id="cb128-4"><a href="#cb128-4" aria-hidden="true" tabindex="-1"></a>   template <em>splice-specialization-specifier</em></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_152" id="pnum_152">1</a></span>
A <code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
immediately followed by
<code class="sourceCode cpp"><span class="op">::</span></code> or
preceded by
<code class="sourceCode cpp"><span class="kw">typename</span></code> is
never interpreted as part of a
<code class="sourceCode cpp"><em>splice-expression</em></code>.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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="kw">struct</span> S <span class="op">{</span> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> a <span class="op">=</span> <span class="dv">1</span>; <span class="op">}</span>;</span>
<span id="cb129-2"><a href="#cb129-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 class="kw">struct</span> TCls <span class="op">{</span> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> b <span class="op">=</span> <span class="dv">2</span>; <span class="op">}</span>;</span>
<span id="cb129-3"><a href="#cb129-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-4"><a href="#cb129-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> c <span class="op">=</span> <span class="op">[:^^</span>S<span class="op">:]::</span>a;                   <span class="co">// [:^^S:] is not an expression</span></span>
<span id="cb129-5"><a href="#cb129-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-6"><a href="#cb129-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> d <span class="op">=</span> <span class="kw">template</span> <span class="op">[:^^</span>TCls<span class="op">:]&lt;</span><span class="dt">int</span><span class="op">&gt;::</span>b;  <span class="co">// template [:^^TCls:]&lt;int&gt; is not</span></span>
<span id="cb129-7"><a href="#cb129-7" aria-hidden="true" tabindex="-1"></a>                                                <span class="co">// an expression</span></span>
<span id="cb129-8"><a href="#cb129-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-9"><a href="#cb129-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="dt">int</span> e <span class="op">=</span> <span class="op">[:</span>V<span class="op">:]</span>;   <span class="co">// splice-expression</span></span>
<span id="cb129-10"><a href="#cb129-10" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> f <span class="op">=</span> <span class="kw">template</span> <span class="op">[:^^</span>e<span class="op">:]&lt;^^</span>S<span class="op">::</span>a<span class="op">&gt;</span>;  <span class="co">// splice-expression</span></span>
<span id="cb129-11"><a href="#cb129-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-12"><a href="#cb129-12" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> g <span class="op">=</span> <span class="kw">typename</span> <span class="op">[:^^</span><span class="dt">int</span><span class="op">:](</span><span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb129-13"><a href="#cb129-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [:^^int:] forms part of a type, not a splice-expression</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_153" id="pnum_153">2</a></span>
For a <code class="sourceCode cpp"><em>splice-expression</em></code> of
the form <code class="sourceCode cpp"><em>splice-specifier</em></code>,
let <code class="sourceCode cpp"><em>S</em></code> be the construct
designated by
<code class="sourceCode cpp"><em>splice-specifier</em></code>.</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_154" id="pnum_154">(2.1)</a></span>
The expression is ill-formed if
<code class="sourceCode cpp"><em>S</em></code> is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_155" id="pnum_155">(2.1.1)</a></span>
a constructor,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_156" id="pnum_156">(2.1.2)</a></span>
a destructor,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_157" id="pnum_157">(2.1.3)</a></span>
an unnamed bit-field, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_158" id="pnum_158">(2.1.4)</a></span>
a local entity ([basic.pre]) such that
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_159" id="pnum_159">(2.1.4.1)</a></span>
there is a lambda scope that intervenes between the expression and the
point at which <code class="sourceCode cpp"><em>S</em></code> was
introduced and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_160" id="pnum_160">(2.1.4.2)</a></span>
the expression would be potentially evaluated if the effect of any
enclosing
<code class="sourceCode cpp"><span class="kw">typeid</span></code>
expressions ([expr.typeid]) were ignored.</li>
</ul></li>
</ul></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_161" id="pnum_161">(2.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is a
function <code class="sourceCode cpp"><em>F</em></code>, the expression
denotes an overload set containing all declarations of
<code class="sourceCode cpp"><em>F</em></code> that precede either the
expression or the point immediately following the
<code class="sourceCode cpp"><em>class-specifier</em></code> of the
outermost class for which the expression is in a complete-class context;
overload resolution is performed to select a unique function
([over.match], [over.over]).</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_162" id="pnum_162">(2.3)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is an
object or a non-static data member, the expression is an lvalue
designating <code class="sourceCode cpp"><em>S</em></code>. The
expression has the same type as
<code class="sourceCode cpp"><em>S</em></code>, and is a bit-field if
and only if <code class="sourceCode cpp"><em>S</em></code> is a
bit-field. <span class="note"><span>[ <em>Note 1:</em> </span>The
implicit transformation (<span>7.5.5 <a href="https://wg21.link/expr.prim.id">[expr.prim.id]</a></span>) whereby
an <code class="sourceCode cpp"><em>id-expression</em></code> denoting a
non-static member becomes a class member access does not apply to a
<code class="sourceCode cpp"><em>splice-expression</em></code>.<span>
— <em>end note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_163" id="pnum_163">(2.4)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is a
variable or a structured binding,
<code class="sourceCode cpp"><em>S</em></code> shall either have static
or thread storage duration or shall inhabit a scope enclosing the
expression. The expression is an lvalue referring to the object or
function <code class="sourceCode cpp"><em>X</em></code> associated with
or referenced by <code class="sourceCode cpp"><em>S</em></code>, has the
same type as <code class="sourceCode cpp"><em>S</em></code>, and is a
bit-field if and only if <code class="sourceCode cpp"><em>X</em></code>
is a bit-field.</p>
<p><span class="note"><span>[ <em>Note 2:</em> </span>The type of a
<code class="sourceCode cpp"><em>splice-expression</em></code>
designating a variable or structured binding of reference type will be
adjusted to a non-reference type (<span>7.2.2 <a href="https://wg21.link/expr.type">[expr.type]</a></span>).<span>
— <em>end note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_164" id="pnum_164">(2.5)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is a value
or an enumerator, the expression is a prvalue that computes
<code class="sourceCode cpp"><em>S</em></code> and whose type is the
same as <code class="sourceCode cpp"><em>S</em></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_165" id="pnum_165">(2.6)</a></span>
Otherwise, the expression is ill-formed.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_166" id="pnum_166">3</a></span>
For a <code class="sourceCode cpp"><em>splice-expression</em></code> of
the form <code class="sourceCode cpp"><span class="kw">template</span> <em>splice-specifier</em></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> shall
designate a function template
<code class="sourceCode cpp"><em>T</em></code> that is not a constructor
template. The expression denotes an overload set containing all
declarations of <code class="sourceCode cpp"><em>T</em></code> that
precede either the expression or the point immediately following the
<code class="sourceCode cpp"><em>class-specifier</em></code> of the
outermost class for which the expression is in a complete-class context;
overload resolution is performed to select a unique function. <span class="note"><span>[ <em>Note 3:</em> </span>During overload resolution,
candidate function templates undergo template argument deduction and the
resulting specializations are considered as candidate functions.<span>
— <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_167" id="pnum_167">4</a></span>
For a <code class="sourceCode cpp"><em>splice-expression</em></code> of
the form <code class="sourceCode cpp"><span class="kw">template</span> <em>splice-specialization-specifier</em></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
shall designate a template
<code class="sourceCode cpp"><em>T</em></code>.</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_168" id="pnum_168">(4.1)</a></span>
If <code class="sourceCode cpp"><em>T</em></code> is a function
template, the expression denotes an overload set containing all
declarations of <code class="sourceCode cpp"><em>T</em></code> that
precede either the expression or the point immediately following the
<code class="sourceCode cpp"><em>class-specifier</em></code> of the
outermost class for which the expression is in a complete-class context;
overload resolution is performed to select a unique function
([over.match], [over.over]).</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_169" id="pnum_169">(4.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>T</em></code> is a
primary variable template, let
<code class="sourceCode cpp"><em>S</em></code> be the specialiation of
<code class="sourceCode cpp"><em>T</em></code> corresponding to the
<code class="sourceCode cpp"><em>template-argument-list</em></code> (if
any) of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>.
The expression is an lvalue referring to the same object associated with
<code class="sourceCode cpp"><em>S</em></code> and has the same type as
<code class="sourceCode cpp"><em>S</em></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_170" id="pnum_170">(4.3)</a></span>
Otherwise, the expression is ill-formed.</p></li>
</ul>
<p><span class="note"><span>[ <em>Note 4:</em> </span>Class members
designated by
<code class="sourceCode cpp"><em>splice-expression</em></code>s are
accessible from any point ([class.access.base]). A class member access
expression whose right operand is a
<code class="sourceCode cpp"><em>splice-expression</em></code> is
ill-formed if the left operand (considered as a pointer) cannot be
implicitly converted to a pointer to the designating class of the right
operand.<span> — <em>end note</em> ]</span></span></p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.post.general-general"><span>7.6.1.1 <a href="https://wg21.link/expr.post.general">[expr.post.general]</a></span>
General<a href="#expr.post.general-general" class="self-link"></a></h3>
<p>Add a production to
<code class="sourceCode cpp"><em>postfix-expression</em></code> for
splices in member access expressions:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb130"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb130-1"><a href="#cb130-1" aria-hidden="true" tabindex="-1"></a>[1]{.pnum} Postfix expressions group left-to-right.</span>
<span id="cb130-2"><a href="#cb130-2" aria-hidden="true" tabindex="-1"></a>  <em>postfix-expression</em>:</span>
<span id="cb130-3"><a href="#cb130-3" aria-hidden="true" tabindex="-1"></a>    ...</span>
<span id="cb130-4"><a href="#cb130-4" aria-hidden="true" tabindex="-1"></a>    <em>postfix-expression</em> . <em>template</em><sub><em>opt</em></sub> <em>id-expression</em></span>
<span id="cb130-5"><a href="#cb130-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>postfix-expression</em> . <em>splice-expression</em></span></span>
<span id="cb130-6"><a href="#cb130-6" aria-hidden="true" tabindex="-1"></a>    <em>postfix-expression</em> -&gt; <em>template</em><sub><em>opt</em></sub> <em>id-expression</em></span>
<span id="cb130-7"><a href="#cb130-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>postfix-expression</em> -&gt; <em>splice-expression</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.ref-class-member-access"><span>7.6.1.5
<a href="https://wg21.link/expr.ref">[expr.ref]</a></span> Class member
access<a href="#expr.ref-class-member-access" class="self-link"></a></h3>
<p>Modify paragraph 1 to account for splices in member access
expressions:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_171" id="pnum_171">1</a></span>
A postfix expression followed by a dot
<code class="sourceCode cpp"><span class="op">.</span></code> or an
arrow <code class="sourceCode cpp"><span class="op">-&gt;</span></code>,
optionally followed by the keyword
<code class="sourceCode cpp"><span class="kw">template</span></code>,
and then followed by an
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or a
<code class="sourceCode cpp"><em>splice-expression</em></code></span>,
is a postfix expression.</p>
<p><span class="note"><span>[ <em>Note 1:</em> </span>If the keyword
<code class="sourceCode cpp"><span class="kw">template</span></code> is
used, the following unqualified name is considered to refer to a
template ([temp.names]). If a
<code class="sourceCode cpp"><em>simple-template-id</em></code> results
and is followed by a
<code class="sourceCode cpp"><span class="op">::</span></code>, the
<code class="sourceCode cpp"><em>id-expression</em></code> is a
<code class="sourceCode cpp"><em>qualified-id</em></code>.<span>
— <em>end note</em> ]</span></span></p>
</blockquote>
</div>
<p>Modify paragraph 2 to account for splices in member access
expressions:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_172" id="pnum_172">2</a></span>
For <span class="rm" style="color: #bf0303"><del>the first option (dot),
if the</del></span> <span class="addu">a dot that is followed by
an</span> <code class="sourceCode cpp"><em>id-expression</em></code>
<span class="rm" style="color: #bf0303"><del>names</del></span> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code> that
designates</span> a static member or an enumerator, the first expression
is a discarded-value expression ([expr.context]); if the
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code>
designates</span> <span class="rm" style="color: #bf0303"><del>names</del></span> a non-static data member,
the first expression shall be a glvalue. <span class="rm" style="color: #bf0303"><del>For the second option (arrow), the first
expression</del></span> <span class="addu">A postfix expression that is
followed by an arrow</span> shall be a prvalue having pointer type. The
expression
<code class="sourceCode cpp">E1<span class="op">-&gt;</span>E2</code> is
converted to the equivalent form <code class="sourceCode cpp"><span class="op">(*(</span>E1<span class="op">)).</span>E2</code>;
the remainder of [expr.ref] will address only <span class="rm" style="color: #bf0303"><del>the first option (dot)</del></span> <span class="addu">the form using a dot</span><sup>49</sup>.</p>
</blockquote>
</div>
<p>Modify paragraph 3 to account for splices in member access
expressions:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_173" id="pnum_173">3</a></span>
The postfix expression before the dot is evaluated;<sup>50</sup> the
result of that evaluation, together with the
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>,
determines the result of the entire postfix expression.</p>
</blockquote>
</div>
<p>Modify paragraph 4 to account for splices in member access
expressions:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_174" id="pnum_174">4</a></span>
Abbreviating
<code class="sourceCode cpp"><em>postfix-expression</em></code>.<code class="sourceCode cpp"><em>id-expression</em></code>
<span class="addu">or <code class="sourceCode cpp"><em>postfix-expression</em><span class="op">.</span><em>splice-expression</em></code></span>
as <code class="sourceCode cpp">E1<span class="op">.</span>E2</code>,
<code class="sourceCode cpp">E1</code> is called the
<code class="sourceCode cpp"><em>object expression</em></code>. […]</p>
</blockquote>
</div>
<p>Adjust the language in paragraphs 6-9 to account for
<code class="sourceCode cpp"><em>splice-expression</em></code>s.
Explicitly add a fallback to paragraph 7 that makes other cases
ill-formed. Update the term “naming class” to “designated class” in
paragraph 8.</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_175" id="pnum_175">*</a></span>
If <code class="sourceCode cpp">E2</code> is a
<code class="sourceCode cpp"><em>splice-expression</em></code>, then
<code class="sourceCode cpp">E2</code> shall designate a member of the
type of <code class="sourceCode cpp">E1</code>.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_176" id="pnum_176">6</a></span>
If <code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a bit-field,
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is a
bit-field. […]</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_177" id="pnum_177">7</a></span>
If <code class="sourceCode cpp">E2</code> <span class="addu">designates
an entity that</span> is declared to have type “reference to
<code class="sourceCode cpp">T</code>”, then
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is an
lvalue of type <code class="sourceCode cpp">T</code>. <span class="rm" style="color: #bf0303"><del>If</del></span> <span class="addu">In that
case, if</span> <code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a static data member,
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code>
designates the object or function to which the reference is bound,
otherwise
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code>
designates the object or function to which the corresponding reference
member of <code class="sourceCode cpp">E1</code> is bound. Otherwise,
one of the following rules applies.</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_178" id="pnum_178">(7.1)</a></span>
If <code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a static data member and the type of
<code class="sourceCode cpp">E2</code> is
<code class="sourceCode cpp">T</code>, then
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is an
lvalue; […]</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_179" id="pnum_179">(7.2)</a></span>
<span class="addu">Otherwise, if</span> <span class="rm" style="color: #bf0303"><del>If</del></span>
<code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a non-static data member and the type of
<code class="sourceCode cpp">E1</code> is “<em>cq1</em> <em>vq1</em>
<code class="sourceCode cpp">X</code>”, and the type of
<code class="sourceCode cpp">E2</code> is “<em>cq2 vq2</em>
<code class="sourceCode cpp">T</code>”, […]. If <span class="addu">the
entity designated by</span> <code class="sourceCode cpp">E2</code> is
declared to be a
<code class="sourceCode cpp"><span class="kw">mutable</span></code>
member, then the type of
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is
“<em>vq12</em> <code class="sourceCode cpp">T</code>”. If <span class="addu">the entity designated by</span>
<code class="sourceCode cpp">E2</code> is not declared to be a
<code class="sourceCode cpp"><span class="kw">mutable</span></code>
member, then the type of
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is
“<em>cq12</em> <em>vq12</em>
<code class="sourceCode cpp">T</code>”.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_180" id="pnum_180">(7.3)</a></span>
<span class="addu">Otherwise, if</span> <span class="rm" style="color: #bf0303"><del>If</del></span>
<code class="sourceCode cpp">E2</code> is an overload set, […]</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_181" id="pnum_181">(7.4)</a></span>
<span class="addu">Otherwise, if</span> <span class="rm" style="color: #bf0303"><del>If</del></span>
<code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a nested type, the expression
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is
ill-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_182" id="pnum_182">(7.5)</a></span>
<span class="addu">Otherwise, if</span> <span class="rm" style="color: #bf0303"><del>If</del></span>
<code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a member enumerator and the type of
<code class="sourceCode cpp">E2</code> is
<code class="sourceCode cpp">T</code>, the expression
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is a
prvalue of type <code class="sourceCode cpp">T</code> whose value is the
value of the enumerator.</p></li>
<li><p><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_183" id="pnum_183">(7.6)</a></span>
Otherwise, the program is ill-formed.</span></p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_184" id="pnum_184">8</a></span>
If <code class="sourceCode cpp">E2</code> <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">designates</span> a non-static member, the program is
ill-formed if the class of which <code class="sourceCode cpp">E2</code>
<span class="rm" style="color: #bf0303"><del>is directly</del></span>
<span class="addu">designates</span> a <span class="addu">direct</span>
member is an ambiguous base (<span>6.5.2 <a href="https://wg21.link/class.member.lookup">[class.member.lookup]</a></span>)
of the <span class="rm" style="color: #bf0303"><del>naming</del></span>
<span class="addu">designating</span> class (<span>11.8.3 <a href="https://wg21.link/class.access.base">[class.access.base]</a></span>)
of <code class="sourceCode cpp">E2</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_185" id="pnum_185">9</a></span>
If <span class="addu">the entity designated by</span>
<code class="sourceCode cpp">E2</code> is a non-static member and the
result of <code class="sourceCode cpp">E1</code> is an object whose type
is not similar ([conv.qual]) to the type of
<code class="sourceCode cpp">E1</code>, the behavior is undefined.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.unary.general-general"><span>7.6.2.1 <a href="https://wg21.link/expr.unary.general">[expr.unary.general]</a></span>
General<a href="#expr.unary.general-general" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>reflect-expression</em></code>
to the grammar for
<code class="sourceCode cpp"><em>unary-expression</em></code> in
paragraph 1:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_186" id="pnum_186">1</a></span>
Expressions with unary operators group right-to-left.</p>
<div>
<div class="sourceCode" id="cb131"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb131-1"><a href="#cb131-1" aria-hidden="true" tabindex="-1"></a>  <em>unary-expression</em>:</span>
<span id="cb131-2"><a href="#cb131-2" aria-hidden="true" tabindex="-1"></a>     ...</span>
<span id="cb131-3"><a href="#cb131-3" aria-hidden="true" tabindex="-1"></a>     <em>delete-expression</em></span>
<span id="cb131-4"><a href="#cb131-4" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>reflect-expression</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.unary.op-unary-operators"><span>7.6.2.2
<a href="https://wg21.link/expr.unary.op">[expr.unary.op]</a></span>
Unary operators<a href="#expr.unary.op-unary-operators" class="self-link"></a></h3>
<p>Modify paragraphs 3 and 4 to permit forming a pointer-to-member with
a splice.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_187" id="pnum_187">3</a></span>
The operand of the unary
<code class="sourceCode cpp"><span class="op">&amp;</span></code>
operator shall be an lvalue of some type
<code class="sourceCode cpp">T</code>.</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_188" id="pnum_188">(3.1)</a></span>
If the operand is a
<code class="sourceCode cpp"><em>qualified-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
<span class="rm" style="color: #bf0303"><del>naming</del></span> <span class="addu">designating</span> a non-static or variant member of some
class <code class="sourceCode cpp">C</code>, other than an explicit
object member function, the result has type “pointer to member of class
<code class="sourceCode cpp">C</code> of type
<code class="sourceCode cpp">T</code>” and designates
<code class="sourceCode cpp">C<span class="op">::</span>m</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_189" id="pnum_189">(3.2)</a></span>
Otherwise, the result has type “pointer to
<code class="sourceCode cpp">T</code>” and points to the designated
object (<span>6.7.1 <a href="https://wg21.link/intro.memory">[intro.memory]</a></span>) or
function (<span>6.8.4 <a href="https://wg21.link/basic.compound">[basic.compound]</a></span>). If
the operand designates an explicit object member function (<span>9.3.4.6
<a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>), the operand
shall be a <code class="sourceCode cpp"><em>qualified-id</em></code>
<span class="addu">or a
<code class="sourceCode cpp"><em>splice-expression</em></code></span>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_190" id="pnum_190">4</a></span>
A pointer to member is only formed when an explicit
<code class="sourceCode cpp"><span class="op">&amp;</span></code> is
used and its operand is a
<code class="sourceCode cpp"><em>qualified-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
not enclosed in parentheses.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.reflect-the-reflection-operator">7.6.2.10* [expr.reflect] The
reflection operator<a href="#expr.reflect-the-reflection-operator" class="self-link"></a></h3>
<p>Add a new subsection of <span>7.6.2 <a href="https://wg21.link/expr.unary">[expr.unary]</a></span> following
<span>7.6.2.9 <a href="https://wg21.link/expr.delete">[expr.delete]</a></span></p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>The reflection operator [expr.reflect]</strong></p>
<div class="sourceCode" id="cb132"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb132-1"><a href="#cb132-1" aria-hidden="true" tabindex="-1"></a><em>reflect-expression</em>:</span>
<span id="cb132-2"><a href="#cb132-2" aria-hidden="true" tabindex="-1"></a>   ^^ ::</span>
<span id="cb132-3"><a href="#cb132-3" aria-hidden="true" tabindex="-1"></a>   ^^ <em>qualified-reflection-name</em></span>
<span id="cb132-4"><a href="#cb132-4" aria-hidden="true" tabindex="-1"></a>   ^^ <em>type-id</em></span>
<span id="cb132-5"><a href="#cb132-5" aria-hidden="true" tabindex="-1"></a>   ^^ <em>id-expression</em></span>
<span id="cb132-6"><a href="#cb132-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb132-7"><a href="#cb132-7" aria-hidden="true" tabindex="-1"></a><em>qualified-reflection-name</em>:</span>
<span id="cb132-8"><a href="#cb132-8" aria-hidden="true" tabindex="-1"></a>   <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>identifier</em></span>
<span id="cb132-9"><a href="#cb132-9" aria-hidden="true" tabindex="-1"></a>   <em>nested-name-specifier</em> template <em>identifier</em></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_191" id="pnum_191">1</a></span>
The unary <code class="sourceCode cpp"><span class="op">^^</span></code>
operator, called the <em>reflection operator</em>, yields a prvalue of
type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
(<span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>).</p>
<p><span class="note"><span>[ <em>Note 1:</em> </span>This document
places no restriction on representing, by reflections, constructs not
described by this document or using such constructs as operands of
<code class="sourceCode cpp"><em>reflect-expression</em></code>s.<span>
— <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_192" id="pnum_192">2</a></span>
The component names of a
<code class="sourceCode cpp"><em>qualified-reflection-name</em></code>
are those of its
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> (if
any) and its
<code class="sourceCode cpp"><em>identifier</em></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_193" id="pnum_193">3</a></span>
A <code class="sourceCode cpp"><em>reflect-expression</em></code> is
parsed as the longest possible sequence of tokens that could
syntactically form a
<code class="sourceCode cpp"><em>reflect-expression</em></code>. A
<code class="sourceCode cpp"><em>reflect-expression</em></code> whose
terminal name is a
<code class="sourceCode cpp"><em>concept-name</em></code> or a
<code class="sourceCode cpp"><em>template-name</em></code> shall not be
followed by
<code class="sourceCode cpp"><span class="op">&lt;</span></code>.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb133"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb133-1"><a href="#cb133-1" aria-hidden="true" tabindex="-1"></a>static_assert(std::meta::is_type(^^int()));  // ^^ applies to the type-id &quot;int()&quot;</span>
<span id="cb133-2"><a href="#cb133-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb133-3"><a href="#cb133-3" aria-hidden="true" tabindex="-1"></a>template&lt;bool&gt; struct X {};</span>
<span id="cb133-4"><a href="#cb133-4" aria-hidden="true" tabindex="-1"></a>consteval bool operator&lt;(std::meta::info, X&lt;false&gt;) { return false; }</span>
<span id="cb133-5"><a href="#cb133-5" aria-hidden="true" tabindex="-1"></a>consteval void g(std::meta::info r, X&lt;false&gt; xv) {</span>
<span id="cb133-6"><a href="#cb133-6" aria-hidden="true" tabindex="-1"></a>  r == ^^int &amp;&amp; true;    // error: ^^ applies to the type-id &quot;int&amp;&amp;&quot;</span>
<span id="cb133-7"><a href="#cb133-7" aria-hidden="true" tabindex="-1"></a>  r == ^^int &amp; true;     // error: ^^ applies to the type-id &quot;int&amp;&quot;</span>
<span id="cb133-8"><a href="#cb133-8" aria-hidden="true" tabindex="-1"></a>  r == (^^int) &amp;&amp; true;  // OK</span>
<span id="cb133-9"><a href="#cb133-9" aria-hidden="true" tabindex="-1"></a>  r == ^^int &amp;&amp;&amp;&amp; true;  // error: &#39;int &amp;&amp;&amp;&amp;&#39; is not a valid type</span>
<span id="cb133-10"><a href="#cb133-10" aria-hidden="true" tabindex="-1"></a>  ^^X &lt; xv;              // error: reflect-expression whose terminal name is a</span>
<span id="cb133-11"><a href="#cb133-11" aria-hidden="true" tabindex="-1"></a>                         // template-name is followed by &lt;</span>
<span id="cb133-12"><a href="#cb133-12" aria-hidden="true" tabindex="-1"></a>  (^^X) &lt; xv;            // OK</span>
<span id="cb133-13"><a href="#cb133-13" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_194" id="pnum_194">4</a></span>
A <code class="sourceCode cpp"><em>reflect-expression</em></code> of the
form <code class="sourceCode cpp"><span class="op">^^</span> <span class="op">::</span></code>
represents the global namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_195" id="pnum_195">5</a></span>
If a <code class="sourceCode cpp"><em>reflect-expression</em></code>
<code class="sourceCode cpp"><em>R</em></code> matches the form <code class="sourceCode cpp"><span class="op">^^</span> <em>qualified-reflection-name</em></code>,
it is interpreted as such and its representation is determined as
follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_196" id="pnum_196">(5.1)</a></span>
If the <code class="sourceCode cpp"><em>identifier</em></code> is a
<code class="sourceCode cpp"><em>namespace-name</em></code> that names a
namespace alias ([namespace.alias]),
<code class="sourceCode cpp"><em>R</em></code> represents that namespace
alias. For any other
<code class="sourceCode cpp"><em>namespace-name</em></code>,
<code class="sourceCode cpp"><em>R</em></code> represents the denoted
namespace.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_197" id="pnum_197">(5.2)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>identifier</em></code> is a
<code class="sourceCode cpp"><em>concept-name</em></code>
([temp.concept]), <code class="sourceCode cpp"><em>R</em></code>
represents the denoted concept.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_198" id="pnum_198">(5.3)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>identifier</em></code> is a
<code class="sourceCode cpp"><em>template-name</em></code>
([temp.names]), the representation of
<code class="sourceCode cpp"><em>R</em></code> is determined as follows:
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_199" id="pnum_199">(5.3.1)</a></span>
If the <code class="sourceCode cpp"><em>template-name</em></code> names
an injected-class-name ([class.pre]), then:
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_200" id="pnum_200">(5.3.1.1)</a></span>
If the
<code class="sourceCode cpp"><em>qualified-reflection-name</em></code>
is of the form <code class="sourceCode cpp"><em>nested-name-specifier</em> <span class="kw">template</span> <em>identifier</em></code>,
then <code class="sourceCode cpp"><em>R</em></code> represents the class
template named by the injected-class-name.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_201" id="pnum_201">(5.3.1.2)</a></span>
Otherwise, the injected-class-name shall be unambiguous when considered
as a <code class="sourceCode cpp"><em>type-name</em></code> and
<code class="sourceCode cpp"><em>R</em></code> represents the class
template specialization so named.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_202" id="pnum_202">(5.3.2)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>template-name</em></code> names a
function template <code class="sourceCode cpp"><em>F</em></code>, then
the <code class="sourceCode cpp"><em>template-name</em></code>
interpreted as an
<code class="sourceCode cpp"><em>id-expression</em></code> shall denote
an overload set containing only
<code class="sourceCode cpp"><em>F</em></code>.
<code class="sourceCode cpp"><em>R</em></code> represents
<code class="sourceCode cpp"><em>F</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_203" id="pnum_203">(5.3.3)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>template-name</em></code> denotes a
primary class template, primary variable template, or alias template,
<code class="sourceCode cpp"><em>R</em></code> represents that
template.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_204" id="pnum_204">(5.4)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>identifier</em></code> names a type
alias that was introduced by the declaration of a template parameter,
<code class="sourceCode cpp"><em>R</em></code> represents the underlying
entity of that type alias. For any other
<code class="sourceCode cpp"><em>identifier</em></code> that names a
type alias, <code class="sourceCode cpp"><em>R</em></code> represents
that type alias.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_205" id="pnum_205">(5.5)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>identifier</em></code> is a
<code class="sourceCode cpp"><em>class-name</em></code> or an
<code class="sourceCode cpp"><em>enum-name</em></code>,
<code class="sourceCode cpp"><em>R</em></code> represents the denoted
type.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_206" id="pnum_206">(5.6)</a></span>
Otherwise, the
<code class="sourceCode cpp"><em>qualified-reflection-name</em></code>
shall be an <code class="sourceCode cpp"><em>id-expression</em></code>
<code class="sourceCode cpp"><em>I</em></code> and
<code class="sourceCode cpp"><em>R</em></code> is
<code class="sourceCode cpp"><span class="op">^^</span> <em>I</em></code>
(see below).</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_207" id="pnum_207">6</a></span>
A <code class="sourceCode cpp"><em>reflect-expression</em></code>
<code class="sourceCode cpp"><em>R</em></code> of the form
<code class="sourceCode cpp"><span class="op">^^</span> <em>type-id</em></code>
represents an entity determined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_208" id="pnum_208">(6.1)</a></span>
If the <code class="sourceCode cpp"><em>type-id</em></code> designates a
placeholder type, <code class="sourceCode cpp"><em>R</em></code> is
ill-formed.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_209" id="pnum_209">(6.2)</a></span>
Otherwise, if the <code class="sourceCode cpp"><em>type-id</em></code>
names a type alias that is a specialization of an alias template,
<code class="sourceCode cpp"><em>R</em></code> represents that type
alias.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_210" id="pnum_210">(6.3)</a></span>
Otherwise, <code class="sourceCode cpp"><em>R</em></code> represents the
type denoted by the
<code class="sourceCode cpp"><em>type-id</em></code>.</li>
</ul>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: All
other cases for
<code class="sourceCode default">^^ <em>type-id</em></code> are covered
by
<code class="sourceCode default"><em>qualified-reflection-name</em></code>.
]</span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_211" id="pnum_211">7</a></span>
A <code class="sourceCode cpp"><em>reflect-expression</em></code>
<code class="sourceCode cpp"><em>R</em></code> of the form <code class="sourceCode cpp"><span class="op">^^</span> <em>id-expression</em></code>
represents an entity determined as follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_212" id="pnum_212">(7.1)</a></span>
If the <code class="sourceCode cpp"><em>id-expression</em></code>
denotes an overload set <code class="sourceCode cpp"><em>S</em></code>,
overload resolution for the expression
<code class="sourceCode cpp"><span class="op">&amp;</span><em>S</em></code>
with no target shall select a unique function ([over.over]);
<code class="sourceCode cpp"><em>R</em></code> represents that
function.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_213" id="pnum_213">(7.2)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>id-expression</em></code> denotes a
variable declared by an
<code class="sourceCode cpp"><em>init-capture</em></code>
([expr.prim.lambda.capture]),
<code class="sourceCode cpp"><em>R</em></code> is ill-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_214" id="pnum_214">(7.3)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>id-expression</em></code> denotes a
local parameter introduced by a
<code class="sourceCode cpp"><em>requires-expression</em></code>
([expr.prim.req]), <code class="sourceCode cpp"><em>R</em></code> is
ill-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_215" id="pnum_215">(7.4)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>id-expression</em></code> denotes a
local entity <code class="sourceCode cpp"><em>E</em></code>
([basic.pre]) for which there is a lambda scope that intervenes between
<code class="sourceCode cpp"><em>R</em></code> and the point at which
<code class="sourceCode cpp"><em>E</em></code> was introduced,
<code class="sourceCode cpp"><em>R</em></code> is ill-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_216" id="pnum_216">(7.5)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>id-expression</em></code> denotes a
function-local predefined variable ([dcl.fct.def.general]),
<code class="sourceCode cpp"><em>R</em></code> is ill-formed. For any
other <code class="sourceCode cpp"><em>id-expression</em></code> that
denotes a variable, <code class="sourceCode cpp"><em>R</em></code>
represents that variable.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_217" id="pnum_217">(7.6)</a></span>
Otherwise, if the
<code class="sourceCode cpp"><em>id-expression</em></code> denotes a
structured binding, enumerator, or non-static data member,
<code class="sourceCode cpp"><em>R</em></code> represents that
entity.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_218" id="pnum_218">(7.7)</a></span>
Otherwise, <code class="sourceCode cpp"><em>R</em></code> is ill-formed.
<span class="note"><span>[ <em>Note 2:</em> </span>This includes
<code class="sourceCode cpp"><em>pack-index-expression</em></code>s and
constant template parameters.<span> — <em>end
note</em> ]</span></span></p></li>
</ul>
<p>The <code class="sourceCode cpp"><em>id-expression</em></code> of a
<code class="sourceCode cpp"><em>reflect-expression</em></code> is an
unevaluated operand ([expr.context]).</p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="dt">void</span> fn<span class="op">()</span> <span class="kw">requires</span> <span class="op">(^^</span>T <span class="op">!=</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb134-2"><a href="#cb134-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 class="dt">void</span> fn<span class="op">()</span> <span class="kw">requires</span> <span class="op">(^^</span>T <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb134-3"><a href="#cb134-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="op">&gt;</span> <span class="dt">void</span> fn<span class="op">()</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">))</span>;</span>
<span id="cb134-4"><a href="#cb134-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb134-5"><a href="#cb134-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> a <span class="op">=</span> <span class="op">^^</span>fn<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span>;     <span class="co">// OK</span></span>
<span id="cb134-6"><a href="#cb134-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> b <span class="op">=</span> <span class="op">^^</span>fn<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>;      <span class="co">// error: ambiguous</span></span>
<span id="cb134-7"><a href="#cb134-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb134-8"><a href="#cb134-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> c <span class="op">=</span> <span class="op">^^</span>std<span class="op">::</span>vector;  <span class="co">// OK</span></span>
<span id="cb134-9"><a href="#cb134-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb134-10"><a href="#cb134-10" 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="cb134-11"><a href="#cb134-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb134-12"><a href="#cb134-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^^</span>T;</span>
<span id="cb134-13"><a href="#cb134-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb134-14"><a href="#cb134-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb134-15"><a href="#cb134-15" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>S<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;::</span>r <span class="op">==</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb134-16"><a href="#cb134-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>S<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;::</span>type <span class="op">!=</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb134-17"><a href="#cb134-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb134-18"><a href="#cb134-18" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> X <span class="op">{}</span> Y;</span>
<span id="cb134-19"><a href="#cb134-19" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> Z <span class="op">{}</span> Z;</span>
<span id="cb134-20"><a href="#cb134-20" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> e <span class="op">=</span> <span class="op">^^</span>Y;  <span class="co">// OK, represents the type alias Y</span></span>
<span id="cb134-21"><a href="#cb134-21" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f <span class="op">=</span> <span class="op">^^</span>Z;  <span class="co">// OK, represents the type Z (not the type alias)</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.eq-equality-operators"><span>7.6.10 <a href="https://wg21.link/expr.eq">[expr.eq]</a></span> Equality
Operators<a href="#expr.eq-equality-operators" class="self-link"></a></h3>
<p>Add a new paragraph between paragraphs 5 and 6:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_219" id="pnum_219">5</a></span>
Two operands of type <code class="sourceCode cpp">std<span class="op">::</span>nullptr_t</code> or
one operand of type <code class="sourceCode cpp">std<span class="op">::</span>nullptr_t</code> and
the other a null pointer constant compare equal.</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_220" id="pnum_220">5+</a></span>
If both operands are of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
comparison is defined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_221" id="pnum_221">(5+.1)</a></span>
If one operand is a null reflection value, then they compare equal if
and only if the other operand is also a null reflection value.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_222" id="pnum_222">(5+.2)</a></span>
Otherwise, if one operand represents a value, then they compare equal if
and only if the other operand represents a value that is
template-argument-equivalent (<span>13.6 <a href="https://wg21.link/temp.type">[temp.type]</a></span>).</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_223" id="pnum_223">(5+.3)</a></span>
Otherwise, if one operand represents an object, then they compare equal
if and only if the other operand represents the same object.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_224" id="pnum_224">(5+.4)</a></span>
Otherwise, if one operand represents an entity, then they compare equal
if and only if the other operand represents the same entity.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_225" id="pnum_225">(5+.5)</a></span>
Otherwise, if one operand represents a direct base class relationship,
then they compare equal if and only if the other operand represents the
same direct base class relationship.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_226" id="pnum_226">(5+.6)</a></span>
Otherwise, both operands
<code class="sourceCode cpp">O<sub><em>1</em></sub></code> and
<code class="sourceCode cpp">O<sub><em>2</em></sub></code> represent
data member descriptions. The operands compare equal if and only if the
data member descriptions represented by
<code class="sourceCode cpp">O<sub><em>1</em></sub></code> and
<code class="sourceCode cpp">O<sub><em>2</em></sub></code> compare equal
(<span>11.4.1 <a href="https://wg21.link/class.mem.general">[class.mem.general]</a></span>).</li>
</ul>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_227" id="pnum_227">6</a></span>
If two operands compare equal, the result is
<code class="sourceCode cpp"><span class="kw">true</span></code> for the
<code class="sourceCode cpp"><span class="op">==</span></code> operator
and <code class="sourceCode cpp"><span class="kw">false</span></code>
for the <code class="sourceCode cpp"><span class="op">!=</span></code>
operator. If two operands compare unequal, the result is
<code class="sourceCode cpp"><span class="kw">false</span></code> for
the <code class="sourceCode cpp"><span class="op">==</span></code>
operator and
<code class="sourceCode cpp"><span class="kw">true</span></code> for the
<code class="sourceCode cpp"><span class="op">!=</span></code> operator.
Otherwise, the result of each of the operators is unspecified.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.const-constant-expressions"><span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span> Constant
Expressions<a href="#expr.const-constant-expressions" class="self-link"></a></h3>
<p>Add a bullet to paragraph 10 between 10.27 and 10.28 to disallow the
production of injected declarations from any core constant expression
that isn’t a consteval block.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_228" id="pnum_228">10</a></span>
An expression <code class="sourceCode cpp"><em>E</em></code> is a
<em>core constant expression</em> unless the evaluation of
<code class="sourceCode cpp"><em>E</em></code>, following the rules of
the abstract machine ([intro.execution]), would evaluate one of the
following:</p>
<p>[…]</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_229" id="pnum_229">(10.27)</a></span>
a
<code class="sourceCode cpp"><span class="kw">dynamic_cast</span></code>
([expr.dynamic.cast]) expression,
<code class="sourceCode cpp"><span class="kw">typeid</span></code>
([expr.typeid]) expression, or
<code class="sourceCode cpp"><em>new-expression</em></code> ([expr.new])
that would throw an exception where no definition of the exception type
is reachable;</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_230" id="pnum_230">(10.27+)</a></span>
an expression that would produce an injected declaration (see below),
unless <code class="sourceCode cpp"><em>E</em></code> is the
corresponding expression of a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
([dcl.pre]);</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_231" id="pnum_231">(10.28)</a></span>
an <code class="sourceCode cpp"><em>asm-declaration</em></code>
([dcl.asm]);</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_232" id="pnum_232">(10.29)</a></span>
[…]</li>
</ul>
</blockquote>
</div>
<p>Modify paragraph 17 to mention
<code class="sourceCode cpp"><em>splice-expression</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_233" id="pnum_233">17</a></span>
During the evaluation of an expression
<code class="sourceCode cpp"><em>E</em></code> as a core constant
expression, all
<code class="sourceCode cpp"><em>id-expression</em></code>s<span class="addu">,
<code class="sourceCode cpp"><em>splice-expression</em></code>s,</span>
and uses of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
that refer to an object or reference whose lifetime did not begin with
the evaluation of <code class="sourceCode cpp"><em>E</em></code> are
treated as referring to a specific instance of that object or reference
whose lifetime and that of all subobjects (including all union members)
includes the entire constant evaluation. […]</p>
</blockquote>
</div>
<p>Modify paragraph 22 to disallow returning non-consteval-only pointers
and references to consteval-only objects from constant expressions.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_234" id="pnum_234">22</a></span>
A <em>constant expression</em> is either a glvalue core constant
expression <span class="addu"><code class="sourceCode cpp"><em>E</em></code></span> that
<span class="addu"> </span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_235" id="pnum_235">(22.1)</a></span>
refers to an object or a non-immediate function<span class="addu">,
and</span></p></li>
<li><p><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_236" id="pnum_236">(22.2)</a></span>
if <code class="sourceCode cpp"><em>E</em></code> designates a function
of consteval-only type (<span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>)
or an object whose complete object is of consteval-only type, then
<code class="sourceCode cpp"><em>E</em></code> is also of consteval-only
type,</span></p>
<div class="addu">
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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="kw">struct</span> Base <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="kw">struct</span> Derived <span class="op">:</span> Base <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>info r; <span class="op">}</span>;</span>
<span id="cb135-3"><a href="#cb135-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb135-4"><a href="#cb135-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">const</span> Base<span class="op">&amp;</span> fn<span class="op">(</span><span class="kw">const</span> Derived<span class="op">&amp;</span> derived<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> derived; <span class="op">}</span></span>
<span id="cb135-5"><a href="#cb135-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb135-6"><a href="#cb135-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> obj <span class="op">=</span> Derived<span class="op">{^^::}</span>; <span class="co">// OK</span></span>
<span id="cb135-7"><a href="#cb135-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> d <span class="op">=</span> obj; <span class="co">// OK</span></span>
<span id="cb135-8"><a href="#cb135-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> b <span class="op">=</span> fn<span class="op">(</span>obj<span class="op">)</span>; <span class="co">// error: not a constant expression</span></span>
<span id="cb135-9"><a href="#cb135-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// because Derived is a consteval-only type but Base is not.</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div></li>
</ul>
<p>or a prvalue core constant expression whose result object
([basic.lval]) satisfies the following constraints:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_237" id="pnum_237">(22.3)</a></span>
each constituent reference refers to an object or a non-immediate
function,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_238" id="pnum_238">(22.4)</a></span>
no constituent value of scalar type is an indeterminate value or
erroneous value (<span>6.7.5 <a href="https://wg21.link/basic.indet">[basic.indet]</a></span>),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_239" id="pnum_239">(22.5)</a></span>
no constituent value of pointer type is a pointer to an immediate
function or an invalid pointer value ([basic.compound]), <span class="rm" style="color: #bf0303"><del>and</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_240" id="pnum_240">(22.6)</a></span>
no constituent value of pointer-to-member type designates an immediate
function<span class="rm" style="color: #bf0303"><del>.</del></span><span class="addu">, and</span></li>
</ul>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_241" id="pnum_241">(22.7)</a></span>
unless the value is of consteval-only type, no constituent value of
pointer or pointer-to-member type is
<ul>
<li>a pointer to a function or member of consteval-only type, or</li>
<li>a pointer to or past an object whose complete object has
consteval-only type,</li>
</ul>
nor does any constituent reference refer to an object or function of
consteval-only type.</li>
</ul>
</div>
</blockquote>
</div>
<p>Modify (and clean up) the definition of <em>immediate-escalating
expression</em> in paragraph 25 to also apply to expressions of
consteval-only type.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_242" id="pnum_242">25</a></span>
A<span class="rm" style="color: #bf0303"><del>n</del></span> <span class="addu">potentially-evaluated</span> expression or conversion is
<em>immediate-escalating</em> if it is <span class="rm" style="color: #bf0303"><del>not</del></span> <span class="addu">neither</span> initially in an immediate function context
<span class="addu">nor a subexpression of an immediate
invocation,</span> and it is <span class="rm" style="color: #bf0303"><del>either</del></span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_243" id="pnum_243">(25.1)</a></span>
<span class="rm" style="color: #bf0303"><del>a
potentially-evaluated</del></span> <span class="addu">an</span>
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
that <span class="rm" style="color: #bf0303"><del>denotes</del></span>
<span class="addu">designates</span> an immediate function<span class="addu">,</span> <span class="rm" style="color: #bf0303"><del>that
is not a subexpression of an immediate invocation, or</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_244" id="pnum_244">(25.2)</a></span>
an immediate invocation that is not a constant expression<span class="addu">, or</span> <span class="rm" style="color: #bf0303"><del>and is not a subexpression of an immediate
invocation.</del></span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_245" id="pnum_245">(25.3)</a></span>
of consteval-only type (<span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>).</span></li>
</ul>
</blockquote>
</div>
<p>Extend the definition of <em>immediate function</em> in paragraph 27
to include functions containing a declaration of a variable of
consteval-only type.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_246" id="pnum_246">27</a></span>
An <em>immediate function</em> is a function or constructor that is
<span class="addu">either</span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_247" id="pnum_247">(27.1)</a></span>
declared with the
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
specifier, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_248" id="pnum_248">(27.2)</a></span>
an immediate-escalating function <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>F</em></code></span></del></span>
whose function <span class="rm" style="color: #bf0303"><del>body
contains</del></span> <span class="addu">parameter scope is the
innermost non-block scope enclosing either</span>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_249" id="pnum_249">(27.2.1)</a></span>
an immediate-escalating expression <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>E</em></code></span>
such that
<span><code class="sourceCode default"><em>E</em></code></span>’s
innermost enclosing non-block scope is
<span><code class="sourceCode default"><em>F</em></code></span>’s
function parameter scope.</del></span><span class="addu">,
or</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_250" id="pnum_250">(27.2.2)</a></span>
a definition of a non-constexpr variable with consteval-only
type.</span></li>
</ul></li>
</ul>
</blockquote>
</div>
<p>After the example following the definition of <em>manifestly
constant-evaluated</em>, introduce new terminology and rules for
injecting declarations and renumber accordingly:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_251" id="pnum_251">28</a></span>
The evaluation of an expression can introduce one or more <em>injected
declarations</em>. Each such declaration has an associated
<em>synthesized point</em> which follows the last non-synthesized
program point in the translation unit containing that declaration. The
evaluation is said to <em>produce</em> the declaration.</p>
<p><span class="note13"><span>[ <em>Note 13:</em> </span>Special rules
concerning reachability apply to synthesized points (<span>10.7 <a href="https://wg21.link/module.reach">[module.reach]</a></span>).<span>
— <em>end note</em> ]</span></span></p>
<p>No member of an injected declaration shall have a name reserved by
the implementation ([lex.name]); no diagnostic is required.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_252" id="pnum_252">29</a></span>
Let <code class="sourceCode cpp"><em>C</em></code> be a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>,
the evaluation of whose corresponding expression produces an injected
declaration <code class="sourceCode cpp"><em>D</em></code>
([meta.reflection.define.aggregate]). The scope of
<code class="sourceCode cpp"><em>D</em></code> shall not enclose
<code class="sourceCode cpp"><em>C</em></code>. The program is
ill-formed if a scope <code class="sourceCode cpp"><em>S</em></code>
encloses exactly one of <code class="sourceCode cpp"><em>C</em></code>
or <code class="sourceCode cpp"><em>D</em></code> where
<code class="sourceCode cpp"><em>S</em></code> is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_253" id="pnum_253">(29.1)</a></span>
a function parameter scope, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_254" id="pnum_254">(29.2)</a></span>
a class scope.</li>
</ul>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<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><span class="kw">struct</span> S0 <span class="op">{</span></span>
<span id="cb136-2"><a href="#cb136-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb136-3"><a href="#cb136-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S0, <span class="op">{})</span>; <span class="co">// error: S0 encloses the consteval block</span></span>
<span id="cb136-4"><a href="#cb136-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb136-5"><a href="#cb136-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb136-6"><a href="#cb136-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-7"><a href="#cb136-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S1;</span>
<span id="cb136-8"><a href="#cb136-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S1, <span class="op">{})</span>; <span class="op">}</span>  <span class="co">// OK</span></span>
<span id="cb136-9"><a href="#cb136-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-10"><a href="#cb136-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="kw">consteval</span> <span class="dt">void</span> tfn1<span class="op">()</span> <span class="op">{</span></span>
<span id="cb136-11"><a href="#cb136-11" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(</span>R, <span class="op">{})</span>;</span>
<span id="cb136-12"><a href="#cb136-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb136-13"><a href="#cb136-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-14"><a href="#cb136-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S2;</span>
<span id="cb136-15"><a href="#cb136-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> tfn1<span class="op">&lt;^^</span>S2<span class="op">&gt;()</span>; <span class="op">}</span></span>
<span id="cb136-16"><a href="#cb136-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, tfn1&lt;^^S2&gt;() and S2 are enclosed by the same scope</span></span>
<span id="cb136-17"><a href="#cb136-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-18"><a href="#cb136-18" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="kw">consteval</span> <span class="dt">void</span> tfn2<span class="op">()</span> <span class="op">{</span></span>
<span id="cb136-19"><a href="#cb136-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(</span>R, <span class="op">{})</span>; <span class="op">}</span></span>
<span id="cb136-20"><a href="#cb136-20" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> b;</span>
<span id="cb136-21"><a href="#cb136-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb136-22"><a href="#cb136-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-23"><a href="#cb136-23" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S3;</span>
<span id="cb136-24"><a href="#cb136-24" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> tfn2<span class="op">&lt;^^</span>S3<span class="op">&gt;()</span>; <span class="op">}</span></span>
<span id="cb136-25"><a href="#cb136-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: complete_type(^^S3) is enclosed tfn2&lt;^^S3&gt;, but S3 is not</span></span>
<span id="cb136-26"><a href="#cb136-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-27"><a href="#cb136-27" 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 class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb136-28"><a href="#cb136-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> S4;</span>
<span id="cb136-29"><a href="#cb136-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="dt">void</span> sfn<span class="op">()</span> <span class="kw">requires</span> <span class="op">([]</span> <span class="op">{</span></span>
<span id="cb136-30"><a href="#cb136-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S4, <span class="op">{})</span>; <span class="op">}</span></span>
<span id="cb136-31"><a href="#cb136-31" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb136-32"><a href="#cb136-32" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb136-33"><a href="#cb136-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb136-34"><a href="#cb136-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-35"><a href="#cb136-35" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> TCls<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;::</span>sfn<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb136-36"><a href="#cb136-36" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: TCls&lt;void&gt;::S4 is not enclosed by requires-clause lambda</span></span>
<span id="cb136-37"><a href="#cb136-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-38"><a href="#cb136-38" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S5;</span>
<span id="cb136-39"><a href="#cb136-39" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Cls <span class="op">{</span></span>
<span id="cb136-40"><a href="#cb136-40" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S5, <span class="op">{})</span>; <span class="op">}</span></span>
<span id="cb136-41"><a href="#cb136-41" aria-hidden="true" tabindex="-1"></a>    <span class="co">// error: S5 is not enclosed by class Cls</span></span>
<span id="cb136-42"><a href="#cb136-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb136-43"><a href="#cb136-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb136-44"><a href="#cb136-44" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S6;</span>
<span id="cb136-45"><a href="#cb136-45" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span> <span class="co">// #1</span></span>
<span id="cb136-46"><a href="#cb136-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> S7; <span class="co">// local class</span></span>
<span id="cb136-47"><a href="#cb136-47" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span> <span class="co">// #2</span></span>
<span id="cb136-48"><a href="#cb136-48" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S6, <span class="op">{})</span>;</span>
<span id="cb136-49"><a href="#cb136-49" aria-hidden="true" tabindex="-1"></a>      <span class="co">// error: consteval block #1 encloses consteval block #2 but not S6</span></span>
<span id="cb136-50"><a href="#cb136-50" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S7, <span class="op">{})</span>;  <span class="co">// OK, consteval block #1 encloses both #2 and S7</span></span>
<span id="cb136-51"><a href="#cb136-51" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb136-52"><a href="#cb136-52" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_255" id="pnum_255">30</a></span>
The <em>evaluation context</em> is a set of program points that
determines the behavior of certain functions used for reflection
([meta.reflection]). During the evaluation of an expression
<code class="sourceCode cpp"><em>E</em></code> as a core constant
expression, the evaluation context is defined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_256" id="pnum_256">(30.1)</a></span>
If <code class="sourceCode cpp"><em>E</em></code> is a
potentially-evaluated subexpression ([intro.execution]) of a default
member initializer used by an aggregate initialization that appears at a
point <code class="sourceCode cpp"><em>Q</em></code>, the evaluation
context of <code class="sourceCode cpp"><em>Q</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_257" id="pnum_257">(30.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>E</em></code> is a
potentially-evaluated subexpression of a default argument
([dcl.fct.default]), and that default argument is being used by an
invocation of a function ([expr.call]) that appears at a point
<code class="sourceCode cpp"><em>Q</em></code>, the evaluation context
of <code class="sourceCode cpp"><em>Q</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_258" id="pnum_258">(30.3)</a></span>
Otherwise, the instantiation context of the point at which
<code class="sourceCode cpp"><em>E</em></code> appears.</li>
</ul>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.pre-preamble"><span>9.1 <a href="https://wg21.link/dcl.pre">[dcl.pre]</a></span> Preamble<a href="#dcl.pre-preamble" class="self-link"></a></h3>
<p>Introduce the non-terminal
<code class="sourceCode cpp"><em>vacuous-declaration</em></code> in
paragraph 9.1 to encompass static assertions, empty declarations, and
consteval blocks:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb137"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb137-1"><a href="#cb137-1" aria-hidden="true" tabindex="-1"></a>  <em>block-declaration</em>:</span>
<span id="cb137-2"><a href="#cb137-2" aria-hidden="true" tabindex="-1"></a>    <em>simple-declaration</em></span>
<span id="cb137-3"><a href="#cb137-3" aria-hidden="true" tabindex="-1"></a>    <em>asm-declaration</em></span>
<span id="cb137-4"><a href="#cb137-4" aria-hidden="true" tabindex="-1"></a>    <em>namespace-alias-definition</em></span>
<span id="cb137-5"><a href="#cb137-5" aria-hidden="true" tabindex="-1"></a>    <em>using-declaration</em></span>
<span id="cb137-6"><a href="#cb137-6" aria-hidden="true" tabindex="-1"></a>    <em>using-enum-declaration</em></span>
<span id="cb137-7"><a href="#cb137-7" aria-hidden="true" tabindex="-1"></a>    <em>using-directive</em></span>
<span id="cb137-8"><a href="#cb137-8" aria-hidden="true" tabindex="-1"></a><span class="st">-   <em>static_assert-declaration</em></span></span>
<span id="cb137-9"><a href="#cb137-9" aria-hidden="true" tabindex="-1"></a>    <em>alias-declaration</em></span>
<span id="cb137-10"><a href="#cb137-10" aria-hidden="true" tabindex="-1"></a>    <em>opaque-enum-declaration</em></span>
<span id="cb137-11"><a href="#cb137-11" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>vacuous-declaration</em></span></span>
<span id="cb137-12"><a href="#cb137-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb137-13"><a href="#cb137-13" aria-hidden="true" tabindex="-1"></a>[...]</span>
<span id="cb137-14"><a href="#cb137-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb137-15"><a href="#cb137-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>vacuous-declaration</em>:</span></span>
<span id="cb137-16"><a href="#cb137-16" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>static_assert-declaration</em></span></span>
<span id="cb137-17"><a href="#cb137-17" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>consteval-block-declaration</em></span></span>
<span id="cb137-18"><a href="#cb137-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb137-19"><a href="#cb137-19" aria-hidden="true" tabindex="-1"></a>  <em>static_assert-declaration</em>:</span>
<span id="cb137-20"><a href="#cb137-20" aria-hidden="true" tabindex="-1"></a>    static_assert ( <em>constant-expression</em> ) ;</span>
<span id="cb137-21"><a href="#cb137-21" aria-hidden="true" tabindex="-1"></a>    static_assert ( <em>constant-expression</em> , <em>static_assert-message</em> ) ;</span>
<span id="cb137-22"><a href="#cb137-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb137-23"><a href="#cb137-23" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>consteval-block-declaration</em>:</span></span>
<span id="cb137-24"><a href="#cb137-24" aria-hidden="true" tabindex="-1"></a><span class="va">+   consteval <em>compound-statement</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Strike the assertion that a
<code class="sourceCode cpp"><em>typedef-name</em></code> is synonymous
with its associated type from paragraph 8 (type aliases are entities
now).</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_259" id="pnum_259">8</a></span>
If the <code class="sourceCode cpp"><em>decl-specifier-seq</em></code>
contains the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier, the declaration is a <em>typedef declaration</em> and each
<code class="sourceCode cpp"><em>declarator-id</em></code> is declared
to be a <code class="sourceCode cpp"><em>typedef-name</em></code><span class="rm" style="color: #bf0303"><del>, synonymous with its associated
type</del></span> (<span>9.2.4 <a href="https://wg21.link/dcl.typedef">[dcl.typedef]</a></span>).</p>
</blockquote>
</div>
<p>Insert the following after paragraph 14 in relation to consteval
blocks:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_260" id="pnum_260">14</a></span>
<em>Recommended practice</em>: When a
<code class="sourceCode cpp"><em>static_assert-declaration</em></code>
fails, […]</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_261" id="pnum_261">*</a></span>
For a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
<code class="sourceCode cpp"><em>D</em></code>, the expression
<code class="sourceCode cpp"><em>E</em></code> corresponding to
<code class="sourceCode cpp"><em>D</em></code> is:</p>
<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><span class="op">[]</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="kw">static</span> <span class="kw">consteval</span> <em>compound-statement</em> <span class="op">()</span></span></code></pre></div>
<p><code class="sourceCode cpp"><em>D</em></code> is equivalent to:</p>
<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><span class="kw">static_assert</span><span class="op">((</span><em>E</em>, <span class="kw">true</span><span class="op">))</span>;</span></code></pre></div>
<p><span class="note"><span>[ <em>Note 1:</em> </span>Evaluating a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
can produce injected declarations as side effects ([expr.const]).<span>
— <em>end note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb140"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb140-1"><a href="#cb140-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S;</span>
<span id="cb140-2"><a href="#cb140-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb140-3"><a href="#cb140-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>meta<span class="op">::</span>define_aggregate<span class="op">(^^</span>S, <span class="op">{})</span>; <span class="co">// ok</span></span>
<span id="cb140-4"><a href="#cb140-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb140-5"><a href="#cb140-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb140-6"><a href="#cb140-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> X <span class="op">{</span> <span class="op">}</span>; <span class="co">// error: local templates are not allowed</span></span>
<span id="cb140-7"><a href="#cb140-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb140-8"><a href="#cb140-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb140-9"><a href="#cb140-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> C <span class="op">=</span> <span class="kw">true</span>; <span class="co">// error: local concepts are not allowed</span></span>
<span id="cb140-10"><a href="#cb140-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb140-11"><a href="#cb140-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span>; <span class="co">// ok</span></span>
<span id="cb140-12"><a href="#cb140-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_262" id="pnum_262">15</a></span>
An <code class="sourceCode cpp"><em>empty-declaration</em></code> has no
effect.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.typedef-the-typedef-specifier"><span>9.2.4 <a href="https://wg21.link/dcl.typedef">[dcl.typedef]</a></span> The
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier<a href="#dcl.typedef-the-typedef-specifier" class="self-link"></a></h3>
<p>Modify paragraphs 1-2 to clarify that the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier now introduces an entity.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_263" id="pnum_263">1</a></span>
Declarations containing the
<code class="sourceCode cpp"><em>decl-specifier</em></code>
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
declare <span class="rm" style="color: #bf0303"><del>identifiers that
can be used later for naming</del></span> <span class="addu">type
aliases whose underlying entities are</span> fundamental (<span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>)
or compound (<span>6.8.4 <a href="https://wg21.link/basic.compound">[basic.compound]</a></span>)
types. The
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier shall not be combined in a
<code class="sourceCode cpp"><em>decl-specifier-seq</em></code> with any
other kind of specifier except a
<code class="sourceCode cpp"><em>defining-type-specifier</em></code>,
and it shall not be used in the
<code class="sourceCode cpp"><em>decl-specifier-seq</em></code> of a
<code class="sourceCode cpp"><em>parameter-declaration</em></code>
(<span>9.3.4.6 <a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>)
nor in the
<code class="sourceCode cpp"><em>decl-specifier-seq</em></code> of a
<code class="sourceCode cpp"><em>function-definition</em></code>
(<span>9.6 <a href="https://wg21.link/dcl.fct.def">[dcl.fct.def]</a></span>). If a
<code class="sourceCode cpp"><em>typedef-specifier</em></code> appears
in a declaration without a
<code class="sourceCode cpp"><em>declarator</em></code>, the program is
ill-formed.</p>
<div class="sourceCode" id="cb141"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb141-1"><a href="#cb141-1" aria-hidden="true" tabindex="-1"></a>  <em>typedef-name</em>:</span>
<span id="cb141-2"><a href="#cb141-2" aria-hidden="true" tabindex="-1"></a>      <em>identifier</em></span>
<span id="cb141-3"><a href="#cb141-3" aria-hidden="true" tabindex="-1"></a>      <em>simple-template-id</em></span></code></pre></div>
<p>A name declared with the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier becomes a
<code class="sourceCode cpp"><em>typedef-name</em></code>. <span class="rm" style="color: #bf0303"><del>A
<span><code class="sourceCode default"><em>typedef-name</em></code></span>
names</del></span> <span class="addu">The underlying entity of the type
alias is</span> the type associated with the
<code class="sourceCode cpp"><em>identifier</em></code> (<span>9.3 <a href="https://wg21.link/dcl.decl">[dcl.decl]</a></span>) or
<code class="sourceCode cpp"><em>simple-template-id</em></code>
(<span>13.1 <a href="https://wg21.link/temp.pre">[temp.pre]</a></span>);
a <code class="sourceCode cpp"><em>typedef-name</em></code> <span class="rm" style="color: #bf0303"><del>is</del></span> thus <span class="rm" style="color: #bf0303"><del>a synonym for</del></span> <span class="addu">denotes</span> another type. A
<code class="sourceCode cpp"><em>typedef-name</em></code> does not
introduce a new type the way a class declaration (<span>11.3 <a href="https://wg21.link/class.name">[class.name]</a></span>) or enum
declaration (<span>9.8.1 <a href="https://wg21.link/dcl.enum">[dcl.enum]</a></span>) does.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_264" id="pnum_264">2</a></span>
A <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span> can also be <span class="rm" style="color: #bf0303"><del>introduced</del></span> <span class="addu">declared</span> by an
<code class="sourceCode cpp"><em>alias-declaration</em></code>. The
<code class="sourceCode cpp"><em>identifier</em></code> following the
<code class="sourceCode cpp"><span class="kw">using</span></code>
keyword is not looked up; it becomes <span class="rm" style="color: #bf0303"><del>a</del></span> <span class="addu">the</span>
<code class="sourceCode cpp"><em>typedef-name</em></code> <span class="addu">of a type alias</span> and the optional
<code class="sourceCode cpp"><em>attribute-specifier-seq</em></code>
following the <code class="sourceCode cpp"><em>identifier</em></code>
appertains to that <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span>. Such a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span> has the same semantics as if it
were introduced by the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier. In particular, it does not define a new type.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.type.simple-simple-type-specifiers"><span>9.2.9.3 <a href="https://wg21.link/dcl.type.simple">[dcl.type.simple]</a></span>
Simple type specifiers<a href="#dcl.type.simple-simple-type-specifiers" class="self-link"></a></h3>
<p>Extend the grammar for
<code class="sourceCode cpp"><em>computed-type-specifier</em></code> as
follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb142"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb142-1"><a href="#cb142-1" aria-hidden="true" tabindex="-1"></a>  <em>computed-type-specifier</em>:</span>
<span id="cb142-2"><a href="#cb142-2" aria-hidden="true" tabindex="-1"></a>      <em>decltype-specifier</em></span>
<span id="cb142-3"><a href="#cb142-3" aria-hidden="true" tabindex="-1"></a>      <em>pack-index-specifier</em></span>
<span id="cb142-4"><a href="#cb142-4" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-type-specifier</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Extend the definition of “placeholder for a deduced class type” in p3
to accommodate
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_265" id="pnum_265">3</a></span>
A
<code class="sourceCode cpp"><em>placeholder-type-specifier</em></code>
is a placeholder for a type to be deduced ([dcl.spec.auto]). A
<code class="sourceCode cpp"><em>type-specifier</em></code> <span class="rm" style="color: #bf0303"><del>of the form <span><code class="sourceCode default">typename<sub><em>opt</em></sub> <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></code></span></del></span>
is a placeholder for a deduced class type ([dcl.type.class.deduct])
<span class="addu">if it either </span></p>
<ul>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_266" id="pnum_266">(3.1)</a></span>
is of the form <code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></code>,
or</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_267" id="pnum_267">(3.2)</a></span>
is of the form
<code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>splice-specifier</em></code>
and the <code class="sourceCode cpp"><em>splice-specifier</em></code>
designates a class template or alias template.</span></li>
</ul>
<p>The
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specifier</em></code></span>, if
any, shall be non-dependent and the
<code class="sourceCode cpp"><em>template-name</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specifier</em></code></span>
shall <span class="rm" style="color: #bf0303"><del>name</del></span>
<span class="addu">designate</span> a deducible template. A
<em>deducible template</em> is either a class template or is an alias
template whose
<code class="sourceCode cpp"><em>defining-type-id</em></code> is of the
form</p>
<div class="sourceCode" id="cb143"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb143-1"><a href="#cb143-1" aria-hidden="true" tabindex="-1"></a>typename<sub><em>opt</em></sub> <em>nested-name-specifier</em><sub><em>opt</em></sub> template<sub><em>opt</em></sub> <em>simple-template-id</em></span></code></pre></div>
<p>where the
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> (if
any) is non-dependent and the
<code class="sourceCode cpp"><em>template-name</em></code> of the
<code class="sourceCode cpp"><em>simple-template-id</em></code> names a
deducible template.</p>
</blockquote>
</div>
<p>Add a row to [tab:dcl.type.simple] to cover the
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
production.</p>
<div class="std">
<blockquote>
<center>
Table 17:
<code class="sourceCode cpp"><em>simple-type-specifier</em></code>s and
the types they specify [tab:dcl.type.simple]
</center>
<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;"><div style="text-align:center">
<strong>Specifier(s)</strong>
</div></th>
<th style="text-align: left;"><div style="text-align:center">
<strong>Type</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp"><em>type-name</em></code></td>
<td style="text-align: left;">the type named</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp"><em>simple-template-id</em></code></td>
<td style="text-align: left;">the type as defined in [temp.names]</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp"><em>decltype-specifier</em></code></td>
<td style="text-align: left;">the type as defined in
[dcl.type.decltype]</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp"><em>pack-index-specifier</em></code></td>
<td style="text-align: left;">the type as defined in
[dcl.type.pack.index]</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp"><em>placeholder-type-specifier</em></code></td>
<td style="text-align: left;">the type as defined in
[dcl.spec.auto]</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp"><em>template-name</em></code></td>
<td style="text-align: left;">the type as defined in
[dcl.type.class.deduct]</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><span class="addu"><code class="sourceCode cpp"><em>splice-type-specifier</em></code></span></td>
<td style="text-align: left;"><span class="addu">the type as defined in
[dcl.type.splice]</span></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">...</span></code></td>
<td style="text-align: left;">…</td>
</tr>
</tbody>
</table>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.type.decltype-decltype-specifiers"><span>9.2.9.6 <a href="https://wg21.link/dcl.type.decltype">[dcl.type.decltype]</a></span>
Decltype specifiers<a href="#dcl.type.decltype-decltype-specifiers" class="self-link"></a></h3>
<p>Add a bullet after bullet 1.3 to apply to
<code class="sourceCode cpp"><em>splice-expression</em></code>s, and
extend the example that follows the paragraph:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_268" id="pnum_268">1</a></span>
For an expression <code class="sourceCode cpp"><em>E</em></code>, the
type denoted by <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><em>E</em><span class="op">)</span></code>
is defined as follows:</p>
<p>[…]</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_269" id="pnum_269">(1.3)</a></span>
otherwise, if <code class="sourceCode cpp"><em>E</em></code> is an
unparenthesized
<code class="sourceCode cpp"><em>id-expression</em></code> or an
unparenthesized class member access ([expr.ref]), <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><em>E</em><span class="op">)</span></code>
is the type of the entity named by
<code class="sourceCode cpp"><em>E</em></code>. If there is no such
entity, the program is ill-formed;</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_270" id="pnum_270">(1.3+)</a></span>
otherwise, if <code class="sourceCode cpp"><em>E</em></code> is an
unparenthesized
<code class="sourceCode cpp"><em>splice-expression</em></code>, <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><em>E</em><span class="op">)</span></code>
is the type of the entity, object, or value designated by the
<code class="sourceCode cpp"><em>splice-specifier</em></code> of
<code class="sourceCode cpp"><em>E</em></code>;</span></li>
</ul>
<p>[…]</p>
<p>The operand of the
<code class="sourceCode cpp"><span class="kw">decltype</span></code>
specifier is an unevaluated operand.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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">const</span> <span class="dt">int</span> <span class="op">&amp;&amp;</span> foo<span class="op">()</span>;</span>
<span id="cb144-2"><a href="#cb144-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i;</span>
<span id="cb144-3"><a href="#cb144-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span><span class="dt">double</span> x; <span class="op">}</span>;</span>
<span id="cb144-4"><a href="#cb144-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> A<span class="op">*</span> a <span class="op">=</span> <span class="kw">new</span> A<span class="op">()</span>;</span>
<span id="cb144-5"><a href="#cb144-5" aria-hidden="true" tabindex="-1"></a><span class="kw">decltype</span><span class="op">(</span>foo<span class="op">())</span> x1 <span class="op">=</span> <span class="dv">17</span>;       <span class="co">// type is const int&amp;&amp;</span></span>
<span id="cb144-6"><a href="#cb144-6" aria-hidden="true" tabindex="-1"></a><span class="kw">decltype</span><span class="op">(</span>i<span class="op">)</span> x2;                <span class="co">// type is int</span></span>
<span id="cb144-7"><a href="#cb144-7" aria-hidden="true" tabindex="-1"></a><span class="kw">decltype</span><span class="op">(</span>a<span class="op">-&gt;</span>x<span class="op">)</span> x3;             <span class="co">// type is double</span></span>
<span id="cb144-8"><a href="#cb144-8" aria-hidden="true" tabindex="-1"></a><span class="kw">decltype</span><span class="op">((</span>a<span class="op">-&gt;</span>x<span class="op">))</span> x4 <span class="op">=</span> x3;      <span class="co">// type is const double&amp;</span></span>
<span id="cb144-9"><a href="#cb144-9" aria-hidden="true" tabindex="-1"></a><span class="addu"><code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">([:^^</span>x1<span class="op">:])</span> x5 <span class="op">=</span> <span class="dv">18</span>;    <span class="co">// type is const int&amp;&amp;</span></code></span></span>
<span id="cb144-10"><a href="#cb144-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb144-11"><a href="#cb144-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb144-12"><a href="#cb144-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">[](</span><span class="kw">auto</span> <span class="op">...</span>pack<span class="op">)</span> <span class="op">{</span></span>
<span id="cb144-13"><a href="#cb144-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">decltype</span><span class="op">(</span>pack<span class="op">...[</span><span class="dv">0</span><span class="op">])</span> <span class="rm" style="color: #bf0303"><del>x5</del></span> <span class="addu">x6</span>;    <span class="co">// type is int</span></span>
<span id="cb144-14"><a href="#cb144-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">decltype</span><span class="op">((</span>pack<span class="op">...[</span><span class="dv">0</span><span class="op">]))</span> <span class="rm" style="color: #bf0303"><del>x6</del></span> <span class="addu">x7</span>;  <span class="co">// type is int&amp;</span></span>
<span id="cb144-15"><a href="#cb144-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb144-16"><a href="#cb144-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.spec.auto.general-placeholder-type-specifiers"><span>9.2.9.7.1
<a href="https://wg21.link/dcl.spec.auto.general">[dcl.spec.auto.general]</a></span>
Placeholder type specifiers<a href="#dcl.spec.auto.general-placeholder-type-specifiers" class="self-link"></a></h3>
<p>Extend the wording in <span>9.2.9.7.1 <a href="https://wg21.link/dcl.spec.auto.general">[dcl.spec.auto.general]</a></span>/13
to account for splicing:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_271" id="pnum_271">13</a></span>
If a variable or function with an undeduced placeholder type is <span class="addu">either</span> named by an expression ([basic.def.odr])
<span class="addu">or designated by a
<code class="sourceCode cpp"><em>splice-specifier</em></code> in an
expression</span>, the program is ill-formed. Once a non-discarded
<code class="sourceCode cpp"><span class="cf">return</span></code>
statement has been seen in a function, however, the return type deduced
from that statement can be used in the rest of the function, including
in other
<code class="sourceCode cpp"><span class="cf">return</span></code>
statements.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div>
<div class="sourceCode" id="cb145"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb145-1"><a href="#cb145-1" aria-hidden="true" tabindex="-1"></a>  auto n = n;                     // error: n&#39;s initializer refers to n</span>
<span id="cb145-2"><a href="#cb145-2" aria-hidden="true" tabindex="-1"></a>  auto f();</span>
<span id="cb145-3"><a href="#cb145-3" aria-hidden="true" tabindex="-1"></a>  void g() { &amp;f; }                // error: f&#39;s return type is unknown</span>
<span id="cb145-4"><a href="#cb145-4" aria-hidden="true" tabindex="-1"></a>  auto sum(int i) {</span>
<span id="cb145-5"><a href="#cb145-5" aria-hidden="true" tabindex="-1"></a>    if (i == 1)</span>
<span id="cb145-6"><a href="#cb145-6" aria-hidden="true" tabindex="-1"></a>      return i;                   // sum&#39;s return type is int</span>
<span id="cb145-7"><a href="#cb145-7" aria-hidden="true" tabindex="-1"></a>    else</span>
<span id="cb145-8"><a href="#cb145-8" aria-hidden="true" tabindex="-1"></a>      return sum(i-1)+i;          // OK, sum&#39;s return type has been deduced</span>
<span id="cb145-9"><a href="#cb145-9" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb145-10"><a href="#cb145-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb145-11"><a href="#cb145-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ auto f2() {</span></span>
<span id="cb145-12"><a href="#cb145-12" aria-hidden="true" tabindex="-1"></a><span class="va">+   int x;</span></span>
<span id="cb145-13"><a href="#cb145-13" aria-hidden="true" tabindex="-1"></a><span class="va">+   return [:std::meta::parent_of(^^x):](); // error: f2&#39;s return type is unknown</span></span>
<span id="cb145-14"><a href="#cb145-14" aria-hidden="true" tabindex="-1"></a><span class="va">+ }</span></span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.type.splice-type-splicing">9.2.9.8+
[dcl.type.splice] Type splicing<a href="#dcl.type.splice-type-splicing" class="self-link"></a></h3>
<p>Add a new subsection of (<span>9.2.9 <a href="https://wg21.link/dcl.type">[dcl.type]</a></span>) following
(<span>9.2.9.8 <a href="https://wg21.link/dcl.type.class.deduct">[dcl.type.class.deduct]</a></span>).</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Type Splicing [dcl.type.splice]</strong></p>
<div class="sourceCode" id="cb146"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb146-1"><a href="#cb146-1" aria-hidden="true" tabindex="-1"></a><em>splice-type-specifier</em>:</span>
<span id="cb146-2"><a href="#cb146-2" aria-hidden="true" tabindex="-1"></a>   typename<sub><em>opt</em></sub> <em>splice-specifier</em></span>
<span id="cb146-3"><a href="#cb146-3" aria-hidden="true" tabindex="-1"></a>   typename<sub><em>opt</em></sub> <em>splice-specialization-specifier</em></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_272" id="pnum_272">1</a></span>
A <code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
immediately followed by
<code class="sourceCode cpp"><span class="op">::</span></code> is never
interpreted as part of a
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>. A
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
not preceded by
<code class="sourceCode cpp"><span class="kw">typename</span></code> is
only interpreted as a
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
within a type-only context (<span>13.8.1 <a href="https://wg21.link/temp.res.general">[temp.res.general]</a></span>).</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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><span class="kw">struct</span> S <span class="op">{</span> <span class="kw">using</span> type <span class="op">=</span> <span class="dt">int</span>; <span class="op">}</span>;</span>
<span id="cb147-2"><a href="#cb147-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> R<span class="op">&gt;</span> <span class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb147-3"><a href="#cb147-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <span class="op">[:</span>R<span class="op">:]::</span>type member;  <span class="co">// typename applies to the qualified name</span></span>
<span id="cb147-4"><a href="#cb147-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb147-5"><a href="#cb147-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb147-6"><a href="#cb147-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb147-7"><a href="#cb147-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">[:^^</span>S<span class="op">::</span>type<span class="op">:]</span> <span class="op">*</span>var;           <span class="co">// error: [:^^S::type:] is an expression</span></span>
<span id="cb147-8"><a href="#cb147-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <span class="op">[:^^</span>S<span class="op">::</span>type<span class="op">:]</span> <span class="op">*</span>var;  <span class="co">// OK, declares variable with type int*</span></span>
<span id="cb147-9"><a href="#cb147-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb147-10"><a href="#cb147-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb147-11"><a href="#cb147-11" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> alias <span class="op">=</span> <span class="op">[:^^</span>S<span class="op">::</span>type<span class="op">:]</span>;    <span class="co">// OK, type-only context</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_273" id="pnum_273">2</a></span>
For a <code class="sourceCode cpp"><em>splice-type-specifier</em></code>
of the form
<code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>splice-specifier</em></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> shall
designate a type, a primary class template, or an alias template. The
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
designates the same entity as the
<code class="sourceCode cpp"><em>splice-specifier</em></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_274" id="pnum_274">3</a></span>
For a <code class="sourceCode cpp"><em>splice-type-specifier</em></code>
of the form <code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>splice-specialization-specifier</em></code>,
the <code class="sourceCode cpp"><em>splice-specifier</em></code> of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
shall designate a primary class template or an alias template. The
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
designates the specialization of
<code class="sourceCode cpp"><em>T</em></code> corresponding to the
<code class="sourceCode cpp"><em>template-argument-list</em></code> (if
any) of the
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.array-arrays"><span>9.3.4.5 <a href="https://wg21.link/dcl.array">[dcl.array]</a></span> Arrays<a href="#dcl.array-arrays" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: This
change is part of the resolution to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span>. ]</span></p>
<p>Use “host scope” in lieu of “inhabits” in paragraph 8:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_275" id="pnum_275">8</a></span>
Furthermore, if there is a reachable declaration of the entity that
<span class="rm" style="color: #bf0303"><del>inhabits</del></span> <span class="addu">has</span> the same <span class="addu">host</span> scope in
which the bound was specified, an omitted array bound is taken to be the
same as in that earlier declaration, and similarly for the definition of
a static data member of a class.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.fct-functions"><span>9.3.4.6 <a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span> Functions<a href="#dcl.fct-functions" class="self-link"></a></h3>
<p>Use “denoted by” instead of “named by” in paragraph 9 to be more
clear about the entity being referred to, and add a bullet to allow for
reflections of abominable function types:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_276" id="pnum_276">9</a></span>
A function type with a
<code class="sourceCode cpp"><em>cv-qualifier-seq</em></code> or a
<code class="sourceCode cpp"><em>ref-qualifier</em></code> (including a
type <span class="rm" style="color: #bf0303"><del>named</del></span>
<span class="addu">denoted</span> by
<code class="sourceCode cpp"><em>typedef-name</em></code>
([dcl.typedef], [temp.param])) shall appear only as:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_277" id="pnum_277">(9.1)</a></span>
the function type for a non-static member function,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_278" id="pnum_278">(9.2)</a></span>
the function type to which a pointer to member refers,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_279" id="pnum_279">(9.3)</a></span>
the top-level function type of a function typedef declaration or
<code class="sourceCode cpp"><em>alias-declaration</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_280" id="pnum_280">(9.4)</a></span>
the <code class="sourceCode cpp"><em>type-id</em></code> in the default
argument of a
<code class="sourceCode cpp"><em>type-parameter</em></code>
([temp.param]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_281" id="pnum_281">(9.5)</a></span>
the <code class="sourceCode cpp"><em>type-id</em></code> of a
<code class="sourceCode cpp"><em>template-argument</em></code> for a
<code class="sourceCode cpp"><em>type-parameter</em></code>
([temp.arg.type])<span class="rm" style="color: #bf0303"><del>.</del></span><span class="addu">,
or</span></li>
</ul>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_282" id="pnum_282">(9.6)</a></span>
the operand of a
<code class="sourceCode cpp"><em>reflect-expression</em></code>
([expr.reflect]).</li>
</ul>
</div>
</blockquote>
</div>
<p>Extend the example that follows to demonstrate taking the reflection
of an abominable function type:</p>
<div class="std">
<blockquote>
<div class="example4">
<span>[ <em>Example 4:</em> </span>
<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="kw">typedef</span> <span class="dt">int</span> FIC<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb148-2"><a href="#cb148-2" aria-hidden="true" tabindex="-1"></a>FIC f;                                          <span class="co">// error: does not declare a member function</span></span>
<span id="cb148-3"><a href="#cb148-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb148-4"><a href="#cb148-4" aria-hidden="true" tabindex="-1"></a>  FIC f;                                        <span class="co">// OK</span></span>
<span id="cb148-5"><a href="#cb148-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb148-6"><a href="#cb148-6" aria-hidden="true" tabindex="-1"></a>FIC S<span class="op">::*</span>pm <span class="op">=</span> <span class="op">&amp;</span>S<span class="op">::</span>f;                             <span class="co">// OK</span></span>
<span id="cb148-7"><a href="#cb148-7" aria-hidden="true" tabindex="-1"></a><span class="addu"><code class="sourceCode cpp"><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info r <span class="op">=</span> <span class="op">^^</span><span class="dt">void</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">&amp;</span>;    <span class="co">// OK</span></code></span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.fct.default-default-arguments"><span>9.3.4.7 <a href="https://wg21.link/dcl.fct.default">[dcl.fct.default]</a></span>
Default arguments<a href="#dcl.fct.default-default-arguments" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
changes related to “host scopes” in paragraphs 4 and 9 are part of the
resolution to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span>. ]</span></p>
<p>Use “host scope” in lieu of “inhabits” in paragraph 4:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_283" id="pnum_283">4</a></span>
For non-template functions, default arguments can be added in later
declarations of a function that <span class="rm" style="color: #bf0303"><del>inhabit</del></span> <span class="addu">have</span> the same <span class="addu">host</span> scope.
Declarations that <span class="rm" style="color: #bf0303"><del>inhabit</del></span> <span class="addu">have</span> different <span class="addu">host</span> scopes
have completely distinct sets of default arguments. […]</p>
</blockquote>
</div>
<p>Modify paragraph 9 to allow reflections of non-static data members to
appear in default function arguments, extend example 8 which follows,
and use “host scope” rather than “inhabits” following example 9.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_284" id="pnum_284">9</a></span>
A default argument is evaluated each time the function is called with no
argument for the corresponding parameter.</p>
<p>[…]</p>
<p>A non-static member shall not appear <span class="addu">or be
designated</span> in a default argument unless it appears as the
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span> of
a class member access expression ([expr.ref]) or unless it is used to
form a pointer to member ([expr.unary.op]) <span class="addu">or a
reflection ([expr.reflect])</span>.</p>
<div class="example8">
<p><span>[ <em>Example 8:</em> </span>The declaration of <code class="sourceCode cpp">X<span class="op">::</span>mem1<span class="op">()</span></code>
in the following example is ill-formed because no object is supplied for
the non-static member
<code class="sourceCode cpp">X<span class="op">::</span>a</code> used as
an initializer.</p>
<div class="sourceCode" id="cb149"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb149-1"><a href="#cb149-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> b;</span>
<span id="cb149-2"><a href="#cb149-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> X <span class="op">{</span></span>
<span id="cb149-3"><a href="#cb149-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> a;</span>
<span id="cb149-4"><a href="#cb149-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> mem1<span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> a<span class="op">)</span>;    <span class="co">// error: non-static member a used as default argument</span></span>
<span id="cb149-5"><a href="#cb149-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> mem2<span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> b<span class="op">)</span>;    <span class="co">// OK; use X::b</span></span>
<span id="cb149-6"><a href="#cb149-6" aria-hidden="true" tabindex="-1"></a>  <span class="addu"><code class="sourceCode cpp"><span class="kw">consteval</span> <span class="dt">void</span> mem3<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r <span class="op">=</span> <span class="op">^^</span>a<span class="op">)</span> <span class="op">{}</span>;    <span class="co">// OK</span></code></span></span>
<span id="cb149-7"><a href="#cb149-7" aria-hidden="true" tabindex="-1"></a>  <span class="addu"><code class="sourceCode cpp"><span class="dt">int</span> mem4<span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="op">[:^^</span>a<span class="op">:])</span>; <span class="co">// error: non-static member a designated in default argument</span></code></span></span>
<span id="cb149-8"><a href="#cb149-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb149-9"><a href="#cb149-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="dt">int</span> b;</span>
<span id="cb149-10"><a href="#cb149-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>[…]</p>
<p>When an overload set contains a declaration of a function <span class="rm" style="color: #bf0303"><del>that inhabits a</del></span>
<span class="addu">whose host</span> scope <span class="addu">is</span>
<code class="sourceCode cpp"><em>S</em></code>, any default argument
associated with any reachable declaration <span class="rm" style="color: #bf0303"><del>that inhabits</del></span> <span class="addu">whose host scope is</span>
<code class="sourceCode cpp"><em>S</em></code> is available to the
call.</p>
<p><span class="note7"><span>[ <em>Note 7:</em> </span>The candidate
might have been found through a
<code class="sourceCode cpp"><em>using-declarator</em></code> from which
the declaration that provides the default argument is not
reaachable.<span> — <em>end note</em> ]</span></span><span> — <em>end
example</em> ]</span></p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.init.general-initializers-general"><span>9.5.1 <a href="https://wg21.link/dcl.init.general">[dcl.init.general]</a></span>
Initializers (General)<a href="#dcl.init.general-initializers-general" class="self-link"></a></h3>
<p>Change paragraphs 6-8 of <span>9.5.1 <a href="https://wg21.link/dcl.init.general">[dcl.init.general]</a></span>
<span class="ednote" style="color: #0000ff">[ Editor&#39;s note: No changes
are necessary for value-initialization, which already forwards to
zero-initialization for scalar types ]</span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_285" id="pnum_285">6</a></span>
To <em>zero-initialize</em> an object or reference of type
<code class="sourceCode cpp">T</code> means:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_286" id="pnum_286">(6.0)</a></span>
<span class="addu">if <code class="sourceCode cpp">T</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
the object is initialized to a null reflection value;</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_287" id="pnum_287">(6.1)</a></span>
if <code class="sourceCode cpp">T</code> is <span class="rm" style="color: #bf0303"><del>a</del></span> <span class="addu">any
other</span> scalar type (<span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>),
the object is initialized to the value obtained by converting the
integer literal
<code class="sourceCode cpp"><span class="dv">0</span></code> (zero) to
<code class="sourceCode cpp">T</code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_288" id="pnum_288">(6.2)</a></span>
[…]</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_289" id="pnum_289">7</a></span>
To <em>default-initialize</em> an object of type
<code class="sourceCode cpp">T</code> means:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_290" id="pnum_290">(7.1)</a></span>
If <code class="sourceCode cpp">T</code> is a (possibly cv-qualified)
class type ([class]), […]</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_291" id="pnum_291">(7.2)</a></span>
If T is an array type, […]</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_292" id="pnum_292">(7.*)</a></span>
<span class="addu">If <code class="sourceCode cpp">T</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
the object is zero-initialized.</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_293" id="pnum_293">(7.3)</a></span>
Otherwise, no initialization is performed.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_294" id="pnum_294">8</a></span>
A class type <code class="sourceCode cpp">T</code> is
<em>const-default-constructible</em> if default-initialization of
<code class="sourceCode cpp">T</code> would invoke a user-provided
constructor of <code class="sourceCode cpp">T</code> (not inherited from
a base class) or if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_295" id="pnum_295">(8.1)</a></span>
[…]</li>
</ul>
<p>If a program calls for the default-initialization of an object of a
const-qualified type <code class="sourceCode cpp">T</code>,
<code class="sourceCode cpp">T</code> shall be <span class="addu"><code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
or</span> a const-default-constructible class type, or array
thereof.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_296" id="pnum_296">9</a></span>
To value-initialize an object of type T means: […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.fct.def.general-function-definitions"><span>9.6.1 <a href="https://wg21.link/dcl.fct.def.general">[dcl.fct.def.general]</a></span>
Function definitions<a href="#dcl.fct.def.general-function-definitions" class="self-link"></a></h3>
<p>Disallow using
<code class="sourceCode cpp"><span class="ot">__func__</span></code> in
a <code class="sourceCode cpp"><span class="kw">consteval</span></code>
block:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_297" id="pnum_297">7</a></span>
A <em>function-local predefined variable</em> is a variable with static
storage duration that is implicitly defined in a function parameter
scope<span class="addu">, other than the function parameter scope of the
expression corresponding to a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_298" id="pnum_298">8</a></span>
The function-local predefined variable
<code class="sourceCode cpp"><span class="ot">__func__</span></code> is
defined as if a definition of the form […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.fct.def.delete-deleted-definitions"><span>9.6.3 <a href="https://wg21.link/dcl.fct.def.delete">[dcl.fct.def.delete]</a></span>
Deleted definitions<a href="#dcl.fct.def.delete-deleted-definitions" class="self-link"></a></h3>
<p>Change paragraph 2 of <span>9.6.3 <a href="https://wg21.link/dcl.fct.def.delete">[dcl.fct.def.delete]</a></span>
to allow for reflections of deleted functions:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_299" id="pnum_299">2</a></span>
A program that refers to a deleted function implicitly or explicitly,
other than to declare it <span class="addu">or to use as the operand of
a <code class="sourceCode cpp"><em>reflect-expression</em></code>
([expr.reflect])</span>, is ill-formed.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="enum.udecl-the-using-enum-declaration"><span>9.8.2 <a href="https://wg21.link/enum.udecl">[enum.udecl]</a></span> The <code class="sourceCode cpp"><span class="kw">using</span> <span class="kw">enum</span></code>
declaration<a href="#enum.udecl-the-using-enum-declaration" class="self-link"></a></h3>
<p>Extend the grammar for
<code class="sourceCode cpp"><em>using-enum-declarator</em></code> as
follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb150"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb150-1"><a href="#cb150-1" aria-hidden="true" tabindex="-1"></a>  <em>using-enum-declaration</em>:</span>
<span id="cb150-2"><a href="#cb150-2" aria-hidden="true" tabindex="-1"></a>     using enum <em>using-enum-declarator</em> ;</span>
<span id="cb150-3"><a href="#cb150-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb150-4"><a href="#cb150-4" aria-hidden="true" tabindex="-1"></a>  <em>using-enum-declarator</em>:</span>
<span id="cb150-5"><a href="#cb150-5" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>identifier</em></span>
<span id="cb150-6"><a href="#cb150-6" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>simple-template-id</em></span>
<span id="cb150-7"><a href="#cb150-7" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-type-specifier</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Modify paragraph 1 to handle
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_300" id="pnum_300">1</a></span>
<span class="addu">A
<code class="sourceCode cpp"><em>using-enum-declarator</em></code> of
the form
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
designates the same construct designated by the
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>. Any
other</span> <span class="rm" style="color: #bf0303"><del>A</del></span>
<code class="sourceCode cpp"><em>using-enum-declarator</em></code> names
the set of declarations found by type-only lookup
([basic.lookup.general]) for the
<code class="sourceCode cpp"><em>using-enum-declarator</em></code>
(<span>6.5.3 <a href="https://wg21.link/basic.lookup.unqual">[basic.lookup.unqual]</a></span>,
<span>6.5.5 <a href="https://wg21.link/basic.lookup.qual">[basic.lookup.qual]</a></span>).
The <code class="sourceCode cpp"><em>using-enum-declarator</em></code>
shall designate a non-dependent type with a reachable
<code class="sourceCode cpp"><em>enum-specifier</em></code>.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="namespace.alias-namespace-alias"><span>9.9.3
<a href="https://wg21.link/namespace.alias">[namespace.alias]</a></span>
Namespace alias<a href="#namespace.alias-namespace-alias" class="self-link"></a></h3>
<p>Modify the grammar for
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
in paragraph 1, and clarify that such declarations declare a “namespace
alias” (which is now an entity as per [basic.pre]).</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_301" id="pnum_301">1</a></span>
A
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
declares <span class="rm" style="color: #bf0303"><del>an alternative
name for a namespace</del></span> <span class="addu">a namespace
alias</span> according to the following grammar:</p>
<div>
<div class="sourceCode" id="cb151"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb151-1"><a href="#cb151-1" aria-hidden="true" tabindex="-1"></a>  <em>namespace-alias</em>:</span>
<span id="cb151-2"><a href="#cb151-2" aria-hidden="true" tabindex="-1"></a>      <em>identifier</em></span>
<span id="cb151-3"><a href="#cb151-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb151-4"><a href="#cb151-4" aria-hidden="true" tabindex="-1"></a>  <em>namespace-alias-definition</em>:</span>
<span id="cb151-5"><a href="#cb151-5" aria-hidden="true" tabindex="-1"></a>      namespace <em>identifier</em> = <em>qualified-namespace-specifier</em></span>
<span id="cb151-6"><a href="#cb151-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     namespace <em>identifier</em> = <em>splice-specifier</em></span></span>
<span id="cb151-7"><a href="#cb151-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb151-8"><a href="#cb151-8" aria-hidden="true" tabindex="-1"></a>  <em>qualified-namespace-specifier</em>:</span>
<span id="cb151-9"><a href="#cb151-9" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>namespace-name</em></span></code></pre></div>
</div>
<p><span class="addu">The
<code class="sourceCode cpp"><em>splice-specifier</em></code> (if any)
shall designate a namespace other than the global namespace.</span></p>
</blockquote>
</div>
<p>Remove the details about what the
<code class="sourceCode cpp"><em>namespace-alias</em></code> denotes;
this will fall out from the “underlying entity” of the namespace alias
defined below:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_302" id="pnum_302">2</a></span>
The <code class="sourceCode cpp"><em>identifier</em></code> in a
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
becomes a <code class="sourceCode cpp"><em>namespace-alias</em></code>
<span class="rm" style="color: #bf0303"><del>and denotes the namespace
denoted by the
<span><code class="sourceCode default"><em>qualified-namespace-specifier</em></code></span></del></span>.</p>
</blockquote>
</div>
<p>Add the following paragraph after paragraph 2 and before the
note:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_303" id="pnum_303">2+</a></span>
The underlying entity (<span>6.1 <a href="https://wg21.link/basic.pre">[basic.pre]</a></span>) of the
namespace alias is the namespace either denoted by the
<code class="sourceCode cpp"><em>qualified-namespace-specifier</em></code>
or designated by the
<code class="sourceCode cpp"><em>splice-specifier</em></code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="namespace.udir-using-namespace-directive"><span>9.9.4 <a href="https://wg21.link/namespace.udir">[namespace.udir]</a></span>
Using namespace directive<a href="#namespace.udir-using-namespace-directive" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><em>splice-specifier</em></code> to
the grammar for
<code class="sourceCode cpp"><em>using-directive</em></code>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb152"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb152-1"><a href="#cb152-1" aria-hidden="true" tabindex="-1"></a>  <em>using-directive</em>:</span>
<span id="cb152-2"><a href="#cb152-2" aria-hidden="true" tabindex="-1"></a>      <em>attribute-specifier-seq</em><sub><em>opt</em></sub> using namespace <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>namespace-name</em></span>
<span id="cb152-3"><a href="#cb152-3" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>attribute-specifier-seq</em><sub><em>opt</em></sub> using namespace <em>splice-specifier</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add the following prior to the first paragraph of <span>9.9.4 <a href="https://wg21.link/namespace.udir">[namespace.udir]</a></span>, and
renumber accordingly:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_304" id="pnum_304">0</a></span>
The <code class="sourceCode cpp"><em>splice-specifier</em></code> (if
any) shall designate a namespace other than the global namespace. The
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<code class="sourceCode cpp"><em>namespace-name</em></code>, and
<code class="sourceCode cpp"><em>splice-specifier</em></code> shall not
be dependent.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_305" id="pnum_305">1</a></span>
A <code class="sourceCode cpp"><em>using-directive</em></code> shall not
appear in class scope, but may appear in namespace scope or in block
scope.</p>
<p>[…]</p>
</blockquote>
</div>
<p>Prefer the verb “designate” rather than “nominate” in the notes that
follow:</p>
<div class="std">
<blockquote>
<p><span class="note2"><span>[ <em>Note 2:</em> </span>A
<code class="sourceCode cpp"><em>using-directive</em></code> makes the
names in the <span class="rm" style="color: #bf0303"><del>nominated</del></span> <span class="addu">designated</span> namespace usable in the scope […]. During
unqualified name lookup, the names appear as if they were declared in
the nearest enclosing namespace which contains both the
<code class="sourceCode cpp"><em>using-directive</em></code> and the
<span class="rm" style="color: #bf0303"><del>nomindated</del></span>
<span class="addu">designated</span> namespace.<span> — <em>end
note</em> ]</span></span></p>
<p>[…]</p>
<p><span class="note4"><span>[ <em>Note 4:</em> </span>A
<code class="sourceCode cpp"><em>using-directive</em></code> is
transitive: if a scope contains a
<code class="sourceCode cpp"><em>using-directive</em></code> that <span class="rm" style="color: #bf0303"><del>nominates</del></span> <span class="addu">designates</span> a namespace that itself contains
<code class="sourceCode cpp"><em>using-directives</em></code>, the
namespaces <span class="rm" style="color: #bf0303"><del>nominated</del></span> <span class="addu">designated</span> by those
<code class="sourceCode cpp"><em>using-directives</em></code> are also
eligible to be considered.<span> — <em>end note</em> ]</span></span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.attr.grammar-attribute-syntax-and-semantics"><span>9.13.1 <a href="https://wg21.link/dcl.attr.grammar">[dcl.attr.grammar]</a></span>
Attribute syntax and semantics<a href="#dcl.attr.grammar-attribute-syntax-and-semantics" class="self-link"></a></h3>
<p>Add a production to the grammar for
<code class="sourceCode cpp"><em>attribute-specifier</em></code> as
follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb153"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb153-1"><a href="#cb153-1" aria-hidden="true" tabindex="-1"></a>  <em>attribute-specifier</em>:</span>
<span id="cb153-2"><a href="#cb153-2" aria-hidden="true" tabindex="-1"></a>     [ [ <em>attribute-using-prefix</em><sub><em>opt</em></sub> <em>attribute-list</em> ] ]</span>
<span id="cb153-3"><a href="#cb153-3" aria-hidden="true" tabindex="-1"></a><span class="va">+    [ [ using <em>attribute-namespace</em> :] ]</span></span>
<span id="cb153-4"><a href="#cb153-4" aria-hidden="true" tabindex="-1"></a>     <em>alignment-specifier</em></span></code></pre></div>
</div>
</blockquote>
</div>
<p>and update the grammar for balanced token as follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb154"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb154-1"><a href="#cb154-1" aria-hidden="true" tabindex="-1"></a>  <em>balanced-token</em> :</span>
<span id="cb154-2"><a href="#cb154-2" aria-hidden="true" tabindex="-1"></a>      ( <em>balanced-token-seq</em><sub><em>opt</em></sub> )</span>
<span id="cb154-3"><a href="#cb154-3" aria-hidden="true" tabindex="-1"></a>      [ <em>balanced-token-seq</em><sub><em>opt</em></sub> ]</span>
<span id="cb154-4"><a href="#cb154-4" aria-hidden="true" tabindex="-1"></a>      { <em>balanced-token-seq</em><sub><em>opt</em></sub> }</span>
<span id="cb154-5"><a href="#cb154-5" aria-hidden="true" tabindex="-1"></a><span class="st">-     any token other than a parenthesis, a bracket, or a brace</span></span>
<span id="cb154-6"><a href="#cb154-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     [: <em>balanced-token-seq</em><sub><em>opt</em></sub> :]</span></span>
<span id="cb154-7"><a href="#cb154-7" aria-hidden="true" tabindex="-1"></a><span class="va">+     any token other than (, ), [, ], {, }, [:, or :]</span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Change a sentence in paragraph 4 of <span>9.13.1 <a href="https://wg21.link/dcl.attr.grammar">[dcl.attr.grammar]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_306" id="pnum_306">4</a></span>
[…] An <code class="sourceCode cpp"><em>attribute-specifier</em></code>
that contains no <code class="sourceCode cpp"><em>attribute</em></code>s
<span class="addu">and no
<code class="sourceCode cpp"><em>alignment-specifier</em></code></span>
has no effect. <span class="addu"><span class="note"><span>[ <em>Note
1:</em> </span>That includes an
<code class="sourceCode cpp"><em>attribute-specifier</em></code> of the
form <code class="sourceCode cpp"><span class="op">[</span> <span class="op">[</span> <span class="kw">using</span> <em>attribute-namespace</em> <span class="op">:]</span> <span class="op">]</span></code>
which is thus equivalent to replacing the
<code class="sourceCode cpp"><span class="op">:]</span></code> token by
the two-token sequence
<code class="sourceCode cpp"><span class="op">:</span></code>
<code class="sourceCode cpp"><span class="op">]</span></code>.<span>
— <em>end note</em> ]</span></span></span> …</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.attr.deprecated-deprecated-attribute"><span>9.13.4 <a href="https://wg21.link/dcl.attr.deprecated">[dcl.attr.deprecated]</a></span>
Deprecated attribute<a href="#dcl.attr.deprecated-deprecated-attribute" class="self-link"></a></h3>
<p>Prefer “type alias” to
“<code class="sourceCode cpp"><em>typedef-name</em></code>” in paragraph
2.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_307" id="pnum_307">2</a></span>
The attribute may be applied to the declaration of a class, a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span>, a variable, a non-static data
member, a function, a namespace, an enumeration, an enumerator, a
concept, or a template specialization.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.attr.unused-maybe-unused-attribute"><span>9.13.8 <a href="https://wg21.link/dcl.attr.unused">[dcl.attr.unused]</a></span>
Maybe unused attribute<a href="#dcl.attr.unused-maybe-unused-attribute" class="self-link"></a></h3>
<p>Prefer “type alias” to
“<code class="sourceCode cpp"><em>typedef-name</em></code>” in paragraph
2.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_308" id="pnum_308">2</a></span>
The attribute may be applied to the declaration of a class, <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span>, variable (including a structured
binding declaration), structured binding, non-static data member,
function, enumeration, or enumerator, or to an
<code class="sourceCode cpp"><em>identifier</em></code> label (<span>8.2
<a href="https://wg21.link/stmt.label">[stmt.label]</a></span>).</p>
</blockquote>
</div>
<h3 class="unnumbered" id="module.global.frag-global-module-fragment"><span>10.4 <a href="https://wg21.link/module.global.frag">[module.global.frag]</a></span>
Global module fragment<a href="#module.global.frag-global-module-fragment" class="self-link"></a></h3>
<p>Specify in paragraph 3 that it is unspecified whether spliced types
are replaced by their designated types, and renumber accordingly. Add an
additional bullet further clarifying that it is unspecified whether any
splice specifier is replaced.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_309" id="pnum_309">3</a></span>
[…]</p>
<p>In this determination, it is unspecified</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_310" id="pnum_310">(3.6)</a></span>
whether a reference to an
<code class="sourceCode cpp"><em>alias-declaration</em></code>,
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
declaration,
<code class="sourceCode cpp"><em>using-declaration</em></code>, or
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
is replaced by the declarations they name prior to this
determination,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_311" id="pnum_311">(3.7)</a></span>
whether a
<code class="sourceCode cpp"><em>simple-template-id</em></code> that
does not denote a dependent type and whose
<code class="sourceCode cpp"><em>template-name</em></code> names an
alias template is replaced by its denoted type prior to this
determination,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_312" id="pnum_312">(3.8)</a></span>
whether a
<code class="sourceCode cpp"><em>decltype-specifier</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-type-specifier</em></code></span>
that does not <span class="rm" style="color: #bf0303"><del>denote</del></span> <span class="addu">designate</span> a dependent type is replaced by its <span class="rm" style="color: #bf0303"><del>denoted</del></span> <span class="addu">designated</span> type prior to this determination, <span class="rm" style="color: #bf0303"><del>and</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_313" id="pnum_313">(3.9)</a></span>
whether a non-value-dependent constant expression is replaced by the
result of constant evaluation prior to this determination<span class="rm" style="color: #bf0303"><del>.</del></span><span class="addu">, and</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_314" id="pnum_314">(3.10)</a></span>
whether a <code class="sourceCode cpp"><em>splice-specifier</em></code>
or <code class="sourceCode cpp"><em>splice-expression</em></code> that
is not dependent is replaced by the construct that it designates prior
to this determination.</span></li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="module.context-instantiation-context"><span>10.6 <a href="https://wg21.link/module.context">[module.context]</a></span>
Instantiation context<a href="#module.context-instantiation-context" class="self-link"></a></h3>
<p>Modify paragraphs 2 through 6 to relax the phrasing used to define
the points in the instantiation context, add a new paragraph to include
synthesized points in the instantiation context, and add a paragraph
clarifying that the context contains only these points.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_315" id="pnum_315">2</a></span>
During the implicit definition of a defaulted function ([special],
[class.compare.default]), the instantiation context <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">contains
each point in</span> the union of the instantiation context from the
definition of the class and the instantiation context of the program
construct that resulted in the implicit definition of the defaulted
function.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_316" id="pnum_316">3</a></span>
During the implicit instantiation of a template whose point of
instantiation is specified as that of an enclosing specialization
([temp.point]), the instantiation context <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">contains
each point in</span> <span class="rm" style="color: #bf0303"><del>the
union of</del></span> the instantiation context of the enclosing
specialization and, if the template is defined in a module interface
unit of a module <code class="sourceCode cpp"><em>M</em></code> and the
point of instantiation is not in a module interface unit of
<code class="sourceCode cpp"><em>M</em></code>, the point at the end of
the <code class="sourceCode cpp"><em>declaration-seq</em></code> of the
primary module interface unit of
<code class="sourceCode cpp"><em>M</em></code> (prior to the
<code class="sourceCode cpp"><em>private-module-fragment</em></code>, if
any).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_317" id="pnum_317">4</a></span>
During the implicit instantiation of a template that is implicitly
instantiated because it is referenced from within the implicit
definition of a defaulted function, the instantiation context <span class="rm" style="color: #bf0303"><del>is</del></span> <span class="addu">contains each point in</span> the instantiation context of
the defaulted function.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_318" id="pnum_318">5</a></span>
During the instantiation of any other template specialization, the
instantiation context <span class="rm" style="color: #bf0303"><del>comprises</del></span> <span class="addu">contains</span> the point of instantiation of the
template.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_319" id="pnum_319">6</a></span>
In any other case, the instantiation context at a point within the
program <span class="rm" style="color: #bf0303"><del>comprises</del></span> <span class="addu">contains</span> that point.</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_320" id="pnum_320">6+</a></span>
During the evaluation <code class="sourceCode cpp"><em>E</em></code> of
an expression, or during the implicit instantiation of any construct
that resulted from that evaluation, the instantiation context also
contains each synthesized point ([expr.const]) corresponding to an
injected declaration produced by any evaluation sequenced before
<code class="sourceCode cpp"><em>E</em></code> ([intro.execution]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_321" id="pnum_321">6++</a></span>
The instantiation context contains only those points specified
above.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="module.reach-reachability"><span>10.7 <a href="https://wg21.link/module.reach">[module.reach]</a></span>
Reachability<a href="#module.reach-reachability" class="self-link"></a></h3>
<p>Modify the definition of reachability to account for injected
declarations:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_322" id="pnum_322">3</a></span>
A declaration <code class="sourceCode cpp"><em>D</em></code> is
<em>reachable from</em> a point
<code class="sourceCode cpp"><em>P</em></code> if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_323" id="pnum_323">(3.1)</a></span>
<span class="addu"><code class="sourceCode cpp"><em>P</em></code> is not
a synthesized point and</span>
<code class="sourceCode cpp"><em>D</em></code> appears prior to
<code class="sourceCode cpp"><em>P</em></code> in the same translation
unit, <span class="rm" style="color: #bf0303"><del>or</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_324" id="pnum_324">(3.2)</a></span>
<span class="addu"><code class="sourceCode cpp"><em>D</em></code> is an
injected declaration for which
<code class="sourceCode cpp"><em>P</em></code> is the corresponding
synthesized point, or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_325" id="pnum_325">(3.3)</a></span>
<code class="sourceCode cpp"><em>D</em></code> is not discarded
(<span>10.4 <a href="https://wg21.link/module.global.frag">[module.global.frag]</a></span>),
appears in a translation unit that is reachable from
<code class="sourceCode cpp"><em>P</em></code>, and does not appear
within a <em>private-module-fragment</em>.</li>
</ul>
<div class="addu">
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb155"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb155-1"><a href="#cb155-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> S <span class="op">{</span></span>
<span id="cb155-2"><a href="#cb155-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> Incomplete;</span>
<span id="cb155-3"><a href="#cb155-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb155-4"><a href="#cb155-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* P1 */</span> <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb155-5"><a href="#cb155-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// OK, n == 7. The member Incomplete::x members-of-precedes the synthesized</span></span>
<span id="cb155-6"><a href="#cb155-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// point P2 associated with the injected declaration produced by the call to</span></span>
<span id="cb155-7"><a href="#cb155-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// define_aggregate.</span></span>
<span id="cb155-8"><a href="#cb155-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> n <span class="op">=</span> members_of<span class="op">(</span></span>
<span id="cb155-9"><a href="#cb155-9" aria-hidden="true" tabindex="-1"></a>        define_aggregate<span class="op">(^^</span>Incomplete, <span class="op">{</span>data_member_spec<span class="op">(^^</span><span class="dt">int</span>, <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;x&quot;</span><span class="op">})})</span>,</span>
<span id="cb155-10"><a href="#cb155-10" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span></span>
<span id="cb155-11"><a href="#cb155-11" aria-hidden="true" tabindex="-1"></a>      <span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb155-12"><a href="#cb155-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb155-13"><a href="#cb155-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>; <span class="co">/* P2 */</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="class.mem.general-general"><span>11.4.1 <a href="https://wg21.link/class.mem.general">[class.mem.general]</a></span>
General<a href="#class.mem.general-general" class="self-link"></a></h3>
<p>Modify the grammar for
<code class="sourceCode cpp"><em>member-declaration</em></code> as
follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb156"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb156-1"><a href="#cb156-1" aria-hidden="true" tabindex="-1"></a>  <em>member-declaration</em>:</span>
<span id="cb156-2"><a href="#cb156-2" aria-hidden="true" tabindex="-1"></a>    <em>attribute-specifier-seq</em><sub>opt</sub> <em>decl-specifier-seq</em><sub>opt</sub> <em>member-declarator-list</em><sub>opt</sub>;</span>
<span id="cb156-3"><a href="#cb156-3" aria-hidden="true" tabindex="-1"></a>    <em>function-definition</em></span>
<span id="cb156-4"><a href="#cb156-4" aria-hidden="true" tabindex="-1"></a>    <em>friend-type-declaration</em></span>
<span id="cb156-5"><a href="#cb156-5" aria-hidden="true" tabindex="-1"></a>    <em>using-declaration</em></span>
<span id="cb156-6"><a href="#cb156-6" aria-hidden="true" tabindex="-1"></a>    <em>using-enum-declaration</em></span>
<span id="cb156-7"><a href="#cb156-7" aria-hidden="true" tabindex="-1"></a><span class="st">-   <em>static_assert-declaration</em></span></span>
<span id="cb156-8"><a href="#cb156-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>vacuous-declaration</em></span></span>
<span id="cb156-9"><a href="#cb156-9" aria-hidden="true" tabindex="-1"></a>    <em>template-declaration</em></span>
<span id="cb156-10"><a href="#cb156-10" aria-hidden="true" tabindex="-1"></a>    <em>explicit-specialization</em></span>
<span id="cb156-11"><a href="#cb156-11" aria-hidden="true" tabindex="-1"></a>    <em>deduction-guide</em></span>
<span id="cb156-12"><a href="#cb156-12" aria-hidden="true" tabindex="-1"></a>    <em>alias-declaration</em></span>
<span id="cb156-13"><a href="#cb156-13" aria-hidden="true" tabindex="-1"></a>    <em>opaque-enum-declaration</em></span>
<span id="cb156-14"><a href="#cb156-14" aria-hidden="true" tabindex="-1"></a>    <em>empty-declaration</em></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Update paragraph 4 accordingly:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_326" id="pnum_326">4</a></span>
A <code class="sourceCode cpp"><em>member-declaration</em></code> does
not declare new members of the class if it is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_327" id="pnum_327">(4.1)</a></span>
a friend declaration ([class.friend]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_328" id="pnum_328">(4.2)</a></span>
a <code class="sourceCode cpp"><em>deduction-guide</em></code>
([temp.deduct.guide]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_329" id="pnum_329">(4.3)</a></span>
a <code class="sourceCode cpp"><em>template-declaration</em></code>
whose declaration is one of the above,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_330" id="pnum_330">(4.4)</a></span>
a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>static_assert-declaration</em></code></span>,</del></span>
<span class="addu"><code class="sourceCode cpp"><em>vacuous-declaration</em></code></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_331" id="pnum_331">(4.5)</a></span>
a <code class="sourceCode cpp"><em>using-declaration</em></code>
([namespace.udecl]) , or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_332" id="pnum_332">(4.6)</a></span>
an <code class="sourceCode cpp"><em>empty-declaration</em></code>.</li>
</ul>
</blockquote>
</div>
<p>Extend paragraph 6, and modify note 3, to clarify the existence of
subobjects corresponding to non-static data members of reference
types.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_333" id="pnum_333">6</a></span>
A data member or member function may be declared
<code class="sourceCode cpp"><span class="kw">static</span></code> in
its <code class="sourceCode cpp"><em>member-declaration</em></code>, in
which case it is a <em>static member</em> (see [class.static]) (a
<em>static data member</em> ([class.static.data]) or <em>static member
function</em> ([class.static.mfct]), respectively) of the class. Any
other data member or member function is a <em>non-static member</em> (a
<em>non-static data member</em> or <em>non-static member function</em>
([class.mfct.non.static]), respectively). <span class="addu">The
<em>layout-associated type</em> of a non-static data member is
<code class="sourceCode cpp"><em>T</em><span class="op">*</span></code>
if it has type
<code class="sourceCode cpp"><em>T</em><span class="op">&amp;</span></code>
or <code class="sourceCode cpp"><em>T</em><span class="op">&amp;&amp;</span></code>
and the type of the member otherwise. For layout purposes, it is as if
the member were declared with its layout-associated type.</span></p>
<div class="rm" style="color: #bf0303">
<p><span class="note3"><span>[ <em>Note 3:</em> </span>A non-static data
member of non-reference type is a member subobject of a class
object.<span> — <em>end note</em> ]</span></span></p>
</div>
</blockquote>
</div>
<p>Add a new paragraph to the end of the section defining <em>data
member description</em>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_334" id="pnum_334">30+</a></span>
A <em>data member description</em> is a quintuple
(<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) describing the
potential declaration of a nonstatic data member where</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_335" id="pnum_335">(30+.1)</a></span>
<code class="sourceCode cpp"><em>T</em></code> is a type or type
alias,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_336" id="pnum_336">(30+.2)</a></span>
<code class="sourceCode cpp"><em>N</em></code> is an
<code class="sourceCode cpp"><em>identifier</em></code> or ⊥,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_337" id="pnum_337">(30+.3)</a></span>
<code class="sourceCode cpp"><em>A</em></code> is an alignment or
⊥,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_338" id="pnum_338">(30+.4)</a></span>
<code class="sourceCode cpp"><em>W</em></code> is a bit-field width or
⊥, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_339" id="pnum_339">(30+.5)</a></span>
<code class="sourceCode cpp"><em>NUA</em></code> is a boolean
value.</li>
</ul>
<p>Two data member descriptions are equal if each of their respective
components are same types, same identifiers, and equal values.</p>
<div class="note">
<p><span>[ <em>Note 4:</em> </span>The components of a data member
description describe a data member such that</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_340" id="pnum_340">(30+.6)</a></span>
its type is specified using the type or type alias given by
<code class="sourceCode cpp"><em>T</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_341" id="pnum_341">(30+.7)</a></span>
it is declared with the name given by
<code class="sourceCode cpp"><em>N</em></code> if
<code class="sourceCode cpp"><em>N</em></code> does not equal ⊥ and is
otherwise unnamed,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_342" id="pnum_342">(30+.8)</a></span>
it is declared with the
<code class="sourceCode cpp"><em>alignment-specifier</em></code>
(<span>9.13.2 <a href="https://wg21.link/dcl.align">[dcl.align]</a></span>) given by
<code class="sourceCode cpp"><span class="kw">alignas</span><span class="op">(</span><em>A</em><span class="op">)</span></code>
if <code class="sourceCode cpp"><em>A</em></code> does not equal ⊥ and
is otherwise declared without an
<code class="sourceCode cpp"><em>alignment-specifier</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_343" id="pnum_343">(30+.9)</a></span>
it is a bit-field (<span>11.4.10 <a href="https://wg21.link/class.bit">[class.bit]</a></span>) with the
width given by <code class="sourceCode cpp"><em>W</em></code> if
<code class="sourceCode cpp"><em>W</em></code> does not equal ⊥ and is
otherwise not a bit-field,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_344" id="pnum_344">(30+.10)</a></span>
it is declared with the attribute <code class="sourceCode cpp"><span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></code>
(<span>9.13.11 <a href="https://wg21.link/dcl.attr.nouniqueaddr">[dcl.attr.nouniqueaddr]</a></span>)
if <code class="sourceCode cpp"><em>NUA</em></code> is
<code class="sourceCode cpp"><span class="kw">true</span></code> and is
otherwise declared without that attribute.</li>
</ul>
<p>Data member descriptions are represented by reflections (<span>6.8.2
<a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>)
returned by <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>data_member_spec</code>
([meta.reflection.define.aggregate]) and can be reified as data members
of a class using <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_aggregate</code>
([meta.reflection.define.aggregate]).<span> — <em>end
note</em> ]</span></p>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="class.union.anon-anonymous-unions"><span>11.5.2 <a href="https://wg21.link/class.union.anon">[class.union.anon]</a></span>
Anonymous unions<a href="#class.union.anon-anonymous-unions" class="self-link"></a></h3>
<p>Replace
<code class="sourceCode cpp"><em>static_assert-declaration</em></code>
with <code class="sourceCode cpp"><em>vacuous-declaration</em></code> in
paragraph 1.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_345" id="pnum_345">1</a></span>
[…] Each <code class="sourceCode cpp"><em>member-declaration</em></code>
in the <code class="sourceCode cpp"><em>member-specification</em></code>
of an anonymous union shall either define one or more public non-static
data members or be a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>static_assert-declaration</em></code></span></del></span>
<span class="addu"><code class="sourceCode cpp"><em>vacuous-declaration</em></code></span>.
[…]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="class.derived.general-general"><span>11.7.1
<a href="https://wg21.link/class.derived.general">[class.derived.general]</a></span>
General<a href="#class.derived.general-general" class="self-link"></a></h3>
<p>Introduce the term “direct base class relationship” to paragraph
2.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_346" id="pnum_346">2</a></span>
The component names of a
<code class="sourceCode cpp"><em>class-or-decltype</em></code> are those
of its
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<code class="sourceCode cpp"><em>type-name</em></code>, and/or
<code class="sourceCode cpp"><em>simple-template-id</em></code>. A
<code class="sourceCode cpp"><em>class-or-decltype</em></code> shall
denote a (possily cv-qualified) class type that is not an incompletely
defined class (<span>11.4 <a href="https://wg21.link/class.mem">[class.mem]</a></span>); any
cv-qualifiers are ignored. The class denoted by the
<code class="sourceCode cpp"><em>class-or-decltype</em></code> of a
<code class="sourceCode cpp"><em>base-specifier</em></code> is called a
<em>direct base class</em> for the class being defined<span class="addu">; each such
<code class="sourceCode cpp"><em>base-specifier</em></code> introduces a
<em>direct base class relationship</em> between the class being defined
and the direct base class</span>. The lookup for the component name of
the <code class="sourceCode cpp"><em>type-name</em></code> or
<code class="sourceCode cpp"><em>simple-template-id</em></code> is
type-only (<span>6.5 <a href="https://wg21.link/basic.lookup">[basic.lookup]</a></span>).
[…]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="class.access.general-general"><span>11.8.1 <a href="https://wg21.link/class.access.general">[class.access.general]</a></span>
General<a href="#class.access.general-general" class="self-link"></a></h3>
<p>Prefer “type alias” rather than
<code class="sourceCode cpp"><em>typedef-name</em></code> in the note
that follows paragraph 4.</p>
<div class="std">
<blockquote>
<p><span class="note3"><span>[ <em>Note 3:</em> </span>Because access
control applies to the declarations named, if access control is applied
to a <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">type alias</span>, only the accessibility of the
typedef or alias declaration itself is considered. The accessibility of
the <span class="rm" style="color: #bf0303"><del>entity referred to by
the
<span><code class="sourceCode default"><em>typedef-name</em></code></span></del></span>
<span class="addu">underlying entity</span> is not considered.<span>
— <em>end note</em> ]</span></span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="class.access.base-accessibility-of-base-classes-and-base-class-members"><span>11.8.3
<a href="https://wg21.link/class.access.base">[class.access.base]</a></span>
Accessibility of base classes and base class members<a href="#class.access.base-accessibility-of-base-classes-and-base-class-members" class="self-link"></a></h3>
<p>Update paragraph 5 to handle
<code class="sourceCode cpp"><em>splice-expression</em></code>s, and to
make more clear that the “naming class” (renamed “designating class”
here) is a property of the expression. State explicitly that members
designated through
<code class="sourceCode cpp"><em>splice-expression</em></code>s are
accessible.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_347" id="pnum_347">5</a></span>
[…]</p>
<p><span class="rm" style="color: #bf0303"><del>The access to a member
is affected by the class in which the member is named. This naming class
is the</del></span> <span class="addu">An expression
<code class="sourceCode cpp">E</code> that designates a member
<code class="sourceCode cpp">m</code> has a <em>designating class</em>
that affects the access to <code class="sourceCode cpp">m</code>. This
designating class is either</span></p>
<ul>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_348" id="pnum_348">(5.1)</a></span>
the innermost class of which <code class="sourceCode cpp">m</code> is
directly a member if <code class="sourceCode cpp">E</code> is a
<code class="sourceCode cpp"><em>splice-expression</em></code>
or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_349" id="pnum_349">(5.2)</a></span>
<span class="addu">the</span> class in whose scope lookup performed a
search that found <span class="addu"><code class="sourceCode cpp">m</code></span> <span class="rm" style="color: #bf0303"><del>the member</del></span> <span class="addu">otherwise</span>.</li>
</ul>
<p><span class="note3"><span>[ <em>Note 3:</em> </span>This class can be
explicit, e.g., when a
<code class="sourceCode cpp"><em>qualified-id</em></code> is used, or
implicit, e.g., when a class member access operator ([expr.ref]) is used
(including cases where an implicit “<code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;</span></code>”
was added). If both a class member access operator and a
<code class="sourceCode cpp"><em>qualified-id</em></code> are used to
<span class="rm" style="color: #bf0303"><del>name</del></span> <span class="addu">designate</span> the member (as in <code class="sourceCode cpp">p<span class="op">-&gt;</span>T<span class="op">::</span>m</code>),
the class <span class="rm" style="color: #bf0303"><del>naming</del></span> <span class="addu">designating</span> the member is the class denoted by the
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> of
the <code class="sourceCode cpp"><em>qualified-id</em></code> (that is,
<code class="sourceCode cpp">T</code>).<span> — <em>end
note</em> ]</span></span></p>
<p>A member <code class="sourceCode cpp">m</code> is accessible at the
point <code class="sourceCode cpp"><em>R</em></code> when <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span> in class
<code class="sourceCode cpp">N</code> if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_350" id="pnum_350">(5.3)</a></span>
<code class="sourceCode cpp">m</code> as a member of
<code class="sourceCode cpp">N</code> is public, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_351" id="pnum_351">(5.4)</a></span>
<code class="sourceCode cpp">m</code> as a member of
<code class="sourceCode cpp">N</code> is private, and
<code class="sourceCode cpp"><em>R</em></code> occurs in a direct member
or friend of class <code class="sourceCode cpp"><em>N</em></code>,
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_352" id="pnum_352">(5.5)</a></span>
<code class="sourceCode cpp">m</code> as a member of
<code class="sourceCode cpp">N</code> is protected, and
<code class="sourceCode cpp"><em>R</em></code> occurs in a direct member
or friend of class <code class="sourceCode cpp"><em>N</em></code>, or in
a member of a class <code class="sourceCode cpp">P</code> derived from
<code class="sourceCode cpp">N</code>, where
<code class="sourceCode cpp">m</code> as a member of
<code class="sourceCode cpp">P</code> is public, private, or protected,
or</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_353" id="pnum_353">(5.6)</a></span>
<code class="sourceCode cpp">m</code> is designated by a
<code class="sourceCode cpp"><em>splice-expression</em></code>,
or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_354" id="pnum_354">(5.7)</a></span>
there exists a base class <code class="sourceCode cpp">B</code> of
<code class="sourceCode cpp">N</code> that is accessible at
<code class="sourceCode cpp"><em>R</em></code>, and
<code class="sourceCode cpp">m</code> is accessible at
<code class="sourceCode cpp"><em>R</em></code> when <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span> in class
<code class="sourceCode cpp">B</code>.</li>
</ul>
</blockquote>
</div>
<p>Update paragraph 6, and the note which follows, to use the term
“designated class”:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_355" id="pnum_355">6</a></span>
If a class member access operator, including an implicit “<code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;</span></code>”,
is used to access a non-static data member or non-static member
function, the reference is ill-formed if the left operand (considered as
a pointer in the
“<code class="sourceCode cpp"><span class="op">.</span></code>” case)
cannot be implicitly converted to a pointer to the <span class="rm" style="color: #bf0303"><del>naming</del></span> <span class="addu">designating</span> class of the right operand.</p>
<p><span class="note"><span>[ <em>Note 4:</em> </span>This requirement
is in addition to the requirement that the member be accessible as <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span>.<span> — <em>end
note</em> ]</span></span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="over.pre-preamble"><span>12.1 <a href="https://wg21.link/over.pre">[over.pre]</a></span> Preamble<a href="#over.pre-preamble" class="self-link"></a></h3>
<p>Add a note explaining the expressions that form overload sets after
paragraph 2.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_356" id="pnum_356">2</a></span>
When a function is named <span class="addu">or designated</span> in a
call, which function declaration is being referenced and the validity of
the call are determined by comparing the types of the arguments at the
point of use with the types of the parameters in the declarations in the
overload set. This function selection process is called <em>overload
resolution</em> and is defined in [over.match].</p>
<p><span class="addu"><span class="note"><span>[ <em>Note 1:</em>
</span>Overload sets are formed by
<code class="sourceCode cpp"><em>id-expression</em></code>s naming
functions and function templates and by
<code class="sourceCode cpp"><em>splice-expression</em></code>s
designating entities of the same kinds.<span> — <em>end
note</em> ]</span></span></span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="over.call.func-call-to-named-function"><span>12.2.2.2.2 <a href="https://wg21.link/over.call.func">[over.call.func]</a></span> Call
to named function<a href="#over.call.func-call-to-named-function" class="self-link"></a></h3>
<p>Change the section title:</p>
<div class="std">
<blockquote>
<h3 id="call-to-named-designated-function">Call to <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span> function<a href="#call-to-named-designated-function" class="self-link"></a></h3>
</blockquote>
</div>
<p>Modify paragraph 1 to clarify that this section will also apply to
splices of function templates.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_357" id="pnum_357">1</a></span>
Of interest in [over.call.func] are only those function calls in which
the <code class="sourceCode cpp"><em>posfix-expression</em></code>
ultimately contains an
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
that denotes one or more functions. Such a
<code class="sourceCode cpp"><em>postfix-expression</em></code>, perhaps
nested arbitrarily deep in parentheses, has one of the following
forms:</p>
<div>
<div class="sourceCode" id="cb157"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb157-1"><a href="#cb157-1" aria-hidden="true" tabindex="-1"></a>  <em>postfix-expression</em>:</span>
<span id="cb157-2"><a href="#cb157-2" aria-hidden="true" tabindex="-1"></a>     <em>postfix-expression</em> . <em>id-expression</em></span>
<span id="cb157-3"><a href="#cb157-3" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>postfix-expression</em> . <em>splice-expression</em></span></span>
<span id="cb157-4"><a href="#cb157-4" aria-hidden="true" tabindex="-1"></a>     <em>postfix-expression</em> -&gt; <em>id-expression</em></span>
<span id="cb157-5"><a href="#cb157-5" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>postfix-expression</em> -&gt; <em>splice-expression</em></span></span>
<span id="cb157-6"><a href="#cb157-6" aria-hidden="true" tabindex="-1"></a>     <em>primary-expression</em></span></code></pre></div>
</div>
<p>These represent two syntactic subcategories of function calls:
qualified function calls and unqualified function calls.</p>
</blockquote>
</div>
<p>Modify paragraph 2 to account for overload resolution of
<code class="sourceCode cpp"><em>splice-expression</em></code>s. Massage
the wording to better account for member function templates.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_358" id="pnum_358">2</a></span>
In qualified function calls, the function is <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span> by an
<code class="sourceCode cpp"><em>id-expression</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-expression</em></code></span>
preceded by an
<code class="sourceCode cpp"><span class="op">-&gt;</span></code> or
<code class="sourceCode cpp"><span class="op">.</span></code> operator.
Since the construct
<code class="sourceCode cpp">A<span class="op">-&gt;</span>B</code> is
generally equivalent to <code class="sourceCode cpp"><span class="op">(*</span>A<span class="op">).</span>B</code>,
the rest of [over] assumes, without loss of generality, that all member
function calls have been normalized to the form that uses an object and
the <code class="sourceCode cpp"><span class="op">.</span></code>
operator. Furthermore, [over] assumes that the
<code class="sourceCode cpp"><em>postfix-expression</em></code> that is
the left operand of the
<code class="sourceCode cpp"><span class="op">.</span></code> operator
has type “<em>cv</em> <code class="sourceCode cpp">T</code>” where
<code class="sourceCode cpp">T</code> denotes a class.<sup>102</sup>
<span class="rm" style="color: #bf0303"><del>The</del></span> <span class="addu">A set of</span> function declarations<span class="addu">,
either</span> found by name lookup ([class.member.lookup]) <span class="addu">if the dot is followed by an
<code class="sourceCode cpp"><em>id-expression</em></code>, or
determined as specified in [expr.prim.splice] if followed by a
<code class="sourceCode cpp"><em>splice-expression</em></code>,</span>
constitute the set of candidate functions. The argument list is the
<code class="sourceCode cpp"><em>expression-list</em></code> in the call
augmented by the addition of the left operand of the
<code class="sourceCode cpp"><span class="op">.</span></code> operator
in the normalized member function call as the implied object argument
(<span>12.2.2 <a href="https://wg21.link/over.match.funcs">[over.match.funcs]</a></span>).</p>
</blockquote>
</div>
<p>Modify paragraph 3 to account for overload resolution of
<code class="sourceCode cpp"><em>splice-expression</em></code>s. Massage
the wording to better account for member function templates.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_359" id="pnum_359">3</a></span>
In unqualified function calls, the function is <span class="rm" style="color: #bf0303"><del>named</del></span> <span class="addu">designated</span> by a
<code class="sourceCode cpp"><em>primary-expression</em></code> <span class="addu">(call it
<code class="sourceCode cpp"><em>E</em></code>)</span>. <span class="rm" style="color: #bf0303"><del>The</del></span> <span class="addu">A set
of</span> function declarations<span class="addu">, either</span> found
by name lookup ([basic.lookup]) <span class="addu">if
<code class="sourceCode cpp"><em>E</em></code> is a (possibly
parenthesized)
<code class="sourceCode cpp"><em>id-expression</em></code>, or
determined as specified in [expr.prim.splice] if
<code class="sourceCode cpp"><em>E</em></code> is a (possibly
parenthesized)
<code class="sourceCode cpp"><em>splice-expression</em></code>,</span>
constitute the set of candidate functions. Because of the rules for name
lookup, the set of candidate functions consists either entirely of
non-member functions or entirely of member functions of some class
<code class="sourceCode cpp">T</code>. In the former case or if <span class="rm" style="color: #bf0303"><del>the
<span><code class="sourceCode default"><em>primary-expression</em></code></span></del></span>
<span class="addu"><code class="sourceCode cpp"><em>E</em></code></span>
is <span class="addu">either a
<code class="sourceCode cpp"><em>splice-expression</em></code> or</span>
the address of an overload set, the argument list is the same as the
<code class="sourceCode cpp"><em>expression-list</em></code> in the
call. Otherwise, the argument list is the
<code class="sourceCode cpp"><em>expression-list</em></code> in the call
augmented by the addition of an implied function argument as in a
qualified function call. If the current class is, or is derived from,
<code class="sourceCode cpp">T</code>, and the keyword
<code class="sourceCode cpp"><span class="kw">this</span></code>
(<span>7.5.3 <a href="https://wg21.link/expr.prim.this">[expr.prim.this]</a></span>)
refers to it, then the implied object argument is <code class="sourceCode cpp"><span class="op">(*</span><span class="kw">this</span><span class="op">)</span></code>.
Otherwise, a contrived object of type
<code class="sourceCode cpp">T</code> becomes the implied object
argument;<sup>103</sup> if overload resolution selects a non-static
member function, the call is ill-formed.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="over.match.class.deduct-class-template-argument-deduction"><span>12.2.2.9
<a href="https://wg21.link/over.match.class.deduct">[over.match.class.deduct]</a></span>
Class template argument deduction<a href="#over.match.class.deduct-class-template-argument-deduction" class="self-link"></a></h3>
<p>Extend paragraph 1 to work with
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_360" id="pnum_360">1</a></span>
When resolving a placeholder for a deduced class type (<span>9.2.9.8 <a href="https://wg21.link/dcl.type.class.deduct">[dcl.type.class.deduct]</a></span>)
where the <code class="sourceCode cpp"><em>template-name</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-type-specifier</em></code></span>
<span class="rm" style="color: #bf0303"><del>names</del></span> <span class="addu">designates</span> a primary class template
<code class="sourceCode cpp">C</code>, a set of functions and function
templates, called the guides of <code class="sourceCode cpp">C</code>,
is formed comprising:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_361" id="pnum_361">(1.1)</a></span>
…</li>
</ul>
</blockquote>
</div>
<p>Extend paragraph 3 to also cover
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_362" id="pnum_362">3</a></span>
When resolving a placeholder for a deduced class type (<span>9.2.9.3 <a href="https://wg21.link/dcl.type.simple">[dcl.type.simple]</a></span>)
where the <code class="sourceCode cpp"><em>template-name</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-type-specifier</em></code></span>
<span class="rm" style="color: #bf0303"><del>names</del></span> <span class="addu">designates</span> an alias template
<code class="sourceCode cpp">A</code>, the
<code class="sourceCode cpp"><em>defining-type-id</em></code> of
<code class="sourceCode cpp">A</code> must be of the form</p>
<div class="sourceCode" id="cb158"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb158-1"><a href="#cb158-1" aria-hidden="true" tabindex="-1"></a>typename<sub><em>opt</em></sub> <em>nested-name-specifier</em><sub><em>opt</em></sub> template<sub><em>opt</em></sub> <em>simple-template-id</em></span></code></pre></div>
<p>as specified in <span>9.2.9.3 <a href="https://wg21.link/dcl.type.simple">[dcl.type.simple]</a></span>.
The guides of <code class="sourceCode cpp">A</code> are the set of
functions or function templates formed as follows. …</p>
</blockquote>
</div>
<h3 class="unnumbered" id="over.match.viable-viable-functions"><span>12.2.3 <a href="https://wg21.link/over.match.viable">[over.match.viable]</a></span>
Viable functions<a href="#over.match.viable-viable-functions" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
changes to paragraph 2.3 (except for the wording related to
<code class="sourceCode default"><em>splice-expression</em>s</code>) are
a part of the resolution to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span>. These changes render
[over.match.best.general]/4 redundant, hence the relocation of its
associated example to this section. ]</span></p>
<p>Specify rules for overload sets denoted by
<code class="sourceCode cpp"><em>splice-expression</em></code>s in
paragraph 2, make drive-by fixes to help clear up the situation more
generally, and move the example that formerly followed
[over.match.best.general]/4 to follow after paragraph 2 (with a new
example covering
<code class="sourceCode cpp"><em>splice-expression</em></code>s).</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_363" id="pnum_363">2</a></span>
First, to be a viable function, a candidate function shall have enough
parameters to agree in number with the arguments in the list.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_364" id="pnum_364">(2.1)</a></span>
If there are <code class="sourceCode cpp"><em>m</em></code> arguments in
the lists, all candidate functions having exactly
<code class="sourceCode cpp"><em>m</em></code> parameters are
viable.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_365" id="pnum_365">(2.2)</a></span>
A candidate function having fewer than
<code class="sourceCode cpp"><em>m</em></code> parameters is viable only
if it has an ellipsis in its parameter list ([dcl.fct]). For the
purposes of overload resolution, any argument for which there is no
corresponding parameter is considered to “match the ellipsis”
([over.ics.ellipsis]).</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_366" id="pnum_366">(2.3)</a></span>
A candidate function having more than
<code class="sourceCode cpp"><em>m</em></code> parameters is viable only
if <span class="addu">there is a declaration
<code class="sourceCode cpp"><em>D</em></code> considered by the
overload resolution such that for each</span> <span class="rm" style="color: #bf0303"><del>all</del></span> parameter<span class="rm" style="color: #bf0303"><del>s</del></span> following the
<code class="sourceCode cpp"><em>m</em><sup>th</sup></code> <span class="rm" style="color: #bf0303"><del>have default
arguments</del></span><span class="addu">, a reachable declaration whose
host scope is the same as that of
<code class="sourceCode cpp"><em>D</em></code> specifies a default
argument for that parameter</span> ([dcl.fct.default]). <span class="addu">If the candidate function is selected as the best viable
function, no other host scope of a declaration considered by overload
resolution shall be the host scope of a declaration that specifies a
default argument for the
(<code class="sourceCode cpp"><em>m</em></code>+1)<sup><em>st</em></sup>
parameter; the host scope of
<code class="sourceCode cpp"><em>D</em></code> shall not be a block
scope if the declarations considered by overload resolution were denoted
by a <code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice]). The default arguments used in a call to the
selected function are the default arguments introduced in the host scope
of <code class="sourceCode cpp"><em>D</em></code>.</span> For the
purposes of overload resolution, the parameter list is truncated on the
right, so that there are exactly
<code class="sourceCode cpp"><em>m</em></code> parameters.</li>
</ul>
<div class="addu">
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb159"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb159-1"><a href="#cb159-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> A <span class="op">{</span></span>
<span id="cb159-2"><a href="#cb159-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span> <span class="op">=</span> <span class="dv">5</span><span class="op">)</span>;</span>
<span id="cb159-3"><a href="#cb159-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb159-4"><a href="#cb159-4" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> B <span class="op">{</span></span>
<span id="cb159-5"><a href="#cb159-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">extern</span> <span class="st">&quot;C&quot;</span> <span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span> <span class="op">=</span> <span class="dv">5</span><span class="op">)</span>;</span>
<span id="cb159-6"><a href="#cb159-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb159-7"><a href="#cb159-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb159-8"><a href="#cb159-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> splice<span class="op">()</span> <span class="op">{</span></span>
<span id="cb159-9"><a href="#cb159-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">[:^^</span>A<span class="op">::</span>f<span class="op">:](</span><span class="dv">3</span><span class="op">)</span>;  <span class="co">// OK, default argument was not used for viability</span></span>
<span id="cb159-10"><a href="#cb159-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">[:^^</span>A<span class="op">::</span>f<span class="op">:]()</span>;   <span class="co">// error: found default argument twice</span></span>
<span id="cb159-11"><a href="#cb159-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb159-12"><a href="#cb159-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb159-13"><a href="#cb159-13" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> A<span class="op">::</span>f;</span>
<span id="cb159-14"><a href="#cb159-14" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> B<span class="op">::</span>f;</span>
<span id="cb159-15"><a href="#cb159-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb159-16"><a href="#cb159-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> use<span class="op">()</span> <span class="op">{</span></span>
<span id="cb159-17"><a href="#cb159-17" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span><span class="dv">3</span><span class="op">)</span>;           <span class="co">// OK, default argument was not used for viability</span></span>
<span id="cb159-18"><a href="#cb159-18" aria-hidden="true" tabindex="-1"></a>  f<span class="op">()</span>;            <span class="co">// error: found default argument twice</span></span>
<span id="cb159-19"><a href="#cb159-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="over.match.best.general-general"><span>12.2.4.1 <a href="https://wg21.link/over.match.best.general">[over.match.best.general]</a></span>
General<a href="#over.match.best.general-general" class="self-link"></a></h3>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
changes to [over.match.viable]/2.3 included in this proposal (part of
the resolution to <span class="citation" data-cites="CWG2701"><a href="https://wg21.link/cwg2701" role="doc-biblioref">[CWG2701]</a></span>) render paragraph 4 redundant;
the contents of example 9 now follow [over.match.viable]/2. ]</span></p>
<p>Delete paragraph 4 and example 9.</p>
<div class="std">
<blockquote>
<div class="rm" style="color: #bf0303">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_367" id="pnum_367">4</a></span>
If the best viable function resolves to a function for which multiple
declarations were found, and if any two of these declarations inhabit
different scopes and specify a default argument that made the function
viable, the program is ill-formed.</p>
<div class="example9">
<span>[ <em>Example 9:</em> </span>
<div class="sourceCode" id="cb160"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb160-1"><a href="#cb160-1" aria-hidden="true" tabindex="-1"></a>namespace A {</span>
<span id="cb160-2"><a href="#cb160-2" aria-hidden="true" tabindex="-1"></a>  extern &quot;C&quot; void f(int = 5);</span>
<span id="cb160-3"><a href="#cb160-3" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb160-4"><a href="#cb160-4" aria-hidden="true" tabindex="-1"></a>namespace B {</span>
<span id="cb160-5"><a href="#cb160-5" aria-hidden="true" tabindex="-1"></a>  extern &quot;C&quot; void f(int = 5);</span>
<span id="cb160-6"><a href="#cb160-6" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb160-7"><a href="#cb160-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb160-8"><a href="#cb160-8" aria-hidden="true" tabindex="-1"></a>using A::f;</span>
<span id="cb160-9"><a href="#cb160-9" aria-hidden="true" tabindex="-1"></a>using B::f;</span>
<span id="cb160-10"><a href="#cb160-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb160-11"><a href="#cb160-11" aria-hidden="true" tabindex="-1"></a>void use() {</span>
<span id="cb160-12"><a href="#cb160-12" aria-hidden="true" tabindex="-1"></a>  f(3);        // OK, default argument was not used for viability</span>
<span id="cb160-13"><a href="#cb160-13" aria-hidden="true" tabindex="-1"></a>  f();         // error: found default argument twice</span>
<span id="cb160-14"><a href="#cb160-14" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>

</div>
</blockquote>
</div>
<h3 class="unnumbered" id="over.over-address-of-an-overload-set"><span>12.3 <a href="https://wg21.link/over.over">[over.over]</a></span> Address of an
overload set<a href="#over.over-address-of-an-overload-set" class="self-link"></a></h3>
<p>Remove the explicit references to
<code class="sourceCode cpp"><em>id-expression</em></code>s from
paragraph 1 to allow taking the address of an overload set specified by
a <code class="sourceCode cpp"><em>splice-expression</em></code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_368" id="pnum_368">1</a></span>
An <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>id-expression</em></code></span>
whose terminal name refers to</del></span> <span class="addu">expression
that designates</span> an overload set
<code class="sourceCode cpp"><em>S</em></code> and that appears without
arguments is resolved to a function, a pointer to function, or a pointer
to member function for a specific function that is chosen from a set of
functions selected from <code class="sourceCode cpp"><em>S</em></code>
determined based on the target type required in the context (if any), as
described below. […]</p>
<p>The <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>id-expression</em></code></span></del></span>
<span class="addu">expression</span> can be preceded by the
<code class="sourceCode cpp"><span class="op">&amp;</span></code>
operator.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="over.built-built-in-operators"><span>12.5 <a href="https://wg21.link/over.built">[over.built]</a></span> Built-in
operators<a href="#over.built-built-in-operators" class="self-link"></a></h3>
<p>Add built-in operator candidates for <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
to <span>12.5 <a href="https://wg21.link/over.built">[over.built]</a></span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_369" id="pnum_369">16</a></span>
For every <code class="sourceCode cpp">T</code>, where
<code class="sourceCode cpp">T</code> is a pointer-to-member type<span class="addu">, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,</span>
or <code class="sourceCode cpp">std<span class="op">::</span>nullptr_t</code>,
there exist candidate operator functions of the form</p>
<div class="sourceCode" id="cb161"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb161-1"><a href="#cb161-1" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>T, T<span class="op">)</span>;</span>
<span id="cb161-2"><a href="#cb161-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> <span class="kw">operator</span><span class="op">!=(</span>T, T<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.param-template-parameters"><span>13.2 <a href="https://wg21.link/temp.param">[temp.param]</a></span> Template
parameters<a href="#temp.param-template-parameters" class="self-link"></a></h3>
<p>Extend
<code class="sourceCode cpp"><em>type-tt-parameter-default</em></code>
and <code class="sourceCode cpp"><em>variable-tt-parameter</em></code>
to permit <code class="sourceCode cpp"><em>splice-specifier</em></code>s
as default template arguments for template template parameters.</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb162"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb162-1"><a href="#cb162-1" aria-hidden="true" tabindex="-1"></a>  <em>type-tt-parameter-default</em>:</span>
<span id="cb162-2"><a href="#cb162-2" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></span>
<span id="cb162-3"><a href="#cb162-3" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em> template <em>template-name</em></span>
<span id="cb162-4"><a href="#cb162-4" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-template-argument</em></span></span>
<span id="cb162-5"><a href="#cb162-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb162-6"><a href="#cb162-6" aria-hidden="true" tabindex="-1"></a>  <em>variable-tt-parameter</em>:</span>
<span id="cb162-7"><a href="#cb162-7" aria-hidden="true" tabindex="-1"></a>      <em>template-head</em> auto ...<sub><em>opt</em></sub> $identifier<sub><em>opt</em></sub></span>
<span id="cb162-8"><a href="#cb162-8" aria-hidden="true" tabindex="-1"></a>      <em>template-head</em> auto <em>identifier</em><sub><em>opt</em></sub> = <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></span>
<span id="cb162-9"><a href="#cb162-9" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>template-head</em> auto <em>identifier</em><sub><em>opt</em></sub> = <em>splice-template-argument</em></span></span>
<span id="cb162-10"><a href="#cb162-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb162-11"><a href="#cb162-11" aria-hidden="true" tabindex="-1"></a>  <em>concept-tt-parameter</em>:</span>
<span id="cb162-12"><a href="#cb162-12" aria-hidden="true" tabindex="-1"></a>      template &lt; <em>template-parameter-list</em> &gt; concept ...<sub><em>opt</em></sub> <em>identifier</em><sub><em>opt</em></sub></span>
<span id="cb162-13"><a href="#cb162-13" aria-hidden="true" tabindex="-1"></a>      template &lt; <em>template-parameter-list</em> &gt; concept <em>identifier</em><sub><em>opt</em></sub> = <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></span>
<span id="cb162-14"><a href="#cb162-14" aria-hidden="true" tabindex="-1"></a><span class="va">+     template &lt; <em>template-parameter-list</em> &gt; concept <em>identifier</em><sub><em>opt</em></sub> = <em>splice-template-argument</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add a paragraph after paragraph 3 to disallow dependent concepts
being used in a
<code class="sourceCode cpp"><em>type-constraint</em></code>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_370" id="pnum_370">3+</a></span>
The <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
of a <code class="sourceCode cpp"><em>type-constraint</em></code>, if
any, shall not be dependent.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.names-names-of-template-specializations"><span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span> Names of
template specializations<a href="#temp.names-names-of-template-specializations" class="self-link"></a></h3>
<p>Define the term
<code class="sourceCode cpp"><em>splice-template-argument</em></code>,
and add it as a production for
<code class="sourceCode cpp"><em>template-argument</em></code>.</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb163"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb163-1"><a href="#cb163-1" aria-hidden="true" tabindex="-1"></a>  <em>template-argument</em>:</span>
<span id="cb163-2"><a href="#cb163-2" aria-hidden="true" tabindex="-1"></a>      <em>constant-expression</em></span>
<span id="cb163-3"><a href="#cb163-3" aria-hidden="true" tabindex="-1"></a>      <em>type-id</em></span>
<span id="cb163-4"><a href="#cb163-4" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></span>
<span id="cb163-5"><a href="#cb163-5" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em><sub><em>opt</em></sub> template <em>template-name</em></span>
<span id="cb163-6"><a href="#cb163-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-template-argument</em></span></span>
<span id="cb163-7"><a href="#cb163-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb163-8"><a href="#cb163-8" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-template-argument</em>:</span></span>
<span id="cb163-9"><a href="#cb163-9" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-specifier</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Extend and re-format paragraph 3 of <span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_371" id="pnum_371">3</a></span>
A <code class="sourceCode cpp"><span class="op">&lt;</span></code> is
interpreted as the delimiter of a
<code class="sourceCode cpp"><em>template-argument-list</em></code> if
it follows</p>
<ul>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_372" id="pnum_372">(3.1)</a></span>
a <code class="sourceCode cpp"><em>splice-specifier</em></code> that
either appears in a type-only context or is preceded by
<code class="sourceCode cpp"><span class="kw">template</span></code> or
<code class="sourceCode cpp"><span class="kw">typename</span></code>,
or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_373" id="pnum_373">(3.2)</a></span>
a name that is not a
<code class="sourceCode cpp"><em>conversion-function-id</em></code> and
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_374" id="pnum_374">(3.2.1)</a></span>
that follows the keyword template or a ~ after a nested-name-specifier
or in a class member access expression, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_375" id="pnum_375">(3.2.2)</a></span>
for which name lookup finds the injected-class-name of a class template
or finds any declaration of a template, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_376" id="pnum_376">(3.2.3)</a></span>
that is an unqualified name for which name lookup either finds one or
more functions or finds nothing, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_377" id="pnum_377">(3.2.4)</a></span>
that is a terminal name in a using-declarator ([namespace.udecl]), in a
declarator-id ([dcl.meaning]), or in a type-only context other than a
nested-name-specifier ([temp.res]).</li>
</ul></li>
</ul>
<p><span class="note"><span>[ <em>Note 1:</em> </span>If the name is an
identifier, it is then interpreted as a <em>template-name</em>. The
keyword template is used to indicate that a dependent qualified name
(<span>13.8.3.2 <a href="https://wg21.link/temp.dep.type">[temp.dep.type]</a></span>)
denotes a template where an expression might appear.<span> — <em>end
note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div>
<div class="sourceCode" id="cb164"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb164-1"><a href="#cb164-1" aria-hidden="true" tabindex="-1"></a>struct X {</span>
<span id="cb164-2"><a href="#cb164-2" aria-hidden="true" tabindex="-1"></a>  template&lt;std::size_t&gt; X* alloc();</span>
<span id="cb164-3"><a href="#cb164-3" aria-hidden="true" tabindex="-1"></a>  template&lt;std::size_t&gt; static X* adjust();</span>
<span id="cb164-4"><a href="#cb164-4" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb164-5"><a href="#cb164-5" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt; void f(T* p) {</span>
<span id="cb164-6"><a href="#cb164-6" aria-hidden="true" tabindex="-1"></a>  T* p1 = p-&gt;alloc&lt;200&gt;();              // error: &lt; means less than</span>
<span id="cb164-7"><a href="#cb164-7" aria-hidden="true" tabindex="-1"></a>  T* p2 = p-&gt;template alloc&lt;200&gt;();     // OK, &lt; starts template argument list</span>
<span id="cb164-8"><a href="#cb164-8" aria-hidden="true" tabindex="-1"></a>  T::adjust&lt;100&gt;();                     // error: &lt; means less than</span>
<span id="cb164-9"><a href="#cb164-9" aria-hidden="true" tabindex="-1"></a>  T::template adjust&lt;100&gt;();            // OK, &lt; starts template argument list</span>
<span id="cb164-10"><a href="#cb164-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb164-11"><a href="#cb164-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ static constexpr auto r = ^^T::adjust;</span></span>
<span id="cb164-12"><a href="#cb164-12" aria-hidden="true" tabindex="-1"></a><span class="va">+ T* p3 = [:r:]&lt;200&gt;();                 // error: &lt; means less than</span></span>
<span id="cb164-13"><a href="#cb164-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ T* p4 = template [:r:]&lt;200&gt;();        // OK, &lt; starts template argument list</span></span>
<span id="cb164-14"><a href="#cb164-14" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<p>Clarify that the
<code class="sourceCode cpp"><span class="op">&gt;</span></code>
disambiguation in paragraph 4 also applies to the parsing of
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_378" id="pnum_378">4</a></span>
When parsing a
<code class="sourceCode cpp"><em>template-argument-list</em></code>, the
first non-nested
<code class="sourceCode cpp"><span class="op">&gt;</span></code><sup>108</sup>
is taken as the ending delimiter rather than a greater-than operator.
Similarly, the first non-nested
<code class="sourceCode cpp"><span class="op">&gt;&gt;</span></code> is
treated as two consecutive but distinct
<code class="sourceCode cpp"><span class="op">&gt;</span></code> tokens,
the first of which is taken as the end of the
<code class="sourceCode cpp"><em>template-argument-list</em></code> and
completes the <code class="sourceCode cpp"><em>template-id</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>.</p>
<p><span class="note"><span>[ <em>Note 2:</em> </span>The second
<code class="sourceCode cpp"><span class="op">&gt;</span></code> token
produced by this replacement rule can terminate an enclosing
<code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
construct or it can be part of a different construct (e.g., a
cast).<span> — <em>end note</em> ]</span></span></p>
</blockquote>
</div>
<p>Extend the definition of a <em>valid</em>
<code class="sourceCode cpp"><em>template-id</em></code> to also cover
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_379" id="pnum_379">7</a></span>
A <code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
is <em>valid</em> if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_380" id="pnum_380">(7.1)</a></span>
there are at most as many arguments as there are parameters or a
parameter is a template parameter pack (<span>13.7.4 <a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_381" id="pnum_381">(7.2)</a></span>
there is an argument for each non-deducible non-pack parameter that does
not have a default
<code class="sourceCode cpp"><em>template-argument</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_382" id="pnum_382">(7.3)</a></span>
each <code class="sourceCode cpp"><em>template-argument</em></code>
matches the corresponding
<code class="sourceCode cpp"><em>template-parameter</em></code>
(<span>13.4 <a href="https://wg21.link/temp.arg">[temp.arg]</a></span>),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_383" id="pnum_383">(7.4)</a></span>
substitution of each template argument into the following template
parameters (if any) succeeds, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_384" id="pnum_384">(7.5)</a></span>
if the <code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
is non-dependent, the associated constraints are satisfied as specified
in the next paragraph.</li>
</ul>
<p>A <code class="sourceCode cpp"><em>simple-template-id</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
shall be valid unless it names a function template specialization
(<span>13.10.3 <a href="https://wg21.link/temp.deduct">[temp.deduct]</a></span>).</p>
</blockquote>
</div>
<p>Extend paragraph 8 to require constraints to also be satisfied by
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_385" id="pnum_385">8</a></span>
When the <code class="sourceCode cpp"><em>template-name</em></code> of a
<code class="sourceCode cpp"><em>simple-template-id</em></code> <span class="addu">or the
<code class="sourceCode cpp"><em>splice-specifier</em></code> of a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
designates</span> <span class="rm" style="color: #bf0303"><del>names</del></span> a constrained
non-function template or a constrained template
<code class="sourceCode cpp"><em>template-parameter</em></code>, and all
<code class="sourceCode cpp"><em>template-arguments</em></code> in the
<code class="sourceCode cpp"><em>simple-template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
are non-dependent (<span>13.8.3.5 <a href="https://wg21.link/temp.dep.temp">[temp.dep.temp]</a></span>), the
associated constraints (<span>13.5.3 <a href="https://wg21.link/temp.constr.decl">[temp.constr.decl]</a></span>)
of the constrained template shall be satisfied (<span>13.5.2 <a href="https://wg21.link/temp.constr.constr">[temp.constr.constr]</a></span>).</p>
</blockquote>
</div>
<p>Modify footnote 108 to account for
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_386" id="pnum_386">108)</a></span>
A <code class="sourceCode cpp"><span class="op">&gt;</span></code> that
encloses the <code class="sourceCode cpp"><em>type-id</em></code> of a
<code class="sourceCode cpp"><span class="kw">dynamic_cast</span></code>,
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>,
<code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>
or
<code class="sourceCode cpp"><span class="kw">const_cast</span></code>,
or which encloses the
<code class="sourceCode cpp"><em>template-argument</em></code>s of a
subsequent <code class="sourceCode cpp"><em>template-id</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>,
is considered nested for the purpose of this description.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.arg.general-general"><span>13.4.1 <a href="https://wg21.link/temp.arg.general">[temp.arg.general]</a></span>
General<a href="#temp.arg.general-general" class="self-link"></a></h3>
<p>Modify paragraph 1; there are now <em>four</em> forms of
<code class="sourceCode cpp"><em>template-argument</em></code>.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_387" id="pnum_387">1</a></span>
The type and form of each
<code class="sourceCode cpp"><em>template-argument</em></code> specified
in a <code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">or in a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
shall match the type and form specified for the corresponding parameter
declared by the template in its
<code class="sourceCode cpp"><em>template-parameter-list</em></code>.
<span class="addu">A
<code class="sourceCode cpp"><em>template-argument</em></code> that is a
splice template argument is considered to match the form specified for
the corresponding template parameter.</span> When the parameter declared
by the template is a template parameter pack, it will correspond to zero
or more
<code class="sourceCode cpp"><em>template-argument</em></code>s.</p>
</blockquote>
</div>
<p>Clarify ambiguity between
<code class="sourceCode cpp"><em>splice-expression</em></code>s and
<code class="sourceCode cpp"><em>splice-template-argument</em></code>s
in paragraph 3:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_388" id="pnum_388">3</a></span>
<span class="addu">A
<code class="sourceCode cpp"><em>template-argument</em></code> of the
form <code class="sourceCode cpp"><em>splice-specifier</em></code> is
interpreted as a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>.</span>
<span class="rm" style="color: #bf0303"><del>In a</del></span> <span class="addu">For any other</span>
<code class="sourceCode cpp"><em>template-argument</em></code>, an
ambiguity between a <code class="sourceCode cpp"><em>type-id</em></code>
and an expression is resolved to a
<code class="sourceCode cpp"><em>type-id</em></code>, regardless of the
form of the corresponding
<code class="sourceCode cpp"><em>template-parameter</em></code>.</p>
<div class="example2">
<span>[ <em>Example 2:</em> </span>
<div>
<div class="sourceCode" id="cb165"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb165-1"><a href="#cb165-1" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt; void f(); <span class="addu">  // #1</span></span>
<span id="cb165-2"><a href="#cb165-2" aria-hidden="true" tabindex="-1"></a>  template&lt;int I&gt; void f(); <span class="addu">    // #2</span></span>
<span id="cb165-3"><a href="#cb165-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb165-4"><a href="#cb165-4" aria-hidden="true" tabindex="-1"></a>  void g() {</span>
<span id="cb165-5"><a href="#cb165-5" aria-hidden="true" tabindex="-1"></a>    f&lt;int()&gt;();       // int() is a type-id: call<span class="addu">s (#1)</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">the first f()</code></span></del></span></span>
<span id="cb165-6"><a href="#cb165-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb165-7"><a href="#cb165-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   constexpr int x = 42;</span></span>
<span id="cb165-8"><a href="#cb165-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   f&lt;[:^^int:]&gt;();    // splice-template-argument: calls (#1)</span></span>
<span id="cb165-9"><a href="#cb165-9" aria-hidden="true" tabindex="-1"></a><span class="va">+   f&lt;[:^^x:]&gt;();      // splice-template-argument: calls (#2)</span></span>
<span id="cb165-10"><a href="#cb165-10" aria-hidden="true" tabindex="-1"></a>  }</span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<p>Clarify in paragraph 9 that default template arguments also apply to
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_389" id="pnum_389">9</a></span>
When a <code class="sourceCode cpp"><em>simple-template-id</em></code>
<span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
does not <span class="rm" style="color: #bf0303"><del>name</del></span>
<span class="addu">designate</span> a function, a default
<code class="sourceCode cpp"><em>template-argument</em></code> is
implicitly instantiated when the value of that default argument is
needed.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.arg.type-template-type-arguments"><span>13.4.2 <a href="https://wg21.link/temp.arg.type">[temp.arg.type]</a></span>
Template type arguments<a href="#temp.arg.type-template-type-arguments" class="self-link"></a></h3>
<p>Extend <span>13.4.2 <a href="https://wg21.link/temp.arg.type">[temp.arg.type]</a></span>/1 to
cover splice template arguments:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_390" id="pnum_390">1</a></span>
A <code class="sourceCode cpp"><em>template-argument</em></code> for a
type template parameter shall <span class="addu">either</span> be a
<code class="sourceCode cpp"><em>type-id</em></code> <span class="addu">or a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>
whose <code class="sourceCode cpp"><em>splice-specifier</em></code>
designates a type</span>.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.arg.nontype-constant-template-arguments"><span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>
Constant template arguments<a href="#temp.arg.nontype-constant-template-arguments" class="self-link"></a></h3>
<p><span class="draftnote" style="color: #01796F">[ Drafting note: We
don’t think we have to change anything here, since if
<code class="sourceCode cpp">E</code> is a
<code class="sourceCode cpp"><em>splice-specifier</em></code> that can
be interpreted as a
<code class="sourceCode cpp"><em>splice-expression</em></code>, the
requirements already fall out based on how paragraphs 1 and 3 are
already worded ]</span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_391" id="pnum_391">1</a></span>
If the type <code class="sourceCode cpp">T</code> of a
<em>template-parameter</em> ([temp.param]) contains a placeholder type
([dcl.spec.auto]) or a placeholder for a deduced class type
([dcl.type.class.deduct]), the type of the parameter is the type deduced
for the variable x in the invented declaration</p>
<div class="sourceCode" id="cb166"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb166-1"><a href="#cb166-1" aria-hidden="true" tabindex="-1"></a>T x <span class="op">=</span> <em>E</em> ;</span></code></pre></div>
<p>where <code class="sourceCode cpp"><em>E</em></code> is the template
argument provided for the parameter.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_392" id="pnum_392">2</a></span>
The value of a constant template parameter
<code class="sourceCode cpp">P</code> of (possibly deduced) type
<code class="sourceCode cpp">T</code> […]</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_393" id="pnum_393">3</a></span>
Otherwise, a temporary variable</p>
<div class="sourceCode" id="cb167"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb167-1"><a href="#cb167-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> T v <span class="op">=</span> <em>A</em>;</span></code></pre></div>
<p>is introduced.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.arg.template-template-template-arguments"><span>13.4.4 <a href="https://wg21.link/temp.arg.template">[temp.arg.template]</a></span>
Template template arguments<a href="#temp.arg.template-template-template-arguments" class="self-link"></a></h3>
<p>Extend paragraph 1 to cover splice template arguments:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_394" id="pnum_394">1</a></span>
A <code class="sourceCode cpp"><em>template-argument</em></code> for a
template template parameter shall <span class="addu">either</span> be
the name of a template <span class="addu">or a
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>.
For a <code class="sourceCode cpp"><em>type-tt-parameter</em></code>,
the name <span class="addu">or
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>
shall <span class="rm" style="color: #bf0303"><del>denote</del></span>
<span class="addu">designate</span> a class template or alias template.
For a
<code class="sourceCode cpp"><em>variable-tt-parameter</em></code>, the
name <span class="addu">or
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>
shall <span class="rm" style="color: #bf0303"><del>denote</del></span>
<span class="addu">designate</span> a variable template. For a
<code class="sourceCode cpp"><em>concept-tt-parameter</em></code>, the
name <span class="addu">or
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>
shall <span class="rm" style="color: #bf0303"><del>denote</del></span>
<span class="addu">designate</span> a concept. Only primary templates
are considered when matching the template argument with the
corresponding parameter; partial specializations are not considered even
if their parameter lists match that of the template template
parameter.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.type-type-equivalence"><span>13.6 <a href="https://wg21.link/temp.type">[temp.type]</a></span> Type
equivalence<a href="#temp.type-type-equivalence" class="self-link"></a></h3>
<p>Extend paragraph 1 to also define the “sameness” of
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_395" id="pnum_395">1</a></span>
Two <code class="sourceCode cpp"><em>template-id</em></code>s <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s</span>
are the same if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_396" id="pnum_396">(1.1)</a></span>
their <code class="sourceCode cpp"><em>template-name</em></code>s,
<code class="sourceCode cpp"><em>operator-function-id</em></code>s,
<span class="rm" style="color: #bf0303"><del>or</del></span>
<code class="sourceCode cpp"><em>literal-operator-id</em></code>s<span class="addu">, or
<code class="sourceCode cpp"><em>splice-specifier</em></code>s</span>
refer to the same template, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_397" id="pnum_397">(1.2)</a></span>
their corresponding type
<code class="sourceCode cpp"><em>template-argument</em></code>s are the
same type, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_398" id="pnum_398">(1.3)</a></span>
the template parameter values determined by their corresponding constant
template arguments (<span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>)
are template-argument-equivalent (see below), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_399" id="pnum_399">(1.4)</a></span>
their corresponding template
<code class="sourceCode cpp"><em>template-argument</em></code>s refer to
the same template.</li>
</ul>
<p>Two <code class="sourceCode cpp"><em>template-id</em></code>s <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s</span>
that are the same refer to the same class, function, or variable.</p>
</blockquote>
</div>
<p>Extend <em>template-argument-equivalent</em> in paragraph 2 to handle
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_400" id="pnum_400">2</a></span>
Two values are <em>template-argument-equivalent</em> if they are of the
same type and</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_401" id="pnum_401">(2.1)</a></span>
they are of integral type and their values are the same, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_402" id="pnum_402">(2.2)</a></span>
they are of floating-point type and their values are identical, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_403" id="pnum_403">(2.3)</a></span>
they are of type <code class="sourceCode cpp">std<span class="op">::</span>nullptr_t</code>,
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_404" id="pnum_404">(2.*)</a></span>
<span class="addu">they are of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
and their values are the same, or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_405" id="pnum_405">(2.4)</a></span>
they are of enumeration type and their values are the same, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_406" id="pnum_406">(2.5)</a></span>
[…]</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.deduct.guide-deduction-guides"><span>13.7.2.3 <a href="https://wg21.link/temp.deduct.guide">[temp.deduct.guide]</a></span>
Deduction guides<a href="#temp.deduct.guide-deduction-guides" class="self-link"></a></h3>
<p>Extend paragraph 1 to clarify that
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s can
also leverage deduction guides.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_407" id="pnum_407">1</a></span>
Deduction guides are used when a
<code class="sourceCode cpp"><em>template-name</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-type-specifier</em></code></span>
appears as a type specifier for a deduced class type
([dcl.type.class.deduct]). Deduction guides are not found by name
lookup. Instead, when performing class template argument deduction
([over.match.class.deduct]), all reachable deduction guides declared for
the class template are considered.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.mem-member-templates"><span>13.7.3 <a href="https://wg21.link/temp.mem">[temp.mem]</a></span> Member
templates<a href="#temp.mem-member-templates" class="self-link"></a></h3>
<p>Clarify in Note 1 that a specialization of a conversion function
template can be formed through a
<code class="sourceCode cpp"><em>splice-expression</em></code>.</p>
<div class="std">
<blockquote>
<div class="note">
<p><span>[ <em>Note 1:</em> </span>A specialization of a conversion
function template is referenced in the same way as a non-template
conversion function that converts to the same type
([class.conv.fct]).</p>
<p>…</p>
<p><span class="addu">An expression designating a particular
specialization of a conversion function template can only be formed with
a <code class="sourceCode cpp"><em>splice-expression</em></code>.</span>
There is no <span class="addu">analogous</span> syntax to form a
<code class="sourceCode cpp"><em>template-id</em></code> ([temp.names])
<span class="addu">for such a function</span> by providing an explicit
template argument list ([temp.arg.explicit]).<span> — <em>end
note</em> ]</span></p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.alias-alias-templates"><span>13.7.8 <a href="https://wg21.link/temp.alias">[temp.alias]</a></span> Alias
templates<a href="#temp.alias-alias-templates" class="self-link"></a></h3>
<p>Extend paragraph 2 to enable reflection of alias template
specializations.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_408" id="pnum_408">2</a></span>
<span class="rm" style="color: #bf0303"><del>When a</del></span> <span class="addu">A</span>
<code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">that</span> refers to the specialization of an alias
template<span class="rm" style="color: #bf0303"><del>, it is equivalent
to</del></span> <span class="addu">is a
<code class="sourceCode cpp"><em>typedef-name</em></code> for a type
alias whose underlying entity is</span> the associated type obtained by
substitution of its
<code class="sourceCode cpp"><em>template-arguments</em></code> for the
<code class="sourceCode cpp"><em>template-parameters</em></code> in the
<code class="sourceCode cpp"><em>defining-type-id</em></code> of the
alias template.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.res.general-general"><span>13.8.1 <a href="https://wg21.link/temp.res.general">[temp.res.general]</a></span>
General<a href="#temp.res.general-general" class="self-link"></a></h3>
<p>Extend paragraph 4 to define what it means for a
<code class="sourceCode cpp"><em>splice-specifier</em></code> to appear
in a type-only context. Also
<code class="sourceCode cpp"><em>using-enum-declarator</em></code>s to
the list of type-only contexts, as it allows the
<code class="sourceCode cpp"><span class="kw">typename</span></code> to
be elided from a
<code class="sourceCode cpp"><em>splice-type-specifier</em></code> in
non-dependent contexts.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_409" id="pnum_409">4</a></span>
A qualified or unqualified name is said to be in a
<code class="sourceCode cpp"><em>type-only context</em></code> if it is
the terminal name of</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_410" id="pnum_410">(4.1)</a></span>
a <code class="sourceCode cpp"><em>typename-specifier</em></code>,
<code class="sourceCode cpp"><em>type-requirement</em></code>,
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<code class="sourceCode cpp"><em>elaborated-type-specifier</em></code>,
<code class="sourceCode cpp"><em>class-or-decltype</em></code>, <span class="addu"><code class="sourceCode cpp"><em>using-enum-declarator</em></code></span>
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_411" id="pnum_411">(4.2)</a></span>
[…]
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_412" id="pnum_412">(4.4.6)</a></span>
<code class="sourceCode cpp"><em>parameter-declaration</em></code> of a
<code class="sourceCode cpp"><em>template-parameter</em></code> (which
necessarily declares a constant template parameter).</li>
</ul></li>
</ul>
<p><span class="addu">A
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
([basic.splice]) is said to be in a <em>type-only context</em> if a
hypothetical qualified name appearing in the same position would be in a
type-only context.</span></p>
<div class="example5">
<span>[ <em>Example 5:</em> </span>
<div class="sourceCode" id="cb168"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb168-1"><a href="#cb168-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> T<span class="op">::</span>R f<span class="op">()</span>;</span>
<span id="cb168-2"><a href="#cb168-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="dt">void</span> f<span class="op">(</span>T<span class="op">::</span>R<span class="op">)</span>;   <span class="co">// ill-formed, no diagnostic required: attempt to</span></span>
<span id="cb168-3"><a href="#cb168-3" aria-hidden="true" tabindex="-1"></a>                                  <span class="co">// declare a `void` variable template</span></span>
<span id="cb168-4"><a href="#cb168-4" aria-hidden="true" tabindex="-1"></a><span class="addu"><code class="sourceCode cpp"><span class="kw">enum</span> <span class="kw">class</span> Enum <span class="op">{</span> A, B, C <span class="op">}</span>;</code></span></span>
<span id="cb168-5"><a href="#cb168-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb168-6"><a href="#cb168-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb168-7"><a href="#cb168-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> Ptr <span class="op">=</span> PtrTraits<span class="op">&lt;</span>T<span class="op">&gt;::</span>Ptr;  <span class="co">// OK, in a <em>defining-type-id</em></span></span>
<span id="cb168-8"><a href="#cb168-8" aria-hidden="true" tabindex="-1"></a>  <span class="addu"><code class="sourceCode cpp"><span class="kw">using</span> Alias <span class="op">=</span> <span class="op">[:^^</span><span class="dt">int</span><span class="op">:]</span>;        <span class="co">// OK, in a <em>defining-type-id</em></span></code></span></span>
<span id="cb168-9"><a href="#cb168-9" aria-hidden="true" tabindex="-1"></a>  T<span class="op">::</span>R f<span class="op">(</span>T<span class="op">::</span>P p<span class="op">)</span> <span class="op">{</span>                <span class="co">// OK, class scope</span></span>
<span id="cb168-10"><a href="#cb168-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">::</span>R<span class="op">&gt;(</span>p<span class="op">)</span>;  <span class="co">// OK, <em>type-id</em> of a `static_cast`</span></span>
<span id="cb168-11"><a href="#cb168-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb168-12"><a href="#cb168-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> g<span class="op">()</span> <span class="op">-&gt;</span> S<span class="op">&lt;</span>T<span class="op">*&gt;::</span>Ptr;         <span class="co">// OK, <em>trailing-return-type</em></span></span>
<span id="cb168-13"><a href="#cb168-13" aria-hidden="true" tabindex="-1"></a>  <span class="addu"><code class="sourceCode cpp"><span class="kw">auto</span> h<span class="op">()</span> <span class="op">-&gt;</span> <span class="op">[:^^</span>S<span class="op">:]&lt;</span>T<span class="op">*&gt;</span>;        <span class="co">// OK, <em>trailing-return-type</em></span></code></span></span>
<span id="cb168-14"><a href="#cb168-14" aria-hidden="true" tabindex="-1"></a>  <span class="addu"><code class="sourceCode cpp"><span class="kw">using</span> <span class="kw">enum</span> <span class="op">[:^^</span>Enum<span class="op">:]</span>;          <span class="co">// OK, <em>using-enum-declarator</em></span></code></span></span>
<span id="cb168-15"><a href="#cb168-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb168-16"><a href="#cb168-16" 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 class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb168-17"><a href="#cb168-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="op">(*</span>pf<span class="op">)(</span>T<span class="op">::</span>X<span class="op">)</span>;               <span class="co">// variable `pf` of type `void*` initialized</span></span>
<span id="cb168-18"><a href="#cb168-18" aria-hidden="true" tabindex="-1"></a>                                  <span class="co">// with `T::X`</span></span>
<span id="cb168-19"><a href="#cb168-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> g<span class="op">(</span>T<span class="op">::</span>X<span class="op">)</span>;                   <span class="co">// error: `T::X` at block scope does not denote</span></span>
<span id="cb168-20"><a href="#cb168-20" aria-hidden="true" tabindex="-1"></a>                                  <span class="co">// a type (attempt to declare a `void` variable)</span></span>
<span id="cb168-21"><a href="#cb168-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.type-dependent-types"><span>13.8.3.2
<a href="https://wg21.link/temp.dep.type">[temp.dep.type]</a></span>
Dependent types<a href="#temp.dep.type-dependent-types" class="self-link"></a></h3>
<p>Account for dependent
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>s in
paragraph 10:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_413" id="pnum_413">10</a></span>
A type is dependent if it is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_414" id="pnum_414">(10.1)</a></span>
a template parameter,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_415" id="pnum_415">(10.2)</a></span>
…</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_416" id="pnum_416">(10.13)</a></span>
denoted by <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><em>expression</em><span class="op">)</span></code>,
where <code class="sourceCode cpp"><em>expression</em></code> is
type-dependent<span class="rm" style="color: #bf0303"><del>.</del></span><span class="addu">,
or</span></li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_417" id="pnum_417">(10.14)</a></span>
denoted by a
<code class="sourceCode cpp"><em>splice-type-specifier</em></code> in
which either the
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is dependent ([temp.dep.splice]).</span></li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.expr-type-dependent-expressions"><span>13.8.3.3 <a href="https://wg21.link/temp.dep.expr">[temp.dep.expr]</a></span>
Type-dependent expressions<a href="#temp.dep.expr-type-dependent-expressions" class="self-link"></a></h3>
<p>Add to the list of never-type-dependent expression forms in paragraph
4:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb169"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb169-1"><a href="#cb169-1" aria-hidden="true" tabindex="-1"></a>     <em>literal</em></span>
<span id="cb169-2"><a href="#cb169-2" aria-hidden="true" tabindex="-1"></a>     sizeof <em>unary-expression</em></span>
<span id="cb169-3"><a href="#cb169-3" aria-hidden="true" tabindex="-1"></a>     sizeof ( <em>type-id</em> )</span>
<span id="cb169-4"><a href="#cb169-4" aria-hidden="true" tabindex="-1"></a>     sizeof ... ( <em>identifier</em> )</span>
<span id="cb169-5"><a href="#cb169-5" aria-hidden="true" tabindex="-1"></a>     alignof ( <em>type-id</em> )</span>
<span id="cb169-6"><a href="#cb169-6" aria-hidden="true" tabindex="-1"></a>     typeid ( <em>expression</em> )</span>
<span id="cb169-7"><a href="#cb169-7" aria-hidden="true" tabindex="-1"></a>     typeid ( <em>type-id</em> )</span>
<span id="cb169-8"><a href="#cb169-8" aria-hidden="true" tabindex="-1"></a>     ::<sub><em>opt</em></sub> delete <em>cast-expression</em></span>
<span id="cb169-9"><a href="#cb169-9" aria-hidden="true" tabindex="-1"></a>     ::<sub><em>opt</em></sub> delete [ ] <em>cast-expression</em></span>
<span id="cb169-10"><a href="#cb169-10" aria-hidden="true" tabindex="-1"></a>     throw <em>assignment-expression</em><sub><em>opt</em></sub></span>
<span id="cb169-11"><a href="#cb169-11" aria-hidden="true" tabindex="-1"></a>     noexcept ( <em>expression</em> )</span>
<span id="cb169-12"><a href="#cb169-12" aria-hidden="true" tabindex="-1"></a>     <em>requires-expression</em></span>
<span id="cb169-13"><a href="#cb169-13" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>reflect-expression</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add a new paragraph at the end of <span>13.8.3.3 <a href="https://wg21.link/temp.dep.expr">[temp.dep.expr]</a></span>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_418" id="pnum_418">9</a></span>
A <code class="sourceCode cpp"><em>primary-expression</em></code> of the
form <code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><span class="kw">template</span> <em>splice-specialization-specifier</em></code>
is type-dependent if its
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is dependent ([temp.dep.splice]).</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.constexpr-value-dependent-expressions"><span>13.8.3.4 <a href="https://wg21.link/temp.dep.constexpr">[temp.dep.constexpr]</a></span>
Value-dependent expressions<a href="#temp.dep.constexpr-value-dependent-expressions" class="self-link"></a></h3>
<p>Add at the end of <span>13.8.3.4 <a href="https://wg21.link/temp.dep.constexpr">[temp.dep.constexpr]</a></span>/2
(before the note):</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_419" id="pnum_419">2</a></span>
An <em>id-expression</em> is value-dependent if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_420" id="pnum_420">(2.1)</a></span>
[…]</li>
</ul>
<p>Expressions of the following form are value-dependent if the
<em>unary-expression</em> or <em>expression</em> is type-dependent or
the <em>type-id</em> is dependent:</p>
<div class="sourceCode" id="cb170"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb170-1"><a href="#cb170-1" aria-hidden="true" tabindex="-1"></a>sizeof unary-expression</span>
<span id="cb170-2"><a href="#cb170-2" aria-hidden="true" tabindex="-1"></a>sizeof ( type-id )</span>
<span id="cb170-3"><a href="#cb170-3" aria-hidden="true" tabindex="-1"></a>typeid ( expression )</span>
<span id="cb170-4"><a href="#cb170-4" aria-hidden="true" tabindex="-1"></a>typeid ( type-id )</span>
<span id="cb170-5"><a href="#cb170-5" aria-hidden="true" tabindex="-1"></a>alignof ( type-id )</span>
<span id="cb170-6"><a href="#cb170-6" aria-hidden="true" tabindex="-1"></a>noexcept ( expression )</span></code></pre></div>
<p><span class="addu">A
<code class="sourceCode cpp"><em>reflect-expression</em></code> is
value-dependent if it contains a dependent
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>,
<code class="sourceCode cpp"><em>type-id</em></code>,
<code class="sourceCode cpp"><em>namespace-name</em></code>, or
<code class="sourceCode cpp"><em>template-name</em></code>, if it names
a dependent member of the current instantiation ([temp.dep.type]), or if
it contains a value-dependent or type-dependent
<code class="sourceCode cpp"><em>id-expression</em></code>.</span></p>
</blockquote>
</div>
<p>Add a new paragraph after <span>13.8.3.4 <a href="https://wg21.link/temp.dep.constexpr">[temp.dep.constexpr]</a></span>/6:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_421" id="pnum_421">6+</a></span>
A <code class="sourceCode cpp"><em>primary-expression</em></code> of the
form <code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><span class="kw">template</span> <em>splice-specialization-specifier</em></code>
is value-dependent if its
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is dependent ([temp.dep.splice]).</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.splice-dependent-splice-specifiers">13.8.3.4+
[temp.dep.splice] Dependent splice specifiers<a href="#temp.dep.splice-dependent-splice-specifiers" class="self-link"></a></h3>
<p>Add a new subsection of <span>13.8.3 <a href="https://wg21.link/temp.dep">[temp.dep]</a></span> following
<span>13.8.3.4 <a href="https://wg21.link/temp.dep.constexpr">[temp.dep.constexpr]</a></span>,
and renumber accordingly.</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Dependent splice specifiers [temp.dep.splice]</strong></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_422" id="pnum_422">1</a></span>
A <code class="sourceCode cpp"><em>splice-specifier</em></code> is
dependent if its converted
<code class="sourceCode cpp"><em>constant-expression</em></code> is
value-dependent. A
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is dependent if its
<code class="sourceCode cpp"><em>splice-specifier</em></code> is
dependent or if any of its arguments are dependent. A
<code class="sourceCode cpp"><em>splice-scope-specifier</em></code> is
dependent if its
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>
is dependent.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_423" id="pnum_423">2</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb171"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb171-1"><a href="#cb171-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> T, <span class="kw">auto</span> NS<span class="op">&gt;</span></span>
<span id="cb171-2"><a href="#cb171-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb171-3"><a href="#cb171-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> a <span class="op">=</span> <span class="op">[:</span>T<span class="op">:]&lt;</span><span class="dv">1</span><span class="op">&gt;</span>;  <span class="co">// [:T:] and [:T:]&lt;1&gt; are dependent</span></span>
<span id="cb171-4"><a href="#cb171-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb171-5"><a href="#cb171-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">([:</span>NS<span class="op">:]::</span><span class="kw">template</span> TCls<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;::</span>v <span class="op">==</span> a<span class="op">::</span>v<span class="op">)</span>;  <span class="co">// [:NS:] is dependent</span></span>
<span id="cb171-6"><a href="#cb171-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb171-7"><a href="#cb171-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb171-8"><a href="#cb171-8" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> NS <span class="op">{</span></span>
<span id="cb171-9"><a href="#cb171-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span> <span class="kw">struct</span> TCls <span class="op">{</span> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> v <span class="op">=</span> V; <span class="op">}</span>;</span>
<span id="cb171-10"><a href="#cb171-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb171-11"><a href="#cb171-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb171-12"><a href="#cb171-12" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb171-13"><a href="#cb171-13" aria-hidden="true" tabindex="-1"></a>  fn<span class="op">&lt;^^</span>NS<span class="op">::</span>TCls, <span class="op">^^</span>NS<span class="op">&gt;()</span>;</span>
<span id="cb171-14"><a href="#cb171-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_424" id="pnum_424">3</a></span></p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<div class="sourceCode" id="cb172"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb172-1"><a href="#cb172-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">class</span> X<span class="op">&gt;</span></span>
<span id="cb172-2"><a href="#cb172-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb172-3"><a href="#cb172-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <span class="op">[:</span> <span class="op">^^</span>X <span class="op">:]&lt;</span><span class="dt">int</span>, <span class="dt">float</span><span class="op">&gt;</span> m;</span>
<span id="cb172-4"><a href="#cb172-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb172-5"><a href="#cb172-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb172-6"><a href="#cb172-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> V1 <span class="op">{}</span>;</span>
<span id="cb172-7"><a href="#cb172-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span>, <span class="kw">class</span> <span class="op">=</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="kw">struct</span> V2 <span class="op">{}</span>;</span>
<span id="cb172-8"><a href="#cb172-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb172-9"><a href="#cb172-9" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>V1<span class="op">&gt;</span> s1; <span class="co">// error: V1&lt;int, float&gt; has too many template arguments</span></span>
<span id="cb172-10"><a href="#cb172-10" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>V2<span class="op">&gt;</span> s2; <span class="co">// OK</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.temp-dependent-template-arguments"><span>13.8.3.5 <a href="https://wg21.link/temp.dep.temp">[temp.dep.temp]</a></span>
Dependent template arguments<a href="#temp.dep.temp-dependent-template-arguments" class="self-link"></a></h3>
<p>Add a new paragraph to cover dependent splice template arguments.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_425" id="pnum_425">5</a></span>
A template
<code class="sourceCode cpp"><em>template-parameter</em></code> is
dependent if it names a
<code class="sourceCode cpp"><em>template-parameter</em></code> or if
its terminal name is dependent.</p>
<p><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_426" id="pnum_426">5+</a></span>
A splice template argument is dependent if its
<code class="sourceCode cpp"><em>splice-specifier</em></code> is
dependent.</span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.dep.namespace-dependent-namespaces">13.8.3.6
[temp.dep.namespace] Dependent namespaces<a href="#temp.dep.namespace-dependent-namespaces" class="self-link"></a></h3>
<p>Add a new section to cover dependent namespace aliases.</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Dependent namespaces [temp.dep.namespace]</strong></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_427" id="pnum_427">1</a></span>
A namespace alias is dependent if it is introduced by a
<code class="sourceCode cpp"><em>namespace-alias-definition</em></code>
whose <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
or <code class="sourceCode cpp"><em>splice-specifier</em></code> is
dependent. A <code class="sourceCode cpp"><em>namespace-name</em></code>
is dependent if it names a dependent namespace alias.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb173"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb173-1"><a href="#cb173-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info R<span class="op">&gt;</span> <span class="dt">int</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb173-2"><a href="#cb173-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> Alias <span class="op">=</span> <span class="op">[:</span>R<span class="op">:]</span>;  <span class="co">// [:R:] is dependent</span></span>
<span id="cb173-3"><a href="#cb173-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> Alias<span class="op">::</span>v;  <span class="co">// Alias is dependent</span></span>
<span id="cb173-4"><a href="#cb173-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb173-5"><a href="#cb173-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb173-6"><a href="#cb173-6" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> NS <span class="op">{</span></span>
<span id="cb173-7"><a href="#cb173-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> v <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb173-8"><a href="#cb173-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb173-9"><a href="#cb173-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb173-10"><a href="#cb173-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> a <span class="op">=</span> fn<span class="op">&lt;^^</span>NS<span class="op">&gt;()</span>;</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.expl.spec-explicit-specialization"><span>13.9.4 <a href="https://wg21.link/temp.expl.spec">[temp.expl.spec]</a></span>
Explicit specialization<a href="#temp.expl.spec-explicit-specialization" class="self-link"></a></h3>
<p>Modify paragraph 9 to allow
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s
to be used like incompletely-defined classes.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_428" id="pnum_428">9</a></span>
A <code class="sourceCode cpp"><em>simple-template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
that <span class="rm" style="color: #bf0303"><del>names</del></span>
<span class="addu">designates</span> a class template explicit
specialization that has been declared but not defined can be used
exactly like the names of other incompletely-defined classes (<span>6.8
<a href="https://wg21.link/basic.types">[basic.types]</a></span>).</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.deduct.general-general"><span>13.10.3.1
<a href="https://wg21.link/temp.deduct.general">[temp.deduct.general]</a></span>
General<a href="#temp.deduct.general-general" class="self-link"></a></h3>
<p>Cover
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s
in paragraph 2:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_429" id="pnum_429">2</a></span>
When an explicit template argument list is specified, if the given
<code class="sourceCode cpp"><em>template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>
is not valid (<span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span>), type
deduction fails. Otherwise, the specified template argument values are
substituted for the corresponding template parameters as specified
below.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.deduct.call-deducing-template-arguments-from-a-function-call"><span>13.10.3.2
<a href="https://wg21.link/temp.deduct.call">[temp.deduct.call]</a></span>
Deducing template arguments from a function call<a href="#temp.deduct.call-deducing-template-arguments-from-a-function-call" class="self-link"></a></h3>
<p>Modify paragraph 4.3 to treat parameter types of function templates
that are specified using
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>s
the same as parameter types that are specified using
<code class="sourceCode cpp"><em>simple-template-id</em></code>s.</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_430" id="pnum_430">(4.3)</a></span>
If <code class="sourceCode cpp">P</code> is a class and
<code class="sourceCode cpp">P</code> has the form
<code class="sourceCode cpp"><em>simple-template-id</em></code> <span class="addu">or <code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>splice-specialization-specifier</em></code></span>,
then the transformed <code class="sourceCode cpp">A</code> can be a
derived class <code class="sourceCode cpp">D</code> of the deduced
<code class="sourceCode cpp">A</code>. Likewise, if
<code class="sourceCode cpp">P</code> is a pointer to a class of the
form <code class="sourceCode cpp"><em>simple-template-id</em></code>
<span class="addu">or <code class="sourceCode cpp">typename<sub><em>opt</em></sub> <em>splice-specialization-specifier</em></code></span>,
the transformed <code class="sourceCode cpp">A</code> can be a pointer
to a derived class <code class="sourceCode cpp">D</code> pointed to by
the deduced <code class="sourceCode cpp">A</code>. However, if there is
a class <code class="sourceCode cpp">C</code> that is a (direct or
indirect) base class of <code class="sourceCode cpp">D</code> and
derived (directly or indirectly) from a class
<code class="sourceCode cpp">B</code> and that would be a valid deduced
<code class="sourceCode cpp">A</code>, the deduced
<code class="sourceCode cpp">A</code> cannot be
<code class="sourceCode cpp">B1</code> or pointer to
<code class="sourceCode cpp">B</code>, respectively.</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.deduct.type-deducing-template-arguments-from-a-type"><span>13.10.3.6
<a href="https://wg21.link/temp.deduct.type">[temp.deduct.type]</a></span>
Deducing template arguments from a type<a href="#temp.deduct.type-deducing-template-arguments-from-a-type" class="self-link"></a></h3>
<p>Add the operand of a
<code class="sourceCode cpp"><em>splice-specifier</em></code> to the
list of non-deduced contexts in paragraph 5:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_431" id="pnum_431">5</a></span>
The non-deduced contexts are:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_432" id="pnum_432">(5.1)</a></span>
The <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
of a type that was specified using a
<code class="sourceCode cpp"><em>qualified-id</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_433" id="pnum_433">(5.2)</a></span>
A <code class="sourceCode cpp"><em>pack-index-specifier</em></code> or a
<code class="sourceCode cpp"><em>pack-index-expression</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_434" id="pnum_434">(5.3)</a></span>
The <code class="sourceCode cpp"><em>expression</em></code> of a
<code class="sourceCode cpp"><em>decltype-specifier</em></code>.</li>
<li><span class="addu"><span class="marginalizedparent"><a class="marginalized" href="#pnum_435" id="pnum_435">(5.3+)</a></span>
The <code class="sourceCode cpp"><em>constant-expression</em></code> of
a
<code class="sourceCode cpp"><em>splice-specifier</em></code>.</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_436" id="pnum_436">(5.4)</a></span>
A constant template argument or an array bound in which a subexpression
references a template parameter.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_437" id="pnum_437">(5.5)</a></span>
…</li>
</ul>
</blockquote>
</div>
<p>Modify paragraph 20 to clarify that the construct enclosing a
template argument might also be a
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code>.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_438" id="pnum_438">20</a></span>
If <code class="sourceCode cpp">P</code> has a form that contains <code class="sourceCode cpp"><span class="op">&lt;</span>i<span class="op">&gt;</span></code>,
and if the type of <code class="sourceCode cpp">i</code> differs from
the type of the corresponding template parameter of the template named
by the enclosing
<code class="sourceCode cpp"><em>simple-template-id</em></code> <span class="addu">or
<code class="sourceCode cpp"><em>splice-specialization-specifier</em></code></span>,
deduction fails. If <code class="sourceCode cpp">P</code> has a form
that contains <code class="sourceCode cpp"><span class="op">[</span>i<span class="op">]</span></code>,
and if the type of <code class="sourceCode cpp">i</code> is not an
integral type, deduction fails.<sup>123</sup> If
<code class="sourceCode cpp">P</code> has a form that includes <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span>i<span class="op">)</span></code>
and the type of <code class="sourceCode cpp">i</code> is not
<code class="sourceCode cpp"><span class="dt">bool</span></code>,
deduction fails.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="cpp.cond-conditional-inclusion"><span>15.2 <a href="https://wg21.link/cpp.cond">[cpp.cond]</a></span> Conditional
inclusion<a href="#cpp.cond-conditional-inclusion" class="self-link"></a></h3>
<p>Extend paragraph 10 to clarify that
<code class="sourceCode cpp"><em>splice-specifier</em></code>s may not
appear in preprocessor directives, while also applying a “drive-by fix”
to disallow lambdas in the same context.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_439" id="pnum_439">10</a></span>
Preprocessing directives of the forms</p>
<div class="sourceCode" id="cb174"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb174-1"><a href="#cb174-1" aria-hidden="true" tabindex="-1"></a>     <span class="pp"># if      <em>constant-expression</em> <em>new-line</em> <em>group</em><sub><em>opt</em></sub></span></span>
<span id="cb174-2"><a href="#cb174-2" aria-hidden="true" tabindex="-1"></a>     <span class="pp"># elif    <em>constant-expression</em> <em>new-line</em> <em>group</em><sub><em>opt</em></sub></span></span></code></pre></div>
<p>check whether the controlling constant expression evaluates to
nonzero. <span class="addu">The program is ill-formed if a
<code class="sourceCode cpp"><em>splice-specifier</em></code> or
<code class="sourceCode cpp"><em>lambda-expression</em></code> appears
in the controlling constant expression.</span></p>
</blockquote>
</div>
<h2 data-number="5.2" id="library"><span class="header-section-number">5.2</span> Library<a href="#library" class="self-link"></a></h2>
<h3 class="unnumbered" id="structure.specifications-detailed-specifications"><span>16.3.2.4 <a href="https://wg21.link/structure.specifications">[structure.specifications]</a></span>
Detailed specifications<a href="#structure.specifications-detailed-specifications" class="self-link"></a></h3>
<p>For convenience, we’re going to add a new library element to
<span>16.3.2.4 <a href="https://wg21.link/structure.specifications">[structure.specifications]</a></span>/3:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_440" id="pnum_440">3</a></span>
Descriptions of function semantics contain the following elements (as
appropriate):</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_441" id="pnum_441">(3.1)</a></span>
<em>Constraints</em>: […]</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_442" id="pnum_442">(3.2)</a></span>
<em>Mandates</em>: the conditions that, if not met, render the program
ill-formed. […]</p></li>
</ul>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_443" id="pnum_443">(3.2+1)</a></span>
<em>Constant When</em>: the conditions that are required for a call to
the function to be a constant subexpression
([defns.const.subexpr]).</li>
</ul>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_444" id="pnum_444">4</a></span>
[…] Next, the semantics of the code sequence are determined by the
<em>Constraints</em>, <em>Mandates</em>, <span class="addu"><em>Constant
When</em>,</span> <em>Preconditions</em>, <em>Effects</em>,
<em>Synchronization</em>, <em>Postconditions</em>, <em>Returns</em>,
<em>Throws</em>, <em>Complexity</em>, <em>Remarks</em>, and
<em>Error</em> conditions specified for the function invocations
contained in the code sequence. […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="headers-headers"><span>16.4.2.3 <a href="https://wg21.link/headers">[headers]</a></span> Headers<a href="#headers-headers" class="self-link"></a></h3>
<p>Add <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
to [tab:headers.cpp].</p>
<div class="std">
<blockquote>
<table>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>algorithm<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>forward_list<span class="op">&gt;</span></code>
</td>
<td>
<span class="addu"><code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code></span>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>stack<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>any<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>fstream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>mutex<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>stacktrace<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>array<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>functional<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span><span class="kw">new</span><span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>stdexcept<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>atomic<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>future<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>numbers<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>stdfloat<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>barrier<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>generator<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>numeric<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>stop_token<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>bit<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>hazard_pointer<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>optional<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>streambuf<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>bitset<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>initializer_list<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>ostream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>string<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>charconv<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>inplace_vector<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>print<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>string_view<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>chrono<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>iomanip<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>queue<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>syncstream<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>compare<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>ios<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>random<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>system_error<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>complex<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>iosfwd<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>ranges<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>text_encoding<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>concepts<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>iostream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>ratio<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>thread<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>condition_variable<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>istream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>rcu<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>tuple<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>coroutine<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>iterator<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>regex<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>type_traits<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>debugging<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>latch<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>scoped_allocator<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>typeindex<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>deque<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>limits<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>semaphore<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>typeinfo<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>exception<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>linalg<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>set<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>unordered_map<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>execution<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>list<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>shared_mutex<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>unordered_set<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>expected<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>locale<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>simd<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>utility<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>filesystem<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>map<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>source_location<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>valarray<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>flat_map<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>mdspan<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>span<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>variant<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>flat_set<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>memory<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>spanstream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>vector<span class="op">&gt;</span></code>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>format<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>memory_resource<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>sstream<span class="op">&gt;</span></code>
</td>
<td>
<code class="sourceCode cpp"><span class="op">&lt;</span>version<span class="op">&gt;</span></code>
</td>
</tr>
</table>
</blockquote>
</div>
<h3 class="unnumbered" id="namespace.std-namespace-std"><span>16.4.5.2.1
<a href="https://wg21.link/namespace.std">[namespace.std]</a></span>
Namespace std<a href="#namespace.std-namespace-std" class="self-link"></a></h3>
<p>Insert before paragraph 7:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_445" id="pnum_445">6</a></span>
Let F denote a standard library function ([global.functions]), a
standard library static member function, or an instantiation of a
standard library function template. Unless F is designated an
<em>addressable function</em>, the behavior of a C++ program is
unspecified (possibly ill-formed) if it explicitly or implicitly
attempts to form a pointer to F. […]</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_446" id="pnum_446">6a</a></span>
Let F denote a standard library function or function template. Unless F
is designated an addressable function, it is unspecified if or how a
reflection value designating the associated entity can be formed. <span class="note"><span>[ <em>Note 1:</em> </span>For example, it is possible
that <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>members_of</code>
will not return reflections of standard library functions that an
implementation handles through an extra-linguistic mechanism.<span>
— <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_447" id="pnum_447">6b</a></span>
Let <code class="sourceCode cpp">C</code> denote a standard library
class or class template specialization. It is unspecified if or how a
reflection value can be formed to any private member of
<code class="sourceCode cpp">C</code>, or what the names of such members
may be.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_448" id="pnum_448">7</a></span>
A translation unit shall not declare namespace std to be an inline
namespace ([namespace.def]).</p>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.type.synop-header-type_traits-synopsis"><span>21.3.3 <a href="https://wg21.link/meta.type.synop">[meta.type.synop]</a></span>
Header <code class="sourceCode cpp"><span class="op">&lt;</span>type_traits<span class="op">&gt;</span></code>
synopsis<a href="#meta.type.synop-header-type_traits-synopsis" class="self-link"></a></h3>
<p>Add a new primary type category type trait:</p>
<div class="std">
<blockquote>
<p><strong>Header <code class="sourceCode cpp"><span class="op">&lt;</span>type_traits<span class="op">&gt;</span></code>
synopsis</strong></p>
<p>…</p>
<div>
<div class="sourceCode" id="cb175"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb175-1"><a href="#cb175-1" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.cat], primary type categories</span>
<span id="cb175-2"><a href="#cb175-2" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_void;</span>
<span id="cb175-3"><a href="#cb175-3" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-4"><a href="#cb175-4" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_function;</span>
<span id="cb175-5"><a href="#cb175-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt; struct is_reflection;</span></span>
<span id="cb175-6"><a href="#cb175-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-7"><a href="#cb175-7" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-8"><a href="#cb175-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-9"><a href="#cb175-9" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.prop], type properties</span>
<span id="cb175-10"><a href="#cb175-10" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_const;</span>
<span id="cb175-11"><a href="#cb175-11" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-12"><a href="#cb175-12" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_aggregate;</span>
<span id="cb175-13"><a href="#cb175-13" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt; struct is_consteval_only;</span></span>
<span id="cb175-14"><a href="#cb175-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-15"><a href="#cb175-15" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-16"><a href="#cb175-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-17"><a href="#cb175-17" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.cat], primary type categories</span>
<span id="cb175-18"><a href="#cb175-18" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb175-19"><a href="#cb175-19" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_void_v = is_void&lt;T&gt;::value;</span>
<span id="cb175-20"><a href="#cb175-20" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-21"><a href="#cb175-21" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb175-22"><a href="#cb175-22" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_function_v = is_function&lt;T&gt;::value;</span>
<span id="cb175-23"><a href="#cb175-23" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt;</span></span>
<span id="cb175-24"><a href="#cb175-24" aria-hidden="true" tabindex="-1"></a><span class="va">+     constexpr bool is_reflection_v = is_reflection&lt;T&gt;::value;</span></span>
<span id="cb175-25"><a href="#cb175-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-26"><a href="#cb175-26" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-27"><a href="#cb175-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb175-28"><a href="#cb175-28" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.prop], type properties</span>
<span id="cb175-29"><a href="#cb175-29" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb175-30"><a href="#cb175-30" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_const_v = is_const&lt;T&gt;::value;</span>
<span id="cb175-31"><a href="#cb175-31" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb175-32"><a href="#cb175-32" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb175-33"><a href="#cb175-33" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_aggregate_v = is_aggregate&lt;T&gt;::value;</span>
<span id="cb175-34"><a href="#cb175-34" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt;</span></span>
<span id="cb175-35"><a href="#cb175-35" aria-hidden="true" tabindex="-1"></a><span class="va">+     constexpr bool is_consteval_only_v = is_consteval_only&lt;T&gt;::value;</span></span>
<span id="cb175-36"><a href="#cb175-36" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb175-37"><a href="#cb175-37" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_signed_v = is_signed&lt;T&gt;::value;</span>
<span id="cb175-38"><a href="#cb175-38" aria-hidden="true" tabindex="-1"></a>...</span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.unary.cat-primary-type-categories"><span>21.3.5.2 <a href="https://wg21.link/meta.unary.cat">[meta.unary.cat]</a></span>
Primary type categories<a href="#meta.unary.cat-primary-type-categories" class="self-link"></a></h3>
<p>Add the <code class="sourceCode cpp">is_reflection</code> primary
type category to the table in paragraph 3:</p>
<div class="std">
<blockquote>
<table>
<tr style="text-align:center">
<th>
Template
</th>
<th>
Condition
</th>
<th>
Comments
</th>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb176"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb176-1"><a href="#cb176-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb176-2"><a href="#cb176-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_void;</span></code></pre></div>
</td>
<td style="text-align:center; vertical-align: middle">
<code class="sourceCode cpp">T</code> is
<code class="sourceCode cpp"><span class="dt">void</span></code>
</td>
<td>
</td>
</tr>
<tr style="text-align:center">
<td>
…
</td>
<td>
…
</td>
<td>
…
</td>
</tr>
<tr>
<td>
<div class="addu">
<div class="sourceCode" id="cb177"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb177-1"><a href="#cb177-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb177-2"><a href="#cb177-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_reflection;</span></code></pre></div>
</div>
</td>
<td style="text-align:center; vertical-align: middle">
<div class="addu">
<p><code class="sourceCode cpp">T</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code></p>
</div>
</td>
<td>
<div class="addu">
<p><br></p>
</div>
</td>
</tr>
</table>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.unary.prop-type-properties"><span>21.3.5.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a></span>
Type properties<a href="#meta.unary.prop-type-properties" class="self-link"></a></h3>
<p>Add the <code class="sourceCode cpp">is_consteval_only</code> type
trait to table 51 following paragraph 5:</p>
<div class="std">
<blockquote>
<table>
<tr style="text-align:center">
<th>
Template
</th>
<th>
Condition
</th>
<th>
Preconditions
</th>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb178"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb178-1"><a href="#cb178-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb178-2"><a href="#cb178-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_const;</span></code></pre></div>
</td>
<td style="text-align:center; vertical-align: middle">
<code class="sourceCode cpp">T</code> is const-qualified
([basic.type.qualifier])
</td>
<td>
</td>
</tr>
<tr style="text-align:center">
<td>
…
</td>
<td>
…
</td>
<td>
…
</td>
</tr>
<tr>
<td>
<div class="addu">
<div class="sourceCode" id="cb179"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb179-1"><a href="#cb179-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb179-2"><a href="#cb179-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> is_consteval_only;</span></code></pre></div>
</div>
</td>
<td style="text-align:center; vertical-align: middle">
<div class="addu">
<p><code class="sourceCode cpp">T</code> is consteval-only
([basic.types.general])</p>
</div>
</td>
<td>
<div class="addu">
<p><br></p>
</div>
</td>
</tr>
</table>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.synop-header-meta-synopsis">[meta.reflection.synop]
Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis<a href="#meta.reflection.synop-header-meta-synopsis" class="self-link"></a></h3>
<p>Add a new subsection in <span>21 <a href="https://wg21.link/meta">[meta]</a></span> after <span>21.3 <a href="https://wg21.link/type.traits">[type.traits]</a></span>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis</strong></p>
<div class="sourceCode" id="cb180"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb180-1"><a href="#cb180-1" aria-hidden="true" tabindex="-1"></a>#include &lt;initializer_list&gt;</span>
<span id="cb180-2"><a href="#cb180-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-3"><a href="#cb180-3" aria-hidden="true" tabindex="-1"></a>namespace std::meta {</span>
<span id="cb180-4"><a href="#cb180-4" aria-hidden="true" tabindex="-1"></a>  using info = decltype(^^::);</span>
<span id="cb180-5"><a href="#cb180-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-6"><a href="#cb180-6" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.operators], operator representations</span>
<span id="cb180-7"><a href="#cb180-7" aria-hidden="true" tabindex="-1"></a>  enum class operators {</span>
<span id="cb180-8"><a href="#cb180-8" aria-hidden="true" tabindex="-1"></a>    <em>see below</em>;</span>
<span id="cb180-9"><a href="#cb180-9" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb180-10"><a href="#cb180-10" aria-hidden="true" tabindex="-1"></a>  using enum operators;</span>
<span id="cb180-11"><a href="#cb180-11" aria-hidden="true" tabindex="-1"></a>  consteval operators operator_of(info r);</span>
<span id="cb180-12"><a href="#cb180-12" aria-hidden="true" tabindex="-1"></a>  consteval string_view symbol_of(operators op);</span>
<span id="cb180-13"><a href="#cb180-13" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8symbol_of(operators op);</span>
<span id="cb180-14"><a href="#cb180-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-15"><a href="#cb180-15" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.names], reflection names and locations</span>
<span id="cb180-16"><a href="#cb180-16" aria-hidden="true" tabindex="-1"></a>  consteval bool has_identifier(info r);</span>
<span id="cb180-17"><a href="#cb180-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-18"><a href="#cb180-18" aria-hidden="true" tabindex="-1"></a>  consteval string_view identifier_of(info r);</span>
<span id="cb180-19"><a href="#cb180-19" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8identifier_of(info r);</span>
<span id="cb180-20"><a href="#cb180-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-21"><a href="#cb180-21" aria-hidden="true" tabindex="-1"></a>  consteval string_view display_string_of(info r);</span>
<span id="cb180-22"><a href="#cb180-22" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8display_string_of(info r);</span>
<span id="cb180-23"><a href="#cb180-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-24"><a href="#cb180-24" aria-hidden="true" tabindex="-1"></a>  consteval source_location source_location_of(info r);</span>
<span id="cb180-25"><a href="#cb180-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-26"><a href="#cb180-26" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.queries], reflection queries</span>
<span id="cb180-27"><a href="#cb180-27" aria-hidden="true" tabindex="-1"></a>  consteval info type_of(info r);</span>
<span id="cb180-28"><a href="#cb180-28" aria-hidden="true" tabindex="-1"></a>  consteval info object_of(info r);</span>
<span id="cb180-29"><a href="#cb180-29" aria-hidden="true" tabindex="-1"></a>  consteval info constant_of(info r);</span>
<span id="cb180-30"><a href="#cb180-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-31"><a href="#cb180-31" aria-hidden="true" tabindex="-1"></a>  consteval bool is_public(info r);</span>
<span id="cb180-32"><a href="#cb180-32" aria-hidden="true" tabindex="-1"></a>  consteval bool is_protected(info r);</span>
<span id="cb180-33"><a href="#cb180-33" aria-hidden="true" tabindex="-1"></a>  consteval bool is_private(info r);</span>
<span id="cb180-34"><a href="#cb180-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-35"><a href="#cb180-35" aria-hidden="true" tabindex="-1"></a>  consteval bool is_virtual(info r);</span>
<span id="cb180-36"><a href="#cb180-36" aria-hidden="true" tabindex="-1"></a>  consteval bool is_pure_virtual(info r);</span>
<span id="cb180-37"><a href="#cb180-37" aria-hidden="true" tabindex="-1"></a>  consteval bool is_override(info r);</span>
<span id="cb180-38"><a href="#cb180-38" aria-hidden="true" tabindex="-1"></a>  consteval bool is_final(info r);</span>
<span id="cb180-39"><a href="#cb180-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-40"><a href="#cb180-40" aria-hidden="true" tabindex="-1"></a>  consteval bool is_deleted(info r);</span>
<span id="cb180-41"><a href="#cb180-41" aria-hidden="true" tabindex="-1"></a>  consteval bool is_defaulted(info r);</span>
<span id="cb180-42"><a href="#cb180-42" aria-hidden="true" tabindex="-1"></a>  consteval bool is_user_provided(info r);</span>
<span id="cb180-43"><a href="#cb180-43" aria-hidden="true" tabindex="-1"></a>  consteval bool is_user_declared(info r);</span>
<span id="cb180-44"><a href="#cb180-44" aria-hidden="true" tabindex="-1"></a>  consteval bool is_explicit(info r);</span>
<span id="cb180-45"><a href="#cb180-45" aria-hidden="true" tabindex="-1"></a>  consteval bool is_noexcept(info r);</span>
<span id="cb180-46"><a href="#cb180-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-47"><a href="#cb180-47" aria-hidden="true" tabindex="-1"></a>  consteval bool is_bit_field(info r);</span>
<span id="cb180-48"><a href="#cb180-48" aria-hidden="true" tabindex="-1"></a>  consteval bool is_enumerator(info r);</span>
<span id="cb180-49"><a href="#cb180-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-50"><a href="#cb180-50" aria-hidden="true" tabindex="-1"></a>  consteval bool is_const(info r);</span>
<span id="cb180-51"><a href="#cb180-51" aria-hidden="true" tabindex="-1"></a>  consteval bool is_volatile(info r);</span>
<span id="cb180-52"><a href="#cb180-52" aria-hidden="true" tabindex="-1"></a>  consteval bool is_mutable_member(info r);</span>
<span id="cb180-53"><a href="#cb180-53" aria-hidden="true" tabindex="-1"></a>  consteval bool is_lvalue_reference_qualified(info r);</span>
<span id="cb180-54"><a href="#cb180-54" aria-hidden="true" tabindex="-1"></a>  consteval bool is_rvalue_reference_qualified(info r);</span>
<span id="cb180-55"><a href="#cb180-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-56"><a href="#cb180-56" aria-hidden="true" tabindex="-1"></a>  consteval bool has_static_storage_duration(info r);</span>
<span id="cb180-57"><a href="#cb180-57" aria-hidden="true" tabindex="-1"></a>  consteval bool has_thread_storage_duration(info r);</span>
<span id="cb180-58"><a href="#cb180-58" aria-hidden="true" tabindex="-1"></a>  consteval bool has_automatic_storage_duration(info r);</span>
<span id="cb180-59"><a href="#cb180-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-60"><a href="#cb180-60" aria-hidden="true" tabindex="-1"></a>  consteval bool has_internal_linkage(info r);</span>
<span id="cb180-61"><a href="#cb180-61" aria-hidden="true" tabindex="-1"></a>  consteval bool has_module_linkage(info r);</span>
<span id="cb180-62"><a href="#cb180-62" aria-hidden="true" tabindex="-1"></a>  consteval bool has_external_linkage(info r);</span>
<span id="cb180-63"><a href="#cb180-63" aria-hidden="true" tabindex="-1"></a>  consteval bool has_c_language_linkage(info r);</span>
<span id="cb180-64"><a href="#cb180-64" aria-hidden="true" tabindex="-1"></a>  consteval bool has_linkage(info r);</span>
<span id="cb180-65"><a href="#cb180-65" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-66"><a href="#cb180-66" aria-hidden="true" tabindex="-1"></a>  consteval bool is_complete_type(info r);</span>
<span id="cb180-67"><a href="#cb180-67" aria-hidden="true" tabindex="-1"></a>  consteval bool is_enumerable_type(info r);</span>
<span id="cb180-68"><a href="#cb180-68" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-69"><a href="#cb180-69" aria-hidden="true" tabindex="-1"></a>  consteval bool is_variable(info r);</span>
<span id="cb180-70"><a href="#cb180-70" aria-hidden="true" tabindex="-1"></a>  consteval bool is_type(info r);</span>
<span id="cb180-71"><a href="#cb180-71" aria-hidden="true" tabindex="-1"></a>  consteval bool is_namespace(info r);</span>
<span id="cb180-72"><a href="#cb180-72" aria-hidden="true" tabindex="-1"></a>  consteval bool is_type_alias(info r);</span>
<span id="cb180-73"><a href="#cb180-73" aria-hidden="true" tabindex="-1"></a>  consteval bool is_namespace_alias(info r);</span>
<span id="cb180-74"><a href="#cb180-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-75"><a href="#cb180-75" aria-hidden="true" tabindex="-1"></a>  consteval bool is_function(info r);</span>
<span id="cb180-76"><a href="#cb180-76" aria-hidden="true" tabindex="-1"></a>  consteval bool is_conversion_function(info r);</span>
<span id="cb180-77"><a href="#cb180-77" aria-hidden="true" tabindex="-1"></a>  consteval bool is_operator_function(info r);</span>
<span id="cb180-78"><a href="#cb180-78" aria-hidden="true" tabindex="-1"></a>  consteval bool is_literal_operator(info r);</span>
<span id="cb180-79"><a href="#cb180-79" aria-hidden="true" tabindex="-1"></a>  consteval bool is_special_member_function(info r);</span>
<span id="cb180-80"><a href="#cb180-80" aria-hidden="true" tabindex="-1"></a>  consteval bool is_constructor(info r);</span>
<span id="cb180-81"><a href="#cb180-81" aria-hidden="true" tabindex="-1"></a>  consteval bool is_default_constructor(info r);</span>
<span id="cb180-82"><a href="#cb180-82" aria-hidden="true" tabindex="-1"></a>  consteval bool is_copy_constructor(info r);</span>
<span id="cb180-83"><a href="#cb180-83" aria-hidden="true" tabindex="-1"></a>  consteval bool is_move_constructor(info r);</span>
<span id="cb180-84"><a href="#cb180-84" aria-hidden="true" tabindex="-1"></a>  consteval bool is_assignment(info r);</span>
<span id="cb180-85"><a href="#cb180-85" aria-hidden="true" tabindex="-1"></a>  consteval bool is_copy_assignment(info r);</span>
<span id="cb180-86"><a href="#cb180-86" aria-hidden="true" tabindex="-1"></a>  consteval bool is_move_assignment(info r);</span>
<span id="cb180-87"><a href="#cb180-87" aria-hidden="true" tabindex="-1"></a>  consteval bool is_destructor(info r);</span>
<span id="cb180-88"><a href="#cb180-88" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-89"><a href="#cb180-89" aria-hidden="true" tabindex="-1"></a>  consteval bool is_template(info r);</span>
<span id="cb180-90"><a href="#cb180-90" aria-hidden="true" tabindex="-1"></a>  consteval bool is_function_template(info r);</span>
<span id="cb180-91"><a href="#cb180-91" aria-hidden="true" tabindex="-1"></a>  consteval bool is_variable_template(info r);</span>
<span id="cb180-92"><a href="#cb180-92" aria-hidden="true" tabindex="-1"></a>  consteval bool is_class_template(info r);</span>
<span id="cb180-93"><a href="#cb180-93" aria-hidden="true" tabindex="-1"></a>  consteval bool is_alias_template(info r);</span>
<span id="cb180-94"><a href="#cb180-94" aria-hidden="true" tabindex="-1"></a>  consteval bool is_conversion_function_template(info r);</span>
<span id="cb180-95"><a href="#cb180-95" aria-hidden="true" tabindex="-1"></a>  consteval bool is_operator_function_template(info r);</span>
<span id="cb180-96"><a href="#cb180-96" aria-hidden="true" tabindex="-1"></a>  consteval bool is_literal_operator_template(info r);</span>
<span id="cb180-97"><a href="#cb180-97" aria-hidden="true" tabindex="-1"></a>  consteval bool is_constructor_template(info r);</span>
<span id="cb180-98"><a href="#cb180-98" aria-hidden="true" tabindex="-1"></a>  consteval bool is_concept(info r);</span>
<span id="cb180-99"><a href="#cb180-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-100"><a href="#cb180-100" aria-hidden="true" tabindex="-1"></a>  consteval bool is_value(info r);</span>
<span id="cb180-101"><a href="#cb180-101" aria-hidden="true" tabindex="-1"></a>  consteval bool is_object(info r);</span>
<span id="cb180-102"><a href="#cb180-102" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-103"><a href="#cb180-103" aria-hidden="true" tabindex="-1"></a>  consteval bool is_structured_binding(info r);</span>
<span id="cb180-104"><a href="#cb180-104" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-105"><a href="#cb180-105" aria-hidden="true" tabindex="-1"></a>  consteval bool is_class_member(info r);</span>
<span id="cb180-106"><a href="#cb180-106" aria-hidden="true" tabindex="-1"></a>  consteval bool is_namespace_member(info r);</span>
<span id="cb180-107"><a href="#cb180-107" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nonstatic_data_member(info r);</span>
<span id="cb180-108"><a href="#cb180-108" aria-hidden="true" tabindex="-1"></a>  consteval bool is_static_member(info r);</span>
<span id="cb180-109"><a href="#cb180-109" aria-hidden="true" tabindex="-1"></a>  consteval bool is_base(info r);</span>
<span id="cb180-110"><a href="#cb180-110" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-111"><a href="#cb180-111" aria-hidden="true" tabindex="-1"></a>  consteval bool has_default_member_initializer(info r);</span>
<span id="cb180-112"><a href="#cb180-112" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-113"><a href="#cb180-113" aria-hidden="true" tabindex="-1"></a>  consteval bool has_parent(info r);</span>
<span id="cb180-114"><a href="#cb180-114" aria-hidden="true" tabindex="-1"></a>  consteval info parent_of(info r);</span>
<span id="cb180-115"><a href="#cb180-115" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-116"><a href="#cb180-116" aria-hidden="true" tabindex="-1"></a>  consteval info dealias(info r);</span>
<span id="cb180-117"><a href="#cb180-117" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-118"><a href="#cb180-118" aria-hidden="true" tabindex="-1"></a>  consteval bool has_template_arguments(info r);</span>
<span id="cb180-119"><a href="#cb180-119" aria-hidden="true" tabindex="-1"></a>  consteval info template_of(info r);</span>
<span id="cb180-120"><a href="#cb180-120" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; template_arguments_of(info r);</span>
<span id="cb180-121"><a href="#cb180-121" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-122"><a href="#cb180-122" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.access.context], access control context</span>
<span id="cb180-123"><a href="#cb180-123" aria-hidden="true" tabindex="-1"></a>  struct access_context;</span>
<span id="cb180-124"><a href="#cb180-124" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-125"><a href="#cb180-125" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.access.queries], member accessessibility queries</span>
<span id="cb180-126"><a href="#cb180-126" aria-hidden="true" tabindex="-1"></a>  consteval bool is_accessible(info r, access_context ctx);</span>
<span id="cb180-127"><a href="#cb180-127" aria-hidden="true" tabindex="-1"></a>  consteval bool has_inaccessible_nonstatic_data_members(</span>
<span id="cb180-128"><a href="#cb180-128" aria-hidden="true" tabindex="-1"></a>      info r,</span>
<span id="cb180-129"><a href="#cb180-129" aria-hidden="true" tabindex="-1"></a>      access_context ctx);</span>
<span id="cb180-130"><a href="#cb180-130" aria-hidden="true" tabindex="-1"></a>  consteval bool has_inaccessible_bases(info r, access_context ctx);</span>
<span id="cb180-131"><a href="#cb180-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-132"><a href="#cb180-132" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.member.queries], reflection member queries</span>
<span id="cb180-133"><a href="#cb180-133" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; members_of(info r, access_context ctx);</span>
<span id="cb180-134"><a href="#cb180-134" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; bases_of(info type, access_context ctx);</span>
<span id="cb180-135"><a href="#cb180-135" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; static_data_members_of(info type, access_context ctx);</span>
<span id="cb180-136"><a href="#cb180-136" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; nonstatic_data_members_of(info type, access_context ctx);</span>
<span id="cb180-137"><a href="#cb180-137" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; enumerators_of(info type_enum);</span>
<span id="cb180-138"><a href="#cb180-138" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-139"><a href="#cb180-139" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.layout], reflection layout queries</span>
<span id="cb180-140"><a href="#cb180-140" aria-hidden="true" tabindex="-1"></a>  struct member_offset;</span>
<span id="cb180-141"><a href="#cb180-141" aria-hidden="true" tabindex="-1"></a>  consteval member_offset offset_of(info r);</span>
<span id="cb180-142"><a href="#cb180-142" aria-hidden="true" tabindex="-1"></a>  consteval size_t size_of(info r);</span>
<span id="cb180-143"><a href="#cb180-143" aria-hidden="true" tabindex="-1"></a>  consteval size_t alignment_of(info r);</span>
<span id="cb180-144"><a href="#cb180-144" aria-hidden="true" tabindex="-1"></a>  consteval size_t bit_size_of(info r);</span>
<span id="cb180-145"><a href="#cb180-145" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-146"><a href="#cb180-146" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.extract], value extraction</span>
<span id="cb180-147"><a href="#cb180-147" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb180-148"><a href="#cb180-148" aria-hidden="true" tabindex="-1"></a>    consteval T extract(info);</span>
<span id="cb180-149"><a href="#cb180-149" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-150"><a href="#cb180-150" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.substitute], reflection substitution</span>
<span id="cb180-151"><a href="#cb180-151" aria-hidden="true" tabindex="-1"></a>  template &lt;class R&gt;</span>
<span id="cb180-152"><a href="#cb180-152" aria-hidden="true" tabindex="-1"></a>    concept reflection_range = <em>see below</em>;</span>
<span id="cb180-153"><a href="#cb180-153" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-154"><a href="#cb180-154" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-155"><a href="#cb180-155" aria-hidden="true" tabindex="-1"></a>    consteval bool can_substitute(info templ, R&amp;&amp; arguments);</span>
<span id="cb180-156"><a href="#cb180-156" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-157"><a href="#cb180-157" aria-hidden="true" tabindex="-1"></a>    consteval info substitute(info templ, R&amp;&amp; arguments);</span>
<span id="cb180-158"><a href="#cb180-158" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-159"><a href="#cb180-159" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.result], expression result reflection</span>
<span id="cb180-160"><a href="#cb180-160" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb180-161"><a href="#cb180-161" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_constant(const T&amp; value);</span>
<span id="cb180-162"><a href="#cb180-162" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb180-163"><a href="#cb180-163" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_object(T&amp; object);</span>
<span id="cb180-164"><a href="#cb180-164" aria-hidden="true" tabindex="-1"></a>  template&lt;class T&gt;</span>
<span id="cb180-165"><a href="#cb180-165" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_function(T&amp; fn);</span>
<span id="cb180-166"><a href="#cb180-166" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-167"><a href="#cb180-167" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.define.aggregate], class definition generation</span>
<span id="cb180-168"><a href="#cb180-168" aria-hidden="true" tabindex="-1"></a>  struct data_member_options;</span>
<span id="cb180-169"><a href="#cb180-169" aria-hidden="true" tabindex="-1"></a>  consteval info data_member_spec(info type,</span>
<span id="cb180-170"><a href="#cb180-170" aria-hidden="true" tabindex="-1"></a>                                  data_member_options options);</span>
<span id="cb180-171"><a href="#cb180-171" aria-hidden="true" tabindex="-1"></a>  consteval bool is_data_member_spec(info r);</span>
<span id="cb180-172"><a href="#cb180-172" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-173"><a href="#cb180-173" aria-hidden="true" tabindex="-1"></a>  consteval info define_aggregate(info type_class, R&amp;&amp;);</span>
<span id="cb180-174"><a href="#cb180-174" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-175"><a href="#cb180-175" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.unary.cat], primary type categories</span>
<span id="cb180-176"><a href="#cb180-176" aria-hidden="true" tabindex="-1"></a>  consteval bool is_void_type(info type);</span>
<span id="cb180-177"><a href="#cb180-177" aria-hidden="true" tabindex="-1"></a>  consteval bool is_null_pointer_type(info type);</span>
<span id="cb180-178"><a href="#cb180-178" aria-hidden="true" tabindex="-1"></a>  consteval bool is_integral_type(info type);</span>
<span id="cb180-179"><a href="#cb180-179" aria-hidden="true" tabindex="-1"></a>  consteval bool is_floating_point_type(info type);</span>
<span id="cb180-180"><a href="#cb180-180" aria-hidden="true" tabindex="-1"></a>  consteval bool is_array_type(info type);</span>
<span id="cb180-181"><a href="#cb180-181" aria-hidden="true" tabindex="-1"></a>  consteval bool is_pointer_type(info type);</span>
<span id="cb180-182"><a href="#cb180-182" aria-hidden="true" tabindex="-1"></a>  consteval bool is_lvalue_reference_type(info type);</span>
<span id="cb180-183"><a href="#cb180-183" aria-hidden="true" tabindex="-1"></a>  consteval bool is_rvalue_reference_type(info type);</span>
<span id="cb180-184"><a href="#cb180-184" aria-hidden="true" tabindex="-1"></a>  consteval bool is_member_object_pointer_type(info type);</span>
<span id="cb180-185"><a href="#cb180-185" aria-hidden="true" tabindex="-1"></a>  consteval bool is_member_function_pointer_type(info type);</span>
<span id="cb180-186"><a href="#cb180-186" aria-hidden="true" tabindex="-1"></a>  consteval bool is_enum_type(info type);</span>
<span id="cb180-187"><a href="#cb180-187" aria-hidden="true" tabindex="-1"></a>  consteval bool is_union_type(info type);</span>
<span id="cb180-188"><a href="#cb180-188" aria-hidden="true" tabindex="-1"></a>  consteval bool is_class_type(info type);</span>
<span id="cb180-189"><a href="#cb180-189" aria-hidden="true" tabindex="-1"></a>  consteval bool is_function_type(info type);</span>
<span id="cb180-190"><a href="#cb180-190" aria-hidden="true" tabindex="-1"></a>  consteval bool is_reflection_type(info type);</span>
<span id="cb180-191"><a href="#cb180-191" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-192"><a href="#cb180-192" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.unary.comp], composite type categories</span>
<span id="cb180-193"><a href="#cb180-193" aria-hidden="true" tabindex="-1"></a>  consteval bool is_reference_type(info type);</span>
<span id="cb180-194"><a href="#cb180-194" aria-hidden="true" tabindex="-1"></a>  consteval bool is_arithmetic_type(info type);</span>
<span id="cb180-195"><a href="#cb180-195" aria-hidden="true" tabindex="-1"></a>  consteval bool is_fundamental_type(info type);</span>
<span id="cb180-196"><a href="#cb180-196" aria-hidden="true" tabindex="-1"></a>  consteval bool is_object_type(info type);</span>
<span id="cb180-197"><a href="#cb180-197" aria-hidden="true" tabindex="-1"></a>  consteval bool is_scalar_type(info type);</span>
<span id="cb180-198"><a href="#cb180-198" aria-hidden="true" tabindex="-1"></a>  consteval bool is_compound_type(info type);</span>
<span id="cb180-199"><a href="#cb180-199" aria-hidden="true" tabindex="-1"></a>  consteval bool is_member_pointer_type(info type);</span>
<span id="cb180-200"><a href="#cb180-200" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-201"><a href="#cb180-201" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.unary.prop], type properties</span>
<span id="cb180-202"><a href="#cb180-202" aria-hidden="true" tabindex="-1"></a>  consteval bool is_const_type(info type);</span>
<span id="cb180-203"><a href="#cb180-203" aria-hidden="true" tabindex="-1"></a>  consteval bool is_volatile_type(info type);</span>
<span id="cb180-204"><a href="#cb180-204" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_copyable_type(info type);</span>
<span id="cb180-205"><a href="#cb180-205" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_relocatable_type(info type);</span>
<span id="cb180-206"><a href="#cb180-206" aria-hidden="true" tabindex="-1"></a>  consteval bool is_replaceable_type(info type);</span>
<span id="cb180-207"><a href="#cb180-207" aria-hidden="true" tabindex="-1"></a>  consteval bool is_standard_layout_type(info type);</span>
<span id="cb180-208"><a href="#cb180-208" aria-hidden="true" tabindex="-1"></a>  consteval bool is_empty_type(info type);</span>
<span id="cb180-209"><a href="#cb180-209" aria-hidden="true" tabindex="-1"></a>  consteval bool is_polymorphic_type(info type);</span>
<span id="cb180-210"><a href="#cb180-210" aria-hidden="true" tabindex="-1"></a>  consteval bool is_abstract_type(info type);</span>
<span id="cb180-211"><a href="#cb180-211" aria-hidden="true" tabindex="-1"></a>  consteval bool is_final_type(info type);</span>
<span id="cb180-212"><a href="#cb180-212" aria-hidden="true" tabindex="-1"></a>  consteval bool is_aggregate_type(info type);</span>
<span id="cb180-213"><a href="#cb180-213" aria-hidden="true" tabindex="-1"></a>  consteval bool is_consteval_only_type(info type);</span>
<span id="cb180-214"><a href="#cb180-214" aria-hidden="true" tabindex="-1"></a>  consteval bool is_signed_type(info type);</span>
<span id="cb180-215"><a href="#cb180-215" aria-hidden="true" tabindex="-1"></a>  consteval bool is_unsigned_type(info type);</span>
<span id="cb180-216"><a href="#cb180-216" aria-hidden="true" tabindex="-1"></a>  consteval bool is_bounded_array_type(info type);</span>
<span id="cb180-217"><a href="#cb180-217" aria-hidden="true" tabindex="-1"></a>  consteval bool is_unbounded_array_type(info type);</span>
<span id="cb180-218"><a href="#cb180-218" aria-hidden="true" tabindex="-1"></a>  consteval bool is_scoped_enum_type(info type);</span>
<span id="cb180-219"><a href="#cb180-219" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-220"><a href="#cb180-220" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-221"><a href="#cb180-221" aria-hidden="true" tabindex="-1"></a>    consteval bool is_constructible_type(info type, R&amp;&amp; type_args);</span>
<span id="cb180-222"><a href="#cb180-222" aria-hidden="true" tabindex="-1"></a>  consteval bool is_default_constructible_type(info type);</span>
<span id="cb180-223"><a href="#cb180-223" aria-hidden="true" tabindex="-1"></a>  consteval bool is_copy_constructible_type(info type);</span>
<span id="cb180-224"><a href="#cb180-224" aria-hidden="true" tabindex="-1"></a>  consteval bool is_move_constructible_type(info type);</span>
<span id="cb180-225"><a href="#cb180-225" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-226"><a href="#cb180-226" aria-hidden="true" tabindex="-1"></a>  consteval bool is_assignable_type(info type_dst, info type_src);</span>
<span id="cb180-227"><a href="#cb180-227" aria-hidden="true" tabindex="-1"></a>  consteval bool is_copy_assignable_type(info type);</span>
<span id="cb180-228"><a href="#cb180-228" aria-hidden="true" tabindex="-1"></a>  consteval bool is_move_assignable_type(info type);</span>
<span id="cb180-229"><a href="#cb180-229" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-230"><a href="#cb180-230" aria-hidden="true" tabindex="-1"></a>  consteval bool is_swappable_with_type(info type_dst, info type_src);</span>
<span id="cb180-231"><a href="#cb180-231" aria-hidden="true" tabindex="-1"></a>  consteval bool is_swappable_type(info type);</span>
<span id="cb180-232"><a href="#cb180-232" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-233"><a href="#cb180-233" aria-hidden="true" tabindex="-1"></a>  consteval bool is_destructible_type(info type);</span>
<span id="cb180-234"><a href="#cb180-234" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-235"><a href="#cb180-235" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-236"><a href="#cb180-236" aria-hidden="true" tabindex="-1"></a>    consteval bool is_trivially_constructible_type(info type, R&amp;&amp; type_args);</span>
<span id="cb180-237"><a href="#cb180-237" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_default_constructible_type(info type);</span>
<span id="cb180-238"><a href="#cb180-238" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_copy_constructible_type(info type);</span>
<span id="cb180-239"><a href="#cb180-239" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_move_constructible_type(info type);</span>
<span id="cb180-240"><a href="#cb180-240" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-241"><a href="#cb180-241" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_assignable_type(info type_dst, info type_src);</span>
<span id="cb180-242"><a href="#cb180-242" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_copy_assignable_type(info type);</span>
<span id="cb180-243"><a href="#cb180-243" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_move_assignable_type(info type);</span>
<span id="cb180-244"><a href="#cb180-244" aria-hidden="true" tabindex="-1"></a>  consteval bool is_trivially_destructible_type(info type);</span>
<span id="cb180-245"><a href="#cb180-245" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-246"><a href="#cb180-246" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-247"><a href="#cb180-247" aria-hidden="true" tabindex="-1"></a>    consteval bool is_nothrow_constructible_type(info type, R&amp;&amp; type_args);</span>
<span id="cb180-248"><a href="#cb180-248" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_default_constructible_type(info type);</span>
<span id="cb180-249"><a href="#cb180-249" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_copy_constructible_type(info type);</span>
<span id="cb180-250"><a href="#cb180-250" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_move_constructible_type(info type);</span>
<span id="cb180-251"><a href="#cb180-251" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-252"><a href="#cb180-252" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_assignable_type(info type_dst, info type_src);</span>
<span id="cb180-253"><a href="#cb180-253" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_copy_assignable_type(info type);</span>
<span id="cb180-254"><a href="#cb180-254" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_move_assignable_type(info type);</span>
<span id="cb180-255"><a href="#cb180-255" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-256"><a href="#cb180-256" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_swappable_with_type(info type_dst, info type_src);</span>
<span id="cb180-257"><a href="#cb180-257" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_swappable_type(info type);</span>
<span id="cb180-258"><a href="#cb180-258" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-259"><a href="#cb180-259" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_destructible_type(info type);</span>
<span id="cb180-260"><a href="#cb180-260" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_relocatable_type(info type);</span>
<span id="cb180-261"><a href="#cb180-261" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-262"><a href="#cb180-262" aria-hidden="true" tabindex="-1"></a>  consteval bool is_implicit_lifetime_type(info type);</span>
<span id="cb180-263"><a href="#cb180-263" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-264"><a href="#cb180-264" aria-hidden="true" tabindex="-1"></a>  consteval bool has_virtual_destructor(info type);</span>
<span id="cb180-265"><a href="#cb180-265" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-266"><a href="#cb180-266" aria-hidden="true" tabindex="-1"></a>  consteval bool has_unique_object_representations(info type);</span>
<span id="cb180-267"><a href="#cb180-267" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-268"><a href="#cb180-268" aria-hidden="true" tabindex="-1"></a>  consteval bool reference_constructs_from_temporary(info type_dst, info type_src);</span>
<span id="cb180-269"><a href="#cb180-269" aria-hidden="true" tabindex="-1"></a>  consteval bool reference_converts_from_temporary(info type_dst, info type_src);</span>
<span id="cb180-270"><a href="#cb180-270" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-271"><a href="#cb180-271" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.unary.prop.query], type property queries</span>
<span id="cb180-272"><a href="#cb180-272" aria-hidden="true" tabindex="-1"></a>  consteval size_t rank(info type);</span>
<span id="cb180-273"><a href="#cb180-273" aria-hidden="true" tabindex="-1"></a>  consteval size_t extent(info type, unsigned i = 0);</span>
<span id="cb180-274"><a href="#cb180-274" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-275"><a href="#cb180-275" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.rel], type relations</span>
<span id="cb180-276"><a href="#cb180-276" aria-hidden="true" tabindex="-1"></a>  consteval bool is_same_type(info type1, info type2);</span>
<span id="cb180-277"><a href="#cb180-277" aria-hidden="true" tabindex="-1"></a>  consteval bool is_base_of_type(info type_base, info type_derived);</span>
<span id="cb180-278"><a href="#cb180-278" aria-hidden="true" tabindex="-1"></a>  consteval bool is_virtual_base_of_type(info type_base, info type_derived);</span>
<span id="cb180-279"><a href="#cb180-279" aria-hidden="true" tabindex="-1"></a>  consteval bool is_convertible_type(info type_src, info type_dst);</span>
<span id="cb180-280"><a href="#cb180-280" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nothrow_convertible_type(info type_src, info type_dst);</span>
<span id="cb180-281"><a href="#cb180-281" aria-hidden="true" tabindex="-1"></a>  consteval bool is_layout_compatible_type(info type1, info type2);</span>
<span id="cb180-282"><a href="#cb180-282" aria-hidden="true" tabindex="-1"></a>  consteval bool is_pointer_interconvertible_base_of_type(info type_base, info type_derived);</span>
<span id="cb180-283"><a href="#cb180-283" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-284"><a href="#cb180-284" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-285"><a href="#cb180-285" aria-hidden="true" tabindex="-1"></a>    consteval bool is_invocable_type(info type, R&amp;&amp; type_args);</span>
<span id="cb180-286"><a href="#cb180-286" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-287"><a href="#cb180-287" aria-hidden="true" tabindex="-1"></a>    consteval bool is_invocable_r_type(info type_result, info type, R&amp;&amp; type_args);</span>
<span id="cb180-288"><a href="#cb180-288" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-289"><a href="#cb180-289" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-290"><a href="#cb180-290" aria-hidden="true" tabindex="-1"></a>    consteval bool is_nothrow_invocable_type(info type, R&amp;&amp; type_args);</span>
<span id="cb180-291"><a href="#cb180-291" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-292"><a href="#cb180-292" aria-hidden="true" tabindex="-1"></a>    consteval bool is_nothrow_invocable_r_type(info type_result, info type, R&amp;&amp; type_args);</span>
<span id="cb180-293"><a href="#cb180-293" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-294"><a href="#cb180-294" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.cv], const-volatile modifications</span>
<span id="cb180-295"><a href="#cb180-295" aria-hidden="true" tabindex="-1"></a>  consteval info remove_const(info type);</span>
<span id="cb180-296"><a href="#cb180-296" aria-hidden="true" tabindex="-1"></a>  consteval info remove_volatile(info type);</span>
<span id="cb180-297"><a href="#cb180-297" aria-hidden="true" tabindex="-1"></a>  consteval info remove_cv(info type);</span>
<span id="cb180-298"><a href="#cb180-298" aria-hidden="true" tabindex="-1"></a>  consteval info add_const(info type);</span>
<span id="cb180-299"><a href="#cb180-299" aria-hidden="true" tabindex="-1"></a>  consteval info add_volatile(info type);</span>
<span id="cb180-300"><a href="#cb180-300" aria-hidden="true" tabindex="-1"></a>  consteval info add_cv(info type);</span>
<span id="cb180-301"><a href="#cb180-301" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-302"><a href="#cb180-302" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.ref], reference modifications</span>
<span id="cb180-303"><a href="#cb180-303" aria-hidden="true" tabindex="-1"></a>  consteval info remove_reference(info type);</span>
<span id="cb180-304"><a href="#cb180-304" aria-hidden="true" tabindex="-1"></a>  consteval info add_lvalue_reference(info type);</span>
<span id="cb180-305"><a href="#cb180-305" aria-hidden="true" tabindex="-1"></a>  consteval info add_rvalue_reference(info type);</span>
<span id="cb180-306"><a href="#cb180-306" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-307"><a href="#cb180-307" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.sign], sign modifications</span>
<span id="cb180-308"><a href="#cb180-308" aria-hidden="true" tabindex="-1"></a>  consteval info make_signed(info type);</span>
<span id="cb180-309"><a href="#cb180-309" aria-hidden="true" tabindex="-1"></a>  consteval info make_unsigned(info type);</span>
<span id="cb180-310"><a href="#cb180-310" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-311"><a href="#cb180-311" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.arr], array modifications</span>
<span id="cb180-312"><a href="#cb180-312" aria-hidden="true" tabindex="-1"></a>  consteval info remove_extent(info type);</span>
<span id="cb180-313"><a href="#cb180-313" aria-hidden="true" tabindex="-1"></a>  consteval info remove_all_extents(info type);</span>
<span id="cb180-314"><a href="#cb180-314" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-315"><a href="#cb180-315" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.ptr], pointer modifications</span>
<span id="cb180-316"><a href="#cb180-316" aria-hidden="true" tabindex="-1"></a>  consteval info remove_pointer(info type);</span>
<span id="cb180-317"><a href="#cb180-317" aria-hidden="true" tabindex="-1"></a>  consteval info add_pointer(info type);</span>
<span id="cb180-318"><a href="#cb180-318" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-319"><a href="#cb180-319" aria-hidden="true" tabindex="-1"></a>  // associated with [meta.trans.other], other transformations</span>
<span id="cb180-320"><a href="#cb180-320" aria-hidden="true" tabindex="-1"></a>  consteval info remove_cvref(info type);</span>
<span id="cb180-321"><a href="#cb180-321" aria-hidden="true" tabindex="-1"></a>  consteval info decay(info type);</span>
<span id="cb180-322"><a href="#cb180-322" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-323"><a href="#cb180-323" aria-hidden="true" tabindex="-1"></a>    consteval info common_type(R&amp;&amp; type_args);</span>
<span id="cb180-324"><a href="#cb180-324" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-325"><a href="#cb180-325" aria-hidden="true" tabindex="-1"></a>    consteval info common_reference(R&amp;&amp; type_args);</span>
<span id="cb180-326"><a href="#cb180-326" aria-hidden="true" tabindex="-1"></a>  consteval info type_underlying_type(info type);</span>
<span id="cb180-327"><a href="#cb180-327" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = initializer_list&lt;info&gt;&gt;</span>
<span id="cb180-328"><a href="#cb180-328" aria-hidden="true" tabindex="-1"></a>    consteval info invoke_result(info type, R&amp;&amp; type_args);</span>
<span id="cb180-329"><a href="#cb180-329" aria-hidden="true" tabindex="-1"></a>  consteval info unwrap_reference(info type);</span>
<span id="cb180-330"><a href="#cb180-330" aria-hidden="true" tabindex="-1"></a>  consteval info unwrap_ref_decay(info type);</span>
<span id="cb180-331"><a href="#cb180-331" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-332"><a href="#cb180-332" aria-hidden="true" tabindex="-1"></a>  consteval size_t tuple_size(info type);</span>
<span id="cb180-333"><a href="#cb180-333" aria-hidden="true" tabindex="-1"></a>  consteval info tuple_element(size_t index, info type);</span>
<span id="cb180-334"><a href="#cb180-334" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-335"><a href="#cb180-335" aria-hidden="true" tabindex="-1"></a>  consteval size_t variant_size(info type);</span>
<span id="cb180-336"><a href="#cb180-336" aria-hidden="true" tabindex="-1"></a>  consteval info variant_alternative(size_t index, info type);</span>
<span id="cb180-337"><a href="#cb180-337" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb180-338"><a href="#cb180-338" aria-hidden="true" tabindex="-1"></a>  consteval strong_ordering type_order(info type_a, info type_b);</span>
<span id="cb180-339"><a href="#cb180-339" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_449" id="pnum_449">1</a></span>
Unless otherwise specified, each function, and each instantiation of any
function template, specified in this header is a designated addressable
function ([namespace.std]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_450" id="pnum_450">2</a></span>
The behavior of any function specified in namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code> is
implementation-defined when a reflection of a construct not otherwise
specified by this document is provided as an argument.</p>
<p><span class="note"><span>[ <em>Note 1:</em> </span>Values of type
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
can represent implementation-specific constructs (<span>6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a></span>).<span>
— <em>end note</em> ]</span></span></p>
<div class="note">
<p><span>[ <em>Note 2:</em> </span>The behavior of many of the functions
specified in namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
have semantics that can be affected by the completeness of class types
represented by reflection values. For such functions, for any reflection
<code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a specialization of a templated class with a reachable
definition, the specialization is implicitly instantiated
([temp.inst]).</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb181"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb181-1"><a href="#cb181-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb181-2"><a href="#cb181-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb181-3"><a href="#cb181-3" aria-hidden="true" tabindex="-1"></a>  T mem;</span>
<span id="cb181-4"><a href="#cb181-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb181-5"><a href="#cb181-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb181-6"><a href="#cb181-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>size_of<span class="op">(^^</span>X<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">))</span>; <span class="co">// instantiates X&lt;int&gt;</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<span> — <em>end note</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_451" id="pnum_451">3</a></span>
Any function in namespace
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
whose return type is <code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code> returns an object
<code class="sourceCode cpp"><em>V</em></code> such that <code class="sourceCode cpp"><em>V</em><span class="op">.</span>data<span class="op">()[</span><em>V</em><span class="op">.</span>size<span class="op">()]</span></code>
equals <code class="sourceCode cpp"><span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span></code>.</p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<div class="sourceCode" id="cb182"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb182-1"><a href="#cb182-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb182-2"><a href="#cb182-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb182-3"><a href="#cb182-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> string_view sv <span class="op">=</span> identifier_of<span class="op">(^^</span>C<span class="op">)</span>;</span>
<span id="cb182-4"><a href="#cb182-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>sv <span class="op">==</span> <span class="st">&quot;C&quot;</span><span class="op">)</span>;</span>
<span id="cb182-5"><a href="#cb182-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>sv<span class="op">.</span>data<span class="op">()[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;C&#39;</span><span class="op">)</span>;</span>
<span id="cb182-6"><a href="#cb182-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>sv<span class="op">.</span>data<span class="op">()[</span><span class="dv">1</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_452" id="pnum_452">4</a></span>
Throughout this clause, variables are introduced to designate various
source constructs. For the purpose of exposition,
<code class="sourceCode cpp"><span class="op">^^</span><em>E</em></code>
is used to a mean a reflection representing
<code class="sourceCode cpp"><em>E</em></code> when
<code class="sourceCode cpp"><em>E</em></code> is such an
exposition-only variable.<span> — <em>end example</em> ]</span></p>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.operators-operator-representations">[meta.reflection.operators]
Operator representations<a href="#meta.reflection.operators-operator-representations" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb183"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb183-1"><a href="#cb183-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> operators <span class="op">{</span></span>
<span id="cb183-2"><a href="#cb183-2" aria-hidden="true" tabindex="-1"></a>  <em>see below</em>;</span>
<span id="cb183-3"><a href="#cb183-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb183-4"><a href="#cb183-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">enum</span> operators;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_453" id="pnum_453">1</a></span>
This enum class specifies constants used to identify operators that can
be overloaded, with the meanings listed in Table 1. The values of the
constants are distinct.</p>
<p><span class="draftnote" style="color: #01796F">[ Drafting note: The
names here are chosen after the punctuation marks, not the semantic
operation, and we are sticking with the Unicode names — or resorting to
the secondary name when the primary name is not well known
(e.g. <code class="sourceCode cpp">solidus</code> -&gt;
<code class="sourceCode cpp">slash</code>) ]</span></p>
<center>
Table 1: Enum class <code class="sourceCode cpp">operators</code>
[meta.reflection.operators]
</center>
<table>
<thead>
<tr class="header">
<th style="text-align: left;"><div style="text-align:center">
<strong>Constant</strong>
</div></th>
<th style="text-align: left;"><div style="text-align:center">
<strong>Corresponding
<code class="sourceCode cpp"><em>operator-function-id</em></code></strong>
</div></th>
<th style="text-align: left;"><div style="text-align:center">
<strong>Operator symbol name</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_new</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">new</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_delete</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">delete</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_array_new</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span><span class="op">[]</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">new</span><span class="op">[]</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_array_delete</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[]</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">delete</span><span class="op">[]</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_co_await</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">co_await</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">co_await</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_parentheses</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">()</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_square_brackets</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">[]</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_arrow</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">-&gt;</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_arrow_star</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-&gt;*</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">-&gt;*</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_tilde</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">~</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">~</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_exclamation</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">!</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">!</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_plus</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">+</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">+</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_minus</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">-</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_star</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">*</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_slash</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">/</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">/</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_percent</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">%</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">%</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_caret</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">^</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">^</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_ampersand</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&amp;</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_pipe</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">|</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">|</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_plus_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">+=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">+=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_minus_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">-=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_star_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">*=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_slash_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">/=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">/=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_percent_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">%=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">%=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_caret_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">^=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">^=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_ampersand_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&amp;=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_pipe_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">|=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">|=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_equals_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">==</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">==</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_exclamation_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">!=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">!=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_less</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&lt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&lt;</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_greater</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&gt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&gt;</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_less_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&lt;=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&lt;=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_greater_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&gt;=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&gt;=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_spaceship</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&lt;=&gt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&lt;=&gt;</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_ampersand_ampersand</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&amp;&amp;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_pipe_pipe</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">||</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">||</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_less_less</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&lt;&lt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&lt;&lt;</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_greater_greater</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&gt;&gt;</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&gt;&gt;</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_less_less_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&lt;&lt;=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&lt;&lt;=</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_greater_greater_equals</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">&gt;&gt;=</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">&gt;&gt;=</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_plus_plus</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">++</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">++</span></code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code class="sourceCode cpp">op_minus_minus</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span><span class="op">--</span></code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="op">--</span></code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><code class="sourceCode cpp">op_comma</code></td>
<td style="text-align: left;"><code class="sourceCode cpp"><span class="kw">operator</span>,</code></td>
<td style="text-align: left;"><code><span class="op">,</span></code></td>
</tr>
</tbody>
</table>
<div class="sourceCode" id="cb184"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb184-1"><a href="#cb184-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> operators operator_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_454" id="pnum_454">2</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">r</code> represents
an operator function or operator function template.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_455" id="pnum_455">3</a></span>
<em>Returns</em>: The value of the enumerator from
<code class="sourceCode cpp">operators</code> whose corresponding
<code class="sourceCode cpp"><em>operator-function-id</em></code> is the
unqualified name of the entity represented by
<code class="sourceCode cpp">r</code>.</p>
<div class="sourceCode" id="cb185"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb185-1"><a href="#cb185-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view symbol_of<span class="op">(</span>operators op<span class="op">)</span>;</span>
<span id="cb185-2"><a href="#cb185-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8symbol_of<span class="op">(</span>operators op<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_456" id="pnum_456">4</a></span>
<em>Constant When</em>: The value of
<code class="sourceCode cpp">op</code> corresponds to one of the
enumerators in <code class="sourceCode cpp">operators</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_457" id="pnum_457">5</a></span>
<em>Returns</em>: <code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code> containing the
characters of the operator symbol name corresponding to
<code class="sourceCode cpp">op</code>, respectively encoded with the
ordinary literal encoding or with UTF-8.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.names-reflection-names-and-locations">[meta.reflection.names]
Reflection names and locations<a href="#meta.reflection.names-reflection-names-and-locations" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb186"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb186-1"><a href="#cb186-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_identifier<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_458" id="pnum_458">1</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_459" id="pnum_459">(1.1)</a></span>
If <code class="sourceCode cpp">r</code> represents an entity that has a
typedef name for linkage purposes ([dcl.typedef]), then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_460" id="pnum_460">(1.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an
unnamed entity, then
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_461" id="pnum_461">(1.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a class
type, then <code class="sourceCode cpp"><span class="op">!</span>has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_462" id="pnum_462">(1.4)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
function, then
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp"><span class="op">!</span>has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>
and the function is not a constructor, destructor, operator function, or
conversion function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_463" id="pnum_463">(1.5)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
template, then
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> does not represent a constructor
template, operator function template, or conversion function template.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_464" id="pnum_464">(1.6)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
variable, then
<code class="sourceCode cpp"><span class="kw">false</span></code> if the
declaration of that variable was instantiated from a function parameter
pack. Otherwise, <code class="sourceCode cpp"><span class="op">!</span>has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_465" id="pnum_465">(1.7)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
structured binding, then
<code class="sourceCode cpp"><span class="kw">false</span></code> if the
declaration of that structured binding was instantiated from a
structured binding pack. Otherwise,
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_466" id="pnum_466">(1.8)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a type
alias, then <code class="sourceCode cpp"><span class="op">!</span>has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_467" id="pnum_467">(1.9)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an
enumerator, non-static data member, namespace, or namespace alias, then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_468" id="pnum_468">(1.10)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship, then <code class="sourceCode cpp">has_identifier<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_469" id="pnum_469">(1.11)</a></span>
Otherwise, <code class="sourceCode cpp">r</code> represents a data
member description (<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) (<span>11.4.1 <a href="https://wg21.link/class.mem.general">[class.mem.general]</a></span>);
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp"><em>N</em></code> is not ⊥. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
</ul>
<div class="sourceCode" id="cb187"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb187-1"><a href="#cb187-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view identifier_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb187-2"><a href="#cb187-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8identifier_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_470" id="pnum_470">2</a></span>
Let <em>E</em> be UTF-8 if returning a
<code class="sourceCode cpp">u8string_view</code>, and otherwise the
ordinary literal encoding.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_471" id="pnum_471">3</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">has_identifier<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> and
the identifier that would be returned (see below) is representable by
<code class="sourceCode cpp"><em>E</em></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_472" id="pnum_472">4</a></span>
<em>Returns</em>: An NTMBS, encoded with
<code class="sourceCode cpp"><em>E</em></code>, determined as
follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_473" id="pnum_473">(4.1)</a></span>
If <code class="sourceCode cpp">r</code> represents an entity with a
typedef name for linkage purposes, then that name.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_474" id="pnum_474">(4.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a literal
operator or literal operator template, then the
<code class="sourceCode cpp"><em>ud-suffix</em></code> of the operator
or operator template.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_475" id="pnum_475">(4.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an
entity, then the identifier introduced by the declaration of that
entity.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_476" id="pnum_476">(4.4)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship, then <code class="sourceCode cpp">identifier_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>
or <code class="sourceCode cpp">u8identifier_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>,
respectively.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_477" id="pnum_477">(4.5)</a></span>
Otherwise, <code class="sourceCode cpp">r</code> represents a data
member description (<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) (<span>11.4.1 <a href="https://wg21.link/class.mem.general">[class.mem.general]</a></span>);
a <code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code>, respectively,
containing the identifier
<code class="sourceCode cpp"><em>N</em></code>.</li>
</ul>
<div class="sourceCode" id="cb188"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb188-1"><a href="#cb188-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view display_string_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb188-2"><a href="#cb188-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8display_string_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_478" id="pnum_478">5</a></span>
<em>Returns</em>: An implementation-defined
<code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code>, respectively.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_479" id="pnum_479">6</a></span>
<em>Recommended practice</em>: Where possible, implementations should
return a string suitable for identifying the represented construct.</p>
<div class="sourceCode" id="cb189"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb189-1"><a href="#cb189-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> source_location source_location_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_480" id="pnum_480">7</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> represents a
value, a type other than a class type or an enumeration type, the global
namespace, or a data member description, then <code class="sourceCode cpp">source_location<span class="op">{}</span></code>.
Otherwise, an implementation-defined
<code class="sourceCode cpp">source_location</code> value.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_481" id="pnum_481">8</a></span>
<em>Recommended practice</em>: If <code class="sourceCode cpp">r</code>
represents an entity with a definition that is reachable from the
evaluation context, a value corresponding to a definition should be
returned.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.queries-reflection-queries">[meta.reflection.queries]
Reflection queries<a href="#meta.reflection.queries-reflection-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb190"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb190-1"><a href="#cb190-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> <em>has-type</em><span class="op">(</span>info r<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_482" id="pnum_482">1</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a value, object,
variable, function that is not a constructor or destructor, enumerator,
non-static data member, unnamed bit-field, direct base class
relationship, or data member description. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb191"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb191-1"><a href="#cb191-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_483" id="pnum_483">2</a></span>
<em>Constant When</em>: <code class="sourceCode cpp"><em>has-type</em><span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_484" id="pnum_484">3</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_485" id="pnum_485">(3.1)</a></span>
If <code class="sourceCode cpp">r</code> represents a value, object,
variable, function, non-static data member, or unnamed bit-field, then
the type of what is represented by
<code class="sourceCode cpp">r</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_486" id="pnum_486">(3.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an
enumerator <code class="sourceCode cpp"><em>N</em></code> of an
enumeration <code class="sourceCode cpp"><em>E</em></code>, then:
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_487" id="pnum_487">(3.2.1)</a></span>
If <code class="sourceCode cpp"><em>E</em></code> is defined by a
declaration <code class="sourceCode cpp"><em>D</em></code> that is
reachable from a point <code class="sourceCode cpp"><em>P</em></code> in
the evaluation context and
<code class="sourceCode cpp"><em>P</em></code> does not occur within an
<code class="sourceCode cpp"><em>enum-specifier</em></code> of
<code class="sourceCode cpp"><em>D</em></code>, then a reflection of
<code class="sourceCode cpp"><em>E</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_488" id="pnum_488">(3.2.2)</a></span>
Otherwise, a reflection of the type of
<code class="sourceCode cpp"><em>N</em></code> prior to the closing
brace of the <code class="sourceCode cpp"><em>enum-specifier</em></code>
as specified in [dcl.enum].</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_489" id="pnum_489">(3.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship, then a reflection of the type of the direct
base class.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_490" id="pnum_490">(3.4)</a></span>
Otherwise, for a data member description
(<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) ([class.mem.general]),
a reflection of the type
<code class="sourceCode cpp"><em>T</em></code>.</li>
</ul>
<div class="sourceCode" id="cb192"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb192-1"><a href="#cb192-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info object_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_491" id="pnum_491">4</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">r</code> is a
reflection representing either</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_492" id="pnum_492">(4.1)</a></span>
an object with static storage duration ([basic.stc.general]), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_493" id="pnum_493">(4.2)</a></span>
a variable that either declares or refers to such an object, and if that
variable is a reference <code class="sourceCode cpp"><em>R</em></code>
then either
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_494" id="pnum_494">(4.2.1)</a></span>
<code class="sourceCode cpp"><em>R</em></code> is usable in constant
expressions ([expr.const]), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_495" id="pnum_495">(4.2.2)</a></span>
the lifetime of <code class="sourceCode cpp"><em>R</em></code> began
within the core constant expression currently under evaluation.</li>
</ul></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_496" id="pnum_496">5</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_497" id="pnum_497">(5.1)</a></span>
If <code class="sourceCode cpp">r</code> represents an object, then
<code class="sourceCode cpp">r</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_498" id="pnum_498">(5.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
reference, then a reflection of the object referred to by that
reference.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_499" id="pnum_499">(5.3)</a></span>
Otherwise (if <code class="sourceCode cpp">r</code> represents any other
variable), a reflection of the object declared by that variable.</li>
</ul>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb193"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb193-1"><a href="#cb193-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x;</span>
<span id="cb193-2"><a href="#cb193-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span><span class="op">&amp;</span> y <span class="op">=</span> x;</span>
<span id="cb193-3"><a href="#cb193-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb193-4"><a href="#cb193-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>x <span class="op">!=</span> <span class="op">^^</span>y<span class="op">)</span>;                       <span class="co">// OK, x and y are different variables so their</span></span>
<span id="cb193-5"><a href="#cb193-5" aria-hidden="true" tabindex="-1"></a>                                                 <span class="co">// reflections compare different</span></span>
<span id="cb193-6"><a href="#cb193-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>object_of<span class="op">(^^</span>x<span class="op">)</span> <span class="op">==</span> object_of<span class="op">(^^</span>y<span class="op">))</span>; <span class="co">// OK, because y is a reference</span></span>
<span id="cb193-7"><a href="#cb193-7" aria-hidden="true" tabindex="-1"></a>                                                 <span class="co">// to x, their underlying objects are the same</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb194"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb194-1"><a href="#cb194-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info constant_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_500" id="pnum_500">6</a></span>
Let <code class="sourceCode cpp"><em>R</em></code> be a constant
expression of type <code class="sourceCode cpp">info</code> such that
<code class="sourceCode cpp"><em>R</em> <span class="op">==</span> r</code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_501" id="pnum_501">7</a></span>
<em>Constant When</em>: <code class="sourceCode cpp"><span class="op">[:</span> <em>R</em> <span class="op">:]</span></code>
is a valid
<code class="sourceCode cpp"><em>splice-expression</em></code>
([expr.prim.splice]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_502" id="pnum_502">8</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb195"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb195-1"><a href="#cb195-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> reflect_constant<span class="op">([:</span> <em>R</em> <span class="op">:])</span>;</span></code></pre></div>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<div class="sourceCode" id="cb196"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb196-1"><a href="#cb196-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">0</span>;</span>
<span id="cb196-2"><a href="#cb196-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> y <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb196-3"><a href="#cb196-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb196-4"><a href="#cb196-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(^^</span>x <span class="op">!=</span> <span class="op">^^</span>y<span class="op">)</span>;                              <span class="co">// OK, x and y are different variables so their</span></span>
<span id="cb196-5"><a href="#cb196-5" aria-hidden="true" tabindex="-1"></a>                                                        <span class="co">// reflections compare different</span></span>
<span id="cb196-6"><a href="#cb196-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>constant_of<span class="op">(^^</span>x<span class="op">)</span> <span class="op">==</span> constant_of<span class="op">(^^</span>y<span class="op">))</span>;    <span class="co">// OK, both constant_of(^^x) and constant_of(^^y)</span></span>
<span id="cb196-7"><a href="#cb196-7" aria-hidden="true" tabindex="-1"></a>                                                        <span class="co">// represent the value 0</span></span>
<span id="cb196-8"><a href="#cb196-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>constant_of<span class="op">(^^</span>x<span class="op">)</span> <span class="op">==</span> reflect_constant<span class="op">(</span><span class="dv">0</span><span class="op">))</span>; <span class="co">// OK, likewise</span></span>
<span id="cb196-9"><a href="#cb196-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb196-10"><a href="#cb196-10" aria-hidden="true" tabindex="-1"></a>info fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb196-11"><a href="#cb196-11" 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="cb196-12"><a href="#cb196-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">^^</span>x;</span>
<span id="cb196-13"><a href="#cb196-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb196-14"><a href="#cb196-14" aria-hidden="true" tabindex="-1"></a>info r <span class="op">=</span> constant_of<span class="op">(</span>fn<span class="op">())</span>;  <span class="co">// error: x is outside its lifetime</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb197"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb197-1"><a href="#cb197-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_public<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb197-2"><a href="#cb197-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_protected<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb197-3"><a href="#cb197-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_private<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_503" id="pnum_503">9</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a class member or
direct base class relationship that is public, protected, or private,
respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb198"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb198-1"><a href="#cb198-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_virtual<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_504" id="pnum_504">10</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents either a virtual member
function or a direct base class relationship that is virtual. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb199"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb199-1"><a href="#cb199-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_pure_virtual<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb199-2"><a href="#cb199-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_override<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_505" id="pnum_505">11</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a member function that
is pure virtual or overrides another member function, respectively.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb200"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb200-1"><a href="#cb200-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_final<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_506" id="pnum_506">12</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a final class or a
final member function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb201"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb201-1"><a href="#cb201-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_deleted<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb201-2"><a href="#cb201-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_defaulted<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_507" id="pnum_507">13</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function that is a
deleted function ([dcl.fct.def.delete]) or defaulted function
([dcl.fct.def.default]), respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb202"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb202-1"><a href="#cb202-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_user_provided<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb202-2"><a href="#cb202-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_user_declared<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_508" id="pnum_508">14</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function that is
user-provided or user-declared ([dcl.fct.def.default]), respectively.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb203"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb203-1"><a href="#cb203-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_explicit<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_509" id="pnum_509">15</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a member function that
is declared explicit. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>. <span class="note"><span>[ <em>Note 1:</em> </span>If
<code class="sourceCode cpp">r</code> represents a member function
template that is declared
<code class="sourceCode cpp"><span class="kw">explicit</span></code>,
<code class="sourceCode cpp">is_explicit<span class="op">(</span>r<span class="op">)</span></code>
is still
<code class="sourceCode cpp"><span class="kw">false</span></code>
because in general such queries for templates cannot be answered.<span>
— <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb204"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb204-1"><a href="#cb204-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_noexcept<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_510" id="pnum_510">16</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
function type or a function with a non-throwing exception specification
([except.spec]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>. <span class="note"><span>[ <em>Note 2:</em> </span>If
<code class="sourceCode cpp">r</code> represents a function template
that is declared
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>,
<code class="sourceCode cpp">is_noexcept<span class="op">(</span>r<span class="op">)</span></code>
is still
<code class="sourceCode cpp"><span class="kw">false</span></code>
because in general such queries for templates cannot be answered.<span>
— <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb205"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb205-1"><a href="#cb205-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_bit_field<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_511" id="pnum_511">17</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a bit-field, or if
<code class="sourceCode cpp">r</code> represents a data member
description (<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) ([class.mem.general])
for which <code class="sourceCode cpp"><em>W</em></code> is not ⊥.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb206"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb206-1"><a href="#cb206-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_enumerator<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_512" id="pnum_512">18</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents an enumerator.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb207"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb207-1"><a href="#cb207-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_const<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb207-2"><a href="#cb207-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_volatile<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_513" id="pnum_513">19</a></span>
Let <code class="sourceCode cpp"><em>T</em></code> be <code class="sourceCode cpp">type_of<span class="op">(</span>r<span class="op">)</span></code>
if <code class="sourceCode cpp"><em>has-type</em><span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Otherwise, let <code class="sourceCode cpp"><em>T</em></code> be <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_514" id="pnum_514">20</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp"><em>T</em></code> represents a const or
volatile type, respectively, or a const- or volatile-qualified function
type, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb208"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb208-1"><a href="#cb208-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_mutable_member<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_515" id="pnum_515">21</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a
<code class="sourceCode cpp"><span class="kw">mutable</span></code>
non-static data member. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb209"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb209-1"><a href="#cb209-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_lvalue_reference_qualified<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb209-2"><a href="#cb209-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_rvalue_reference_qualified<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_516" id="pnum_516">22</a></span>
Let <code class="sourceCode cpp"><em>T</em></code> be <code class="sourceCode cpp">type_of<span class="op">(</span>r<span class="op">)</span></code>
if <code class="sourceCode cpp"><em>has-type</em><span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Otherwise, let <code class="sourceCode cpp"><em>T</em></code> be <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_517" id="pnum_517">23</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp"><em>T</em></code> represents a lvalue- or
rvalue-reference qualified function type, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb210"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb210-1"><a href="#cb210-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_static_storage_duration<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb210-2"><a href="#cb210-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_thread_storage_duration<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb210-3"><a href="#cb210-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_automatic_storage_duration<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_518" id="pnum_518">24</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents an object or variable
that has static, thread, or automatic storage duration, respectively
([basic.stc]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>. <span class="note"><span>[ <em>Note 3:</em> </span>It is not possible to have
a reflection representing an object or variable having dynamic storage
duration.<span> — <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb211"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb211-1"><a href="#cb211-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_internal_linkage<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb211-2"><a href="#cb211-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_module_linkage<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb211-3"><a href="#cb211-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_external_linkage<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb211-4"><a href="#cb211-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_c_language_linkage<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb211-5"><a href="#cb211-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_linkage<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_519" id="pnum_519">25</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a variable, function,
type, template, or namespace whose name has internal linkage, module
linkage, external linkage, C language linkage, or any linkage,
respectively ([basic.link]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb212"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb212-1"><a href="#cb212-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_complete_type<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_520" id="pnum_520">26</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">is_type<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> and
there is some point in the evaluation context from which the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is not an incomplete type ([basic.types]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb213"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb213-1"><a href="#cb213-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_enumerable_type<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_521" id="pnum_521">27</a></span>
A type <code class="sourceCode cpp"><em>T</em></code> is
<em>enumerable</em> from a point
<code class="sourceCode cpp"><em>P</em></code> if either</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_522" id="pnum_522">(27.1)</a></span>
<code class="sourceCode cpp"><em>T</em></code> is a class type complete
at <code class="sourceCode cpp"><em>P</em></code> or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_523" id="pnum_523">(27.2)</a></span>
<code class="sourceCode cpp"><em>T</em></code> is an enumeration type
defined by a declaration <code class="sourceCode cpp"><em>D</em></code>
such that <code class="sourceCode cpp"><em>D</em></code> is reachable
from <code class="sourceCode cpp"><em>P</em></code> but
<code class="sourceCode cpp"><em>P</em></code> does not occur within an
<code class="sourceCode cpp"><em>enum-specifier</em></code> of
<code class="sourceCode cpp"><em>D</em></code> ([dcl.enum]).</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_524" id="pnum_524">28</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type that is enumerable from some point in the evaluation
context. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="example">
<span>[ <em>Example 3:</em> </span>
<div class="sourceCode" id="cb214"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb214-1"><a href="#cb214-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> S;</span>
<span id="cb214-2"><a href="#cb214-2" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> E;</span>
<span id="cb214-3"><a href="#cb214-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_enumerable_type<span class="op">(^^</span>S<span class="op">))</span>;</span>
<span id="cb214-4"><a href="#cb214-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_enumerable_type<span class="op">(^^</span>E<span class="op">))</span>;</span>
<span id="cb214-5"><a href="#cb214-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb214-6"><a href="#cb214-6" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> S <span class="op">{</span></span>
<span id="cb214-7"><a href="#cb214-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> mfn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb214-8"><a href="#cb214-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span>is_enumerable_type<span class="op">(^^</span>S<span class="op">))</span>;</span>
<span id="cb214-9"><a href="#cb214-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb214-10"><a href="#cb214-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(!</span>is_enumerable_type<span class="op">(^^</span>S<span class="op">))</span>;</span>
<span id="cb214-11"><a href="#cb214-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb214-12"><a href="#cb214-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_enumerable_type<span class="op">(^^</span>S<span class="op">))</span>;</span>
<span id="cb214-13"><a href="#cb214-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb214-14"><a href="#cb214-14" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> E <span class="op">{</span></span>
<span id="cb214-15"><a href="#cb214-15" aria-hidden="true" tabindex="-1"></a>  A <span class="op">=</span> is_enumerable_type<span class="op">(^^</span>E<span class="op">)</span> <span class="op">?</span> <span class="dv">1</span> <span class="op">:</span> <span class="dv">2</span></span>
<span id="cb214-16"><a href="#cb214-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb214-17"><a href="#cb214-17" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_enumerable_type<span class="op">(^^</span>E<span class="op">))</span>;</span>
<span id="cb214-18"><a href="#cb214-18" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>E<span class="op">::</span>A<span class="op">)</span> <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb215"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb215-1"><a href="#cb215-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_variable<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_525" id="pnum_525">29</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a variable. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb216"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb216-1"><a href="#cb216-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_type<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb216-2"><a href="#cb216-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_namespace<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_526" id="pnum_526">30</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents an entity whose
underlying entity is a type or namespace, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb217"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb217-1"><a href="#cb217-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_type_alias<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb217-2"><a href="#cb217-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_namespace_alias<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_527" id="pnum_527">31</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a type alias or
namespace alias, respectively <span class="note"><span>[ <em>Note
4:</em> </span>A specialization of an alias template is a type
alias<span> — <em>end note</em> ]</span></span>. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb218"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb218-1"><a href="#cb218-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_function<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_528" id="pnum_528">32</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb219"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb219-1"><a href="#cb219-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_conversion_function<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb219-2"><a href="#cb219-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_operator_function<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb219-3"><a href="#cb219-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_literal_operator<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_529" id="pnum_529">33</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function that is a
conversion function ([class.conv.fct]), operator function ([over.oper]),
or literal operator ([over.literal]), respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb220"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb220-1"><a href="#cb220-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_special_member_function<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-2"><a href="#cb220-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_constructor<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-3"><a href="#cb220-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_default_constructor<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-4"><a href="#cb220-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_copy_constructor<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-5"><a href="#cb220-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_move_constructor<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-6"><a href="#cb220-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_assignment<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-7"><a href="#cb220-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_copy_assignment<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-8"><a href="#cb220-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_move_assignment<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb220-9"><a href="#cb220-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_destructor<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_530" id="pnum_530">34</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function that is a
special member function ([special]), a constructor, a default
constructor, a copy constructor, a move constructor, an assignment
operator, a copy assignment operator, a move assignment operator, or a
destructor, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb221"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb221-1"><a href="#cb221-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_template<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_531" id="pnum_531">35</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function template,
class template, variable template, alias template, or concept.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_532" id="pnum_532">36</a></span>
<span class="note"><span>[ <em>Note 5:</em> </span>A template
specialization is not a template. <code class="sourceCode cpp">is_template<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> but
<code class="sourceCode cpp">is_template<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;)</span></code>
is
<code class="sourceCode cpp"><span class="kw">false</span></code>.<span>
— <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb222"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb222-1"><a href="#cb222-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_function_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-2"><a href="#cb222-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_variable_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-3"><a href="#cb222-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_class_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-4"><a href="#cb222-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_alias_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-5"><a href="#cb222-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_conversion_function_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-6"><a href="#cb222-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_operator_function_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-7"><a href="#cb222-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_literal_operator_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-8"><a href="#cb222-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_constructor_template<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb222-9"><a href="#cb222-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_concept<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_533" id="pnum_533">37</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a function template,
variable template, class template, alias template, conversion function
template, operator function template, literal operator template,
constructor template, or concept respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb223"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb223-1"><a href="#cb223-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_value<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb223-2"><a href="#cb223-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_object<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_534" id="pnum_534">38</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a value or object,
respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb224"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb224-1"><a href="#cb224-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_structured_binding<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_535" id="pnum_535">39</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a structured binding.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb225"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb225-1"><a href="#cb225-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_class_member<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb225-2"><a href="#cb225-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_namespace_member<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb225-3"><a href="#cb225-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nonstatic_data_member<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb225-4"><a href="#cb225-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_static_member<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb225-5"><a href="#cb225-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_base<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_536" id="pnum_536">40</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a class member,
namespace member, non-static data member, static member, or direct base
class relationship, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb226"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb226-1"><a href="#cb226-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_default_member_initializer<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_537" id="pnum_537">41</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a non-static data
member that has a default member initializer. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb227"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb227-1"><a href="#cb227-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_parent<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_538" id="pnum_538">42</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_539" id="pnum_539">(42.1)</a></span>
If <code class="sourceCode cpp">r</code> represents the global
namespace, then
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_540" id="pnum_540">(42.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an entity
that has C language linkage ([dcl.link]), then
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_541" id="pnum_541">(42.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an entity
that has a language linkage other than C++ language linkage, then an
implementation-defined value.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_542" id="pnum_542">(42.4)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a type
that is neither a class nor enumeration type, then
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_543" id="pnum_543">(42.5)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an entity
or direct base class relationship, then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_544" id="pnum_544">(42.6)</a></span>
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
</ul>
<div class="sourceCode" id="cb228"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb228-1"><a href="#cb228-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info parent_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_545" id="pnum_545">43</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">has_parent<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_546" id="pnum_546">44</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_547" id="pnum_547">(44.1)</a></span>
If <code class="sourceCode cpp">r</code> represents a non-static data
member that is a direct member of an anonymous union, or an unnamed
bit-field declared within the
<code class="sourceCode cpp"><em>member-specification</em></code> of
such a union, then a reflection representing the innermost enclosing
anonymous union.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_548" id="pnum_548">(44.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents an
enumerator, then a reflection representing the corresponding enumeration
type.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_549" id="pnum_549">(44.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship between a class
<code class="sourceCode cpp"><em>D</em></code> and a direct base class
<code class="sourceCode cpp"><em>B</em></code>, then a reflection
representing <code class="sourceCode cpp"><em>D</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_550" id="pnum_550">(44.4)</a></span>
Otherwise, let <code class="sourceCode cpp"><em>E</em></code> be the
class, function, or namespace whose class scope, function parameter
scope, or namespace scope is, respectively, the innermost such scope
that either is, or encloses, the target scope of a declaration of what
is represented by <code class="sourceCode cpp">r</code>.
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_551" id="pnum_551">(44.5)</a></span>
If <code class="sourceCode cpp"><em>E</em></code> is the function call
operator of a closure type for a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
([dcl.pre]), then <code class="sourceCode cpp">parent_of<span class="op">(</span>parent_of<span class="op">(^^</span><em>E</em><span class="op">))</span></code>.
<span class="note"><span>[ <em>Note 6:</em> </span>In this case, the
first <code class="sourceCode cpp">parent_of</code> will be the closure
type, so the second <code class="sourceCode cpp">parent_of</code> is
necessary to give the parent of that closure type.<span> — <em>end
note</em> ]</span></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_552" id="pnum_552">(44.6)</a></span>
Otherwise,
<code class="sourceCode cpp"><span class="op">^^</span><em>E</em></code>.</li>
</ul></li>
</ul>
<div class="example">
<span>[ <em>Example 4:</em> </span>
<div class="sourceCode" id="cb229"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb229-1"><a href="#cb229-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> I <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb229-2"><a href="#cb229-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb229-3"><a href="#cb229-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> F <span class="op">:</span> I <span class="op">{</span></span>
<span id="cb229-4"><a href="#cb229-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb229-5"><a href="#cb229-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> o;</span>
<span id="cb229-6"><a href="#cb229-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb229-7"><a href="#cb229-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb229-8"><a href="#cb229-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">enum</span> N <span class="op">{</span></span>
<span id="cb229-9"><a href="#cb229-9" aria-hidden="true" tabindex="-1"></a>    A</span>
<span id="cb229-10"><a href="#cb229-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb229-11"><a href="#cb229-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb229-12"><a href="#cb229-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb229-13"><a href="#cb229-13" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ctx <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb229-14"><a href="#cb229-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb229-15"><a href="#cb229-15" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>parent_of<span class="op">(^^</span>F<span class="op">)</span> <span class="op">==</span> <span class="op">^^::)</span>;</span>
<span id="cb229-16"><a href="#cb229-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>parent_of<span class="op">(</span>bases_of<span class="op">(^^</span>F, ctx<span class="op">)[</span><span class="dv">0</span><span class="op">])</span> <span class="op">==</span> <span class="op">^^</span>F<span class="op">)</span>;</span>
<span id="cb229-17"><a href="#cb229-17" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_union_type<span class="op">(</span>parent_of<span class="op">(^^</span>F<span class="op">::</span>o<span class="op">)))</span>;</span>
<span id="cb229-18"><a href="#cb229-18" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>parent_of<span class="op">(^^</span>F<span class="op">::</span>N<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span>F<span class="op">)</span>;</span>
<span id="cb229-19"><a href="#cb229-19" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>parent_of<span class="op">(^^</span>F<span class="op">::</span>A<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span>F<span class="op">::</span>N<span class="op">)</span>;</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb230"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb230-1"><a href="#cb230-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info dealias<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_553" id="pnum_553">45</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">r</code> represents
an entity.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_554" id="pnum_554">46</a></span>
<em>Returns</em>: A reflection representing the underlying entity of
what <code class="sourceCode cpp">r</code> represents.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_555" id="pnum_555">47</a></span></p>
<div class="example">
<span>[ <em>Example 5:</em> </span>
<div class="sourceCode" id="cb231"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb231-1"><a href="#cb231-1" aria-hidden="true" tabindex="-1"></a>using X = int;</span>
<span id="cb231-2"><a href="#cb231-2" aria-hidden="true" tabindex="-1"></a>using Y = X;</span>
<span id="cb231-3"><a href="#cb231-3" aria-hidden="true" tabindex="-1"></a>static_assert(dealias(^^int) == ^^int);</span>
<span id="cb231-4"><a href="#cb231-4" aria-hidden="true" tabindex="-1"></a>static_assert(dealias(^^X) == ^^int);</span>
<span id="cb231-5"><a href="#cb231-5" aria-hidden="true" tabindex="-1"></a>static_assert(dealias(^^Y) == ^^int);</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb232"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb232-1"><a href="#cb232-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_template_arguments<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_556" id="pnum_556">48</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a specialization of a
function template, variable template, class template, or an alias
template. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb233"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb233-1"><a href="#cb233-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info template_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_557" id="pnum_557">49</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_558" id="pnum_558">50</a></span>
<em>Returns</em>: A reflection of the primary template of the
specialization represented by <code class="sourceCode cpp">r</code>.</p>
<div class="sourceCode" id="cb234"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb234-1"><a href="#cb234-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_arguments_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_559" id="pnum_559">51</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">has_template_arguments<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_560" id="pnum_560">52</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing reflections of the template arguments of the template
specialization represented by <code class="sourceCode cpp">r</code>, in
the order they appear in the corresponding template argument list. For a
given template argument <code class="sourceCode cpp"><em>A</em></code>,
its corresponding reflection
<code class="sourceCode cpp"><em>R</em></code> is determined as
follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_561" id="pnum_561">(52.1)</a></span>
If <code class="sourceCode cpp"><em>A</em></code> denotes a type or a
type alias, then <code class="sourceCode cpp"><em>R</em></code> is a
reflection representing the underlying entity of
<code class="sourceCode cpp"><em>A</em></code>. <span class="note"><span>[ <em>Note 7:</em>
</span><code class="sourceCode cpp"><em>R</em></code> always represents
a type, never a type alias.<span> — <em>end
note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_562" id="pnum_562">(52.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>A</em></code> denotes a
class template, variable template, concept, or alias template, then
<code class="sourceCode cpp"><em>R</em></code> is a reflection
representing <code class="sourceCode cpp"><em>A</em></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_563" id="pnum_563">(52.3)</a></span>
Otherwise, <code class="sourceCode cpp"><em>A</em></code> is a constant
template argument ([temp.arg.nontype]). Let
<code class="sourceCode cpp"><em>P</em></code> be the corresponding
template parameter.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_564" id="pnum_564">(52.3.1)</a></span>
If <code class="sourceCode cpp"><em>P</em></code> has reference type,
then <code class="sourceCode cpp"><em>R</em></code> is a reflection
representing the object referred to by
<code class="sourceCode cpp"><em>A</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_565" id="pnum_565">(52.3.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>P</em></code> has class
type, then <code class="sourceCode cpp"><em>R</em></code> represents the
corresponding template parameter object.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_566" id="pnum_566">(52.3.3)</a></span>
Otherwise, <code class="sourceCode cpp"><em>R</em></code> is a
reflection representing the value computed by
<code class="sourceCode cpp"><em>A</em></code>.</li>
</ul></li>
</ul>
<div class="example">
<span>[ <em>Example 6:</em> </span>
<div class="sourceCode" id="cb235"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb235-1"><a href="#cb235-1" aria-hidden="true" tabindex="-1"></a>template &lt;class T, class U=T&gt; struct Pair { };</span>
<span id="cb235-2"><a href="#cb235-2" aria-hidden="true" tabindex="-1"></a>template &lt;class T&gt; struct Pair&lt;char, T&gt; { };</span>
<span id="cb235-3"><a href="#cb235-3" aria-hidden="true" tabindex="-1"></a>template &lt;class T&gt; using PairPtr = Pair&lt;T*&gt;;</span>
<span id="cb235-4"><a href="#cb235-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb235-5"><a href="#cb235-5" aria-hidden="true" tabindex="-1"></a>static_assert(template_of(^^Pair&lt;int&gt;) == ^^Pair);</span>
<span id="cb235-6"><a href="#cb235-6" aria-hidden="true" tabindex="-1"></a>static_assert(template_of(^^Pair&lt;char, char&gt;) == ^^Pair);</span>
<span id="cb235-7"><a href="#cb235-7" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(^^Pair&lt;int&gt;).size() == 2);</span>
<span id="cb235-8"><a href="#cb235-8" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(^^Pair&lt;int&gt;)[0] == ^^int);</span>
<span id="cb235-9"><a href="#cb235-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb235-10"><a href="#cb235-10" aria-hidden="true" tabindex="-1"></a>static_assert(template_of(^^PairPtr&lt;int&gt;) == ^^PairPtr);</span>
<span id="cb235-11"><a href="#cb235-11" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(^^PairPtr&lt;int&gt;).size() == 1);</span>
<span id="cb235-12"><a href="#cb235-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb235-13"><a href="#cb235-13" aria-hidden="true" tabindex="-1"></a>struct S { };</span>
<span id="cb235-14"><a href="#cb235-14" aria-hidden="true" tabindex="-1"></a>int i;</span>
<span id="cb235-15"><a href="#cb235-15" aria-hidden="true" tabindex="-1"></a>template &lt;int, int&amp;, S, template &lt;class&gt; class&gt;</span>
<span id="cb235-16"><a href="#cb235-16" aria-hidden="true" tabindex="-1"></a>struct X { };</span>
<span id="cb235-17"><a href="#cb235-17" aria-hidden="true" tabindex="-1"></a>constexpr auto T = ^^X&lt;1, i, S{}, PairPtr&gt;;</span>
<span id="cb235-18"><a href="#cb235-18" aria-hidden="true" tabindex="-1"></a>static_assert(is_value(template_arguments_of(T)[0]));</span>
<span id="cb235-19"><a href="#cb235-19" aria-hidden="true" tabindex="-1"></a>static_assert(is_object(template_arguments_of(T)[1]));</span>
<span id="cb235-20"><a href="#cb235-20" aria-hidden="true" tabindex="-1"></a>static_assert(is_object(template_arguments_of(T)[2]));</span>
<span id="cb235-21"><a href="#cb235-21" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(T)[3] == ^^PairPtr);</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.access.context-access-control-context">[meta.reflection.access.context]
Access control context<a href="#meta.reflection.access.context-access-control-context" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_567" id="pnum_567">1</a></span>
The <code class="sourceCode cpp">access_context</code> class is a
non-aggregate type that represents a namespace, class, or function from
which queries pertaining to access rules may be performed, as well as
the naming class ([class.access.base]), if any.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_568" id="pnum_568">2</a></span>
An <code class="sourceCode cpp">access_context</code> has an associated
scope and naming class.</p>
<div class="sourceCode" id="cb236"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb236-1"><a href="#cb236-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> access_context <span class="op">{</span></span>
<span id="cb236-2"><a href="#cb236-2" aria-hidden="true" tabindex="-1"></a>   access_context<span class="op">()</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb236-3"><a href="#cb236-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb236-4"><a href="#cb236-4" aria-hidden="true" tabindex="-1"></a>   <span class="kw">consteval</span> info scope<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb236-5"><a href="#cb236-5" aria-hidden="true" tabindex="-1"></a>   <span class="kw">consteval</span> info naming_class<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb236-6"><a href="#cb236-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb236-7"><a href="#cb236-7" aria-hidden="true" tabindex="-1"></a>   <span class="kw">static</span> <span class="kw">consteval</span> access_context current<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb236-8"><a href="#cb236-8" aria-hidden="true" tabindex="-1"></a>   <span class="kw">static</span> <span class="kw">consteval</span> access_context unprivileged<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb236-9"><a href="#cb236-9" aria-hidden="true" tabindex="-1"></a>   <span class="kw">static</span> <span class="kw">consteval</span> access_context unchecked<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb236-10"><a href="#cb236-10" aria-hidden="true" tabindex="-1"></a>   <span class="kw">consteval</span> access_context via<span class="op">(</span>info cls<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb236-11"><a href="#cb236-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_569" id="pnum_569">3</a></span>
<code class="sourceCode cpp">access_context</code> is a structural type.
Two values <code class="sourceCode cpp">ac1</code> and
<code class="sourceCode cpp">ac2</code> of type
<code class="sourceCode cpp">access_context</code> are
template-argument-equivalent ([temp.type]) if <code class="sourceCode cpp">ac1<span class="op">.</span>scope<span class="op">()</span></code>
and <code class="sourceCode cpp">ac2<span class="op">.</span>scope<span class="op">()</span></code>
are template-argument-equivalent and <code class="sourceCode cpp">ac1<span class="op">.</span>naming_class<span class="op">()</span></code>
and <code class="sourceCode cpp">ac2<span class="op">.</span>naming_class<span class="op">()</span></code>
are template-argument-equivalent.</p>
<div class="sourceCode" id="cb237"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb237-1"><a href="#cb237-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info scope<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb237-2"><a href="#cb237-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info naming_class<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_570" id="pnum_570">4</a></span>
<em>Returns</em>: The
<code class="sourceCode cpp">access_context</code>’s associated scope
and naming class, respectively.</p>
<div class="sourceCode" id="cb238"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb238-1"><a href="#cb238-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> access_context current<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_571" id="pnum_571">5</a></span>
<code class="sourceCode cpp">current</code> is not an addressable
function ([namespace.std]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_572" id="pnum_572">6</a></span>
Given a program point <code class="sourceCode cpp"><em>P</em></code>,
let <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>P</em><span class="op">)</span></code>
be the following program point:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_573" id="pnum_573">(6.1)</a></span>
If a potentially-evaluated subexpression ([intro.execution]) of a
default member initializer
<code class="sourceCode cpp"><em>I</em></code> for a member of a class
<code class="sourceCode cpp"><em>C</em></code> ([class.mem.general])
appears at <code class="sourceCode cpp"><em>P</em></code>, then a point
determined as follows:
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_574" id="pnum_574">(6.1.1)</a></span>
If an aggregate initialization is using
<code class="sourceCode cpp"><em>I</em></code>, <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>Q</em><span class="op">)</span></code>,
where <code class="sourceCode cpp"><em>Q</em></code> is the point at
which that aggregate initialization appears.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_575" id="pnum_575">(6.1.2)</a></span>
Otherwise, if an initialization by an inherited constructor
([class.inhctor.init]) is using
<code class="sourceCode cpp"><em>I</em></code>, a point whose immediate
scope is the class scope corresponding to
<code class="sourceCode cpp"><em>C</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_576" id="pnum_576">(6.1.3)</a></span>
Otherwise, a point whose immediate scope is the function parameter scope
corresponding to the constructor definition that is using
<code class="sourceCode cpp"><em>I</em></code>.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_577" id="pnum_577">(6.2)</a></span>
Otherwise, if a potentially-evaluated subexpression of a default
argument ([dcl.fct.default]) appears at
<code class="sourceCode cpp"><em>P</em></code>, <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>Q</em><span class="op">)</span></code>,
where <code class="sourceCode cpp"><em>Q</em></code> is the point at
which the invocation of the function ([expr.call]) using that default
argument appears.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_578" id="pnum_578">(6.3)</a></span>
Otherwise, if the immediate scope of
<code class="sourceCode cpp"><em>P</em></code> is a function parameter
scope introduced by a declaration
<code class="sourceCode cpp"><em>D</em></code>, and
<code class="sourceCode cpp"><em>P</em></code> appears either before the
locus of <code class="sourceCode cpp"><em>D</em></code> or within the
trailing <code class="sourceCode cpp"><em>requires-clause</em></code> of
<code class="sourceCode cpp"><em>D</em></code>, a point whose immediate
scope is the innermost scope enclosing the locus of
<code class="sourceCode cpp"><em>D</em></code> that is not a template
parameter scope.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_579" id="pnum_579">(6.4)</a></span>
Otherwise, if the immediate scope of
<code class="sourceCode cpp"><em>P</em></code> is a function parameter
scope introduced by a
<code class="sourceCode cpp"><em>lambda-expression</em></code>
<code class="sourceCode cpp"><em>L</em></code> whose
<code class="sourceCode cpp"><em>lambda-introducer</em></code> appears
at point <code class="sourceCode cpp"><em>Q</em></code>, and
<code class="sourceCode cpp"><em>P</em></code> appears either within the
<code class="sourceCode cpp"><em>trailing-return-type</em></code> or the
trailing <code class="sourceCode cpp"><em>requires-clause</em></code> of
<code class="sourceCode cpp"><em>L</em></code>, <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>Q</em><span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_580" id="pnum_580">(6.5)</a></span>
Otherwise, if the immediate scope of
<code class="sourceCode cpp"><em>P</em></code> is a block scope and the
innermost function parameter scope enclosing
<code class="sourceCode cpp"><em>P</em></code> is introduced by a
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
([dcl.pre]), a point whose immediate scope is the scope inhabited by the
outermost
<code class="sourceCode cpp"><em>consteval-block-declaration</em></code>
that contains <code class="sourceCode cpp"><em>P</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_581" id="pnum_581">(6.6)</a></span>
Otherwise, <code class="sourceCode cpp"><em>P</em></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_582" id="pnum_582">7</a></span>
Given a scope <code class="sourceCode cpp"><em>S</em></code>, let <code class="sourceCode cpp"><em>ctx-scope</em><span class="op">(</span><em>S</em><span class="op">)</span></code>
be the following scope:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_583" id="pnum_583">(7.1)</a></span>
If <code class="sourceCode cpp"><em>S</em></code> is a class scope or a
namespace scope, <code class="sourceCode cpp"><em>S</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_584" id="pnum_584">(7.2)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is a
function parameter scope introduced by the declaration of a function,
<code class="sourceCode cpp"><em>S</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_585" id="pnum_585">(7.3)</a></span>
Otherwise, if <code class="sourceCode cpp"><em>S</em></code> is a lambda
scope introduced by a
<code class="sourceCode cpp"><em>lambda-expression</em></code>
<code class="sourceCode cpp"><em>L</em></code>, the function parameter
scope corresponding to the call operator of the closure type for
<code class="sourceCode cpp"><em>L</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_586" id="pnum_586">(7.4)</a></span>
Otherwise, <code class="sourceCode cpp"><em>ctx-scope</em><span class="op">(</span><em>S</em><span class="ch">&#39;)</span></code>
where
<code class="sourceCode cpp"><em>S</em><span class="ch">&#39;</span></code>
is the parent scope of
<code class="sourceCode cpp"><em>S</em></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_587" id="pnum_587">8</a></span>
An invocation of <code class="sourceCode cpp">current</code> that
appears at a program point
<code class="sourceCode cpp"><em>P</em></code> is value-dependent
([temp.dep.contexpr]) if <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>P</em><span class="op">)</span></code>
is enclosed by a scope corresponding to a templated entity.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_588" id="pnum_588">9</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose naming class is the null reflection and whose scope represents the
function, class, or namespace whose corresponding function parameter
scope, class scope, or namespace scope is <code class="sourceCode cpp"><em>eval-ctx</em><span class="op">(</span><em>S</em><span class="op">)</span></code>,
where <code class="sourceCode cpp"><em>S</em></code> is the immediate
scope of <code class="sourceCode cpp"><em>eval-point</em><span class="op">(</span><em>P</em><span class="op">)</span></code>
and <code class="sourceCode cpp"><em>P</em></code> is the point at which
the invocation of <code class="sourceCode cpp">current</code> lexically
appears.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb239"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb239-1"><a href="#cb239-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span></span>
<span id="cb239-2"><a href="#cb239-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> a <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb239-3"><a href="#cb239-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> A<span class="op">(</span><span class="dt">int</span> p<span class="op">)</span> <span class="op">:</span> a<span class="op">(</span>p<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb239-4"><a href="#cb239-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb239-5"><a href="#cb239-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span></span>
<span id="cb239-6"><a href="#cb239-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> A<span class="op">::</span>A;</span>
<span id="cb239-7"><a href="#cb239-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> B<span class="op">(</span><span class="dt">int</span> p, <span class="dt">int</span> q<span class="op">)</span> <span class="op">:</span> A<span class="op">(</span>p <span class="op">*</span> q<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb239-8"><a href="#cb239-8" aria-hidden="true" tabindex="-1"></a>  info s <span class="op">=</span> access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">()</span>;</span>
<span id="cb239-9"><a href="#cb239-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb239-10"><a href="#cb239-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb239-11"><a href="#cb239-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Agg <span class="op">{</span></span>
<span id="cb239-12"><a href="#cb239-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="dt">bool</span> eq<span class="op">(</span>info rhs <span class="op">=</span> access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">())</span> <span class="op">{</span></span>
<span id="cb239-13"><a href="#cb239-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> s <span class="op">==</span> rhs;</span>
<span id="cb239-14"><a href="#cb239-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb239-15"><a href="#cb239-15" aria-hidden="true" tabindex="-1"></a>  info s <span class="op">=</span> access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">()</span>;</span>
<span id="cb239-16"><a href="#cb239-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb239-17"><a href="#cb239-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb239-18"><a href="#cb239-18" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> NS <span class="op">{</span></span>
<span id="cb239-19"><a href="#cb239-19" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>Agg<span class="op">{}.</span>s <span class="op">==</span> access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">())</span>;  <span class="co">// OK</span></span>
<span id="cb239-20"><a href="#cb239-20" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>Agg<span class="op">{}.</span>eq<span class="op">())</span>;  <span class="co">// OK</span></span>
<span id="cb239-21"><a href="#cb239-21" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>B<span class="op">(</span><span class="dv">1</span><span class="op">).</span>s <span class="op">==</span> <span class="op">^^</span>B<span class="op">)</span>;  <span class="co">// OK</span></span>
<span id="cb239-22"><a href="#cb239-22" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_constructor<span class="op">(</span>B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}.</span>s<span class="op">)</span> <span class="op">&amp;&amp;</span> parent_of<span class="op">(</span>B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}.</span>s<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span>B<span class="op">)</span>;  <span class="co">// OK</span></span>
<span id="cb239-23"><a href="#cb239-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb239-24"><a href="#cb239-24" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> fn<span class="op">()</span> <span class="op">-&gt;</span> <span class="op">[:</span>is_namespace<span class="op">(</span>access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">())</span> <span class="op">?</span> <span class="op">^^</span><span class="dt">int</span> <span class="op">:</span> <span class="op">^^</span><span class="dt">bool</span><span class="op">:]</span>;</span>
<span id="cb239-25"><a href="#cb239-25" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>type_of<span class="op">(^^</span>fn<span class="op">)</span> <span class="op">==</span> <span class="op">^^</span><span class="kw">auto</span><span class="op">()-&gt;</span><span class="dt">int</span><span class="op">)</span>;  <span class="co">// OK</span></span>
<span id="cb239-26"><a href="#cb239-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb239-27"><a href="#cb239-27" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> R<span class="op">&gt;</span></span>
<span id="cb239-28"><a href="#cb239-28" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> TCls <span class="op">{</span></span>
<span id="cb239-29"><a href="#cb239-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="dt">bool</span> fn<span class="op">()</span></span>
<span id="cb239-30"><a href="#cb239-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>is_type<span class="op">(</span>access_context<span class="op">::</span>current<span class="op">().</span>scope<span class="op">()))</span> <span class="op">{</span></span>
<span id="cb239-31"><a href="#cb239-31" aria-hidden="true" tabindex="-1"></a>      <span class="co">// OK, scope is &#39;TCls&lt;R&gt;&#39;.</span></span>
<span id="cb239-32"><a href="#cb239-32" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb239-33"><a href="#cb239-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb239-34"><a href="#cb239-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb239-35"><a href="#cb239-35" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>TCls<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;{}.</span>fn<span class="op">())</span>;  <span class="co">// OK</span></span>
<span id="cb239-36"><a href="#cb239-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb240"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb240-1"><a href="#cb240-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> access_context unprivileged<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_589" id="pnum_589">10</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose naming class is the null reflection and whose scope is the global
namespace.</p>
<div class="sourceCode" id="cb241"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb241-1"><a href="#cb241-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> access_context unchecked<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_590" id="pnum_590">11</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose naming class and scope are both the null reflection.</p>
<div class="sourceCode" id="cb242"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb242-1"><a href="#cb242-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context via<span class="op">(</span>info cls<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_591" id="pnum_591">12</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">cls</code> is
either the null reflection or a reflection of a complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_592" id="pnum_592">13</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose scope is <code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;</span>scope<span class="op">()</span></code>
and whose naming class is <code class="sourceCode cpp">cls</code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.access.queries-member-accessibility-queries">[meta.reflection.access.queries]
Member accessibility queries<a href="#meta.reflection.access.queries-member-accessibility-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb243"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb243-1"><a href="#cb243-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_accessible<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_593" id="pnum_593">1</a></span>
Let <code class="sourceCode cpp"><em>PARENT-CLS</em><span class="op">(</span>r<span class="op">)</span></code>
be:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_594" id="pnum_594">(1.1)</a></span>
If <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>
represents a class <code class="sourceCode cpp"><em>C</em></code>, then
the class <code class="sourceCode cpp"><em>C</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_595" id="pnum_595">(1.2)</a></span>
Otherwise, <code class="sourceCode cpp"><em>PARENT-CLS</em><span class="op">(</span>parent_of<span class="op">(</span>r<span class="op">))</span></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_596" id="pnum_596">2</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_597" id="pnum_597">(2.1)</a></span>
<code class="sourceCode cpp">r</code> does not represent a class member
for which <code class="sourceCode cpp"><em>PARENT-CLS</em><span class="op">(</span>r<span class="op">)</span></code>
is an incomplete class and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_598" id="pnum_598">(2.2)</a></span>
<code class="sourceCode cpp">r</code> does not represent a direct base
class relationship between a base class and an incomplete derived
class.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_599" id="pnum_599">3</a></span>
Let <code class="sourceCode cpp"><em>DESIGNATING-CLS</em><span class="op">(</span>r, ctx<span class="op">)</span></code>
be:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_600" id="pnum_600">(3.1)</a></span>
If <code class="sourceCode cpp">ctx<span class="op">.</span>naming_class<span class="op">()</span></code>
represents a class <code class="sourceCode cpp"><em>C</em></code>, then
<code class="sourceCode cpp"><em>C</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_601" id="pnum_601">(3.2)</a></span>
Otherwise, <code class="sourceCode cpp"><em>PARENT-CLS</em><span class="op">(</span>r<span class="op">)</span></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_602" id="pnum_602">4</a></span>
<em>Returns</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_603" id="pnum_603">(4.1)</a></span>
If <code class="sourceCode cpp">r</code> represents an unnamed bit-field
<code class="sourceCode cpp"><em>F</em></code>, then <code class="sourceCode cpp">is_accessible<span class="op">(</span>r<sub><span class="math inline"><em>H</em></span></sub>, ctx<span class="op">)</span></code>
where
<code class="sourceCode cpp">r<sub><span class="math inline"><em>H</em></span></sub></code>
represents a hypothetical non-static data member of the class
represented by <code class="sourceCode cpp"><em>PARENT-CLS</em><span class="op">(</span>r<span class="op">)</span></code>
with the same access as <code class="sourceCode cpp"><em>F</em></code>.
<span class="note"><span>[ <em>Note 1:</em> </span>Unnamed bit-fields
are treated as class members for the purpose of
<code class="sourceCode cpp">is_accessible</code>.<span> — <em>end
note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_604" id="pnum_604">(4.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> does not represent a
class member or a direct base class relationship, then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_605" id="pnum_605">(4.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_606" id="pnum_606">(4.3.1)</a></span>
a class member that is not a (possibly indirect or variant) member of
<code class="sourceCode cpp"><em>DESIGNATING-CLS</em><span class="op">(</span>r, ctx<span class="op">)</span></code>
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_607" id="pnum_607">(4.3.2)</a></span>
a direct base class relationship such that <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>
does not represent <code class="sourceCode cpp"><em>DESIGNATING-CLS</em><span class="op">(</span>r, ctx<span class="op">)</span></code>
or a (direct or indirect) base class thereof,</li>
</ul>
<p>then
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_608" id="pnum_608">(4.4)</a></span>
Otherwise, if <code class="sourceCode cpp">ctx<span class="op">.</span>scope<span class="op">()</span></code>
is the null reflection, then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_609" id="pnum_609">(4.5)</a></span>
Otherwise, letting <code class="sourceCode cpp"><em>P</em></code> be a
program point whose immediate scope is the function parameter scope,
class scope, or namespace scope corresponding to the function, class, or
namespace represented by <code class="sourceCode cpp">ctx<span class="op">.</span>scope<span class="op">()</span></code>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_610" id="pnum_610">(4.5.1)</a></span>
If <code class="sourceCode cpp">r</code> represents a direct base class
relationship with base class
<code class="sourceCode cpp"><em>B</em></code>, then
<code class="sourceCode cpp"><span class="kw">true</span></code> if base
class <code class="sourceCode cpp"><em>B</em></code> of <code class="sourceCode cpp"><em>DESIGNATING-CLS</em><span class="op">(</span>r, ctx<span class="op">)</span></code>
is accessible at <code class="sourceCode cpp"><em>P</em></code>
([class.access.base]); otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_611" id="pnum_611">(4.5.2)</a></span>
Otherwise, <code class="sourceCode cpp">r</code> represents a class
member <code class="sourceCode cpp"><em>M</em></code>;
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp"><em>M</em></code> would be accessible at
<code class="sourceCode cpp"><em>P</em></code> when designated in <code class="sourceCode cpp"><em>DESIGNATING-CLS</em><span class="op">(</span>r, ctx<span class="op">)</span></code>
([class.access.base]) if the effect of any
<code class="sourceCode cpp"><em>using-declaration</em></code>s
([namespace.udecl]) were ignored. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</li>
</ul></li>
</ul>
<div class="note">
<p><span>[ <em>Note 2:</em> </span>The definitions of when a class
member or base class is accessible from a point
<code class="sourceCode cpp"><em>P</em></code> do not consider whether a
declaration of that entity is reachable from
<code class="sourceCode cpp"><em>P</em></code>.<span> — <em>end
note</em> ]</span></p>
</div>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb244"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb244-1"><a href="#cb244-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb244-2"><a href="#cb244-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb244-3"><a href="#cb244-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb244-4"><a href="#cb244-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb244-5"><a href="#cb244-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb244-6"><a href="#cb244-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> mem;</span>
<span id="cb244-7"><a href="#cb244-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">consteval</span> access_context fn<span class="op">()</span>;</span>
<span id="cb244-8"><a href="#cb244-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb244-9"><a href="#cb244-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^^</span>mem;</span>
<span id="cb244-10"><a href="#cb244-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb244-11"><a href="#cb244-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb244-12"><a href="#cb244-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_accessible<span class="op">(</span>Cls<span class="op">::</span>r, fn<span class="op">()))</span>;                        <span class="co">// OK</span></span>
<span id="cb244-13"><a href="#cb244-13" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_accessible<span class="op">(</span>Cls<span class="op">::</span>r, access_context<span class="op">::</span>current<span class="op">()))</span>;  <span class="co">// OK</span></span>
<span id="cb244-14"><a href="#cb244-14" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_accessible<span class="op">(</span>Cls<span class="op">::</span>r, access_context<span class="op">::</span>unchecked<span class="op">()))</span>; <span class="co">// OK</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb245"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb245-1"><a href="#cb245-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_nonstatic_data_members<span class="op">(</span></span>
<span id="cb245-2"><a href="#cb245-2" aria-hidden="true" tabindex="-1"></a>      info r,</span>
<span id="cb245-3"><a href="#cb245-3" aria-hidden="true" tabindex="-1"></a>      access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_612" id="pnum_612">5</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_613" id="pnum_613">(5.1)</a></span>
<code class="sourceCode cpp">nonstatic_data_members_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>
is a constant subexpression and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_614" id="pnum_614">(5.2)</a></span>
<code class="sourceCode cpp">r</code> does not represent a closure
type.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_615" id="pnum_615">6</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code> for
any <code class="sourceCode cpp"><em>R</em></code> in <code class="sourceCode cpp">nonstatic_data_members_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb246"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb246-1"><a href="#cb246-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_bases<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_616" id="pnum_616">7</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">bases_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>
is a constant subexpression.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_617" id="pnum_617">8</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code> for
any <code class="sourceCode cpp"><em>R</em></code> in <code class="sourceCode cpp">bases_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.member.queries-reflection-member-queries">[meta.reflection.member.queries]
Reflection member queries<a href="#meta.reflection.member.queries-reflection-member-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb247"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb247-1"><a href="#cb247-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> members_of<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_618" id="pnum_618">1</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is a reflection representing either a class type that is complete from
some point in the evaluation context or a namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_619" id="pnum_619">2</a></span>
A declaration <code class="sourceCode cpp"><em>D</em></code>
<em>members-of-precedes</em> a point
<code class="sourceCode cpp"><em>P</em></code> if
<code class="sourceCode cpp"><em>D</em></code> precedes either
<code class="sourceCode cpp"><em>P</em></code> or the point immediately
following the
<code class="sourceCode cpp"><em>class-specifier</em></code> of the
outermost class for which <code class="sourceCode cpp"><em>P</em></code>
is in a complete-class context.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_620" id="pnum_620">3</a></span>
A declaration <code class="sourceCode cpp"><em>D</em></code> of a member
<code class="sourceCode cpp"><em>M</em></code> of a class or namespace
<code class="sourceCode cpp"><em>Q</em></code> is
<em><code class="sourceCode cpp"><em>Q</em></code>-members-of-eligible</em>
if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_621" id="pnum_621">(3.1)</a></span>
<code class="sourceCode cpp"><em>M</em></code> is not a closure type
([expr.prim.lambda.closure]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_622" id="pnum_622">(3.2)</a></span>
<code class="sourceCode cpp"><em>M</em></code> is not a specialization
of a template ([temp.pre]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_623" id="pnum_623">(3.3)</a></span>
if <code class="sourceCode cpp"><em>Q</em></code> is a class that is not
a closure type, then <code class="sourceCode cpp"><em>M</em></code> is a
direct member of <code class="sourceCode cpp"><em>Q</em></code>
([class.mem.general]) that is not a variant member of a nested anonymous
union of <code class="sourceCode cpp"><em>Q</em></code>
([class.union.anon]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_624" id="pnum_624">(3.4)</a></span>
if <code class="sourceCode cpp"><em>Q</em></code> is a namespace, then
<code class="sourceCode cpp"><em>D</em></code> inhabits the namespace
scope of <code class="sourceCode cpp"><em>Q</em></code>, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_625" id="pnum_625">(3.5)</a></span>
if <code class="sourceCode cpp"><em>Q</em></code> is a closure type,
then <code class="sourceCode cpp"><em>M</em></code> is a function call
operator or function call operator template.</li>
</ul>
<p>It is implementation-defined whether declarations of other members of
a closure type <code class="sourceCode cpp"><em>Q</em></code> are
<code class="sourceCode cpp"><em>Q</em></code>-members-of-eligible.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_626" id="pnum_626">4</a></span>
A member <code class="sourceCode cpp"><em>M</em></code> of a class or
namespace <code class="sourceCode cpp"><em>Q</em></code> is
<em><code class="sourceCode cpp"><em>Q</em></code>-members-of-representable</em>
from a point <code class="sourceCode cpp"><em>P</em></code> if a
<code class="sourceCode cpp"><em>Q</em></code>-members-of-eligible
declaration of <code class="sourceCode cpp"><em>M</em></code>
members-of-precedes <code class="sourceCode cpp"><em>P</em></code> and
<code class="sourceCode cpp"><em>M</em></code> is</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_627" id="pnum_627">(4.1)</a></span>
a class or enumeration type,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_628" id="pnum_628">(4.2)</a></span>
a type alias,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_629" id="pnum_629">(4.3)</a></span>
a primary class template, function template, primary variable template,
alias template, or concept,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_630" id="pnum_630">(4.4)</a></span>
a variable or reference,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_631" id="pnum_631">(4.5)</a></span>
a function <code class="sourceCode cpp"><em>F</em></code> for which
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_632" id="pnum_632">(4.6)</a></span>
the type of <code class="sourceCode cpp"><em>F</em></code> does not
contain an undeduced placeholder type,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_633" id="pnum_633">(4.7)</a></span>
the constraints (if any) of
<code class="sourceCode cpp"><em>F</em></code> are satisfied, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_634" id="pnum_634">(4.8)</a></span>
if <code class="sourceCode cpp"><em>F</em></code> is a prospective
destructor, <code class="sourceCode cpp"><em>F</em></code> is the
selected destructor ([class.dtor]),</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_635" id="pnum_635">(4.9)</a></span>
a non-static data member,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_636" id="pnum_636">(4.10)</a></span>
a namespace, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_637" id="pnum_637">(4.11)</a></span>
a namespace alias.</li>
</ul>
<p><span class="note"><span>[ <em>Note 1:</em> </span>Examples of direct
members that are not
<code class="sourceCode cpp"><em>Q</em></code>-members-of-representable
for any entity <code class="sourceCode cpp"><em>Q</em></code> include:
unscoped enumerators ([enum]), partial specializations of templates
([temp.spec.partial]), and closure types
([expr.prim.lambda.closure]).<span> — <em>end
note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_638" id="pnum_638">5</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing reflections of all members
<code class="sourceCode cpp"><em>M</em></code> of the entity
<code class="sourceCode cpp"><em>Q</em></code> represented by <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
for which</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_639" id="pnum_639">(5.1)</a></span>
<code class="sourceCode cpp"><em>M</em></code> is
<code class="sourceCode cpp"><em>Q</em></code>-members-of-representable
from some point in the evaluation context and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_640" id="pnum_640">(5.2)</a></span>
<code class="sourceCode cpp">is_accessible<span class="op">(^^</span><em>M</em>, ctx<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
</ul>
<p>If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a class <code class="sourceCode cpp"><em>C</em></code>, then
the <code class="sourceCode cpp">vector</code> also contains reflections
representing all unnamed bit-fields
<code class="sourceCode cpp"><em>B</em></code> whose declarations
inhabit the class scope corresponding to
<code class="sourceCode cpp"><em>C</em></code> for which <code class="sourceCode cpp">is_accessible<span class="op">(^^</span><em>B</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Reflections of class members and unnamed bit-fields that are declared
appear in the order in which they are declared. <span class="note"><span>[ <em>Note 2:</em> </span>Base classes are not
members. Implicitly-declared special members appear after any
user-declared members ([special]).<span> — <em>end
note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb248"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb248-1"><a href="#cb248-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> B <span class="op">{}</span>;</span>
<span id="cb248-2"><a href="#cb248-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb248-3"><a href="#cb248-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">:</span> B <span class="op">{</span></span>
<span id="cb248-4"><a href="#cb248-4" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb248-5"><a href="#cb248-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> I;</span>
<span id="cb248-6"><a href="#cb248-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb248-7"><a href="#cb248-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> m;</span>
<span id="cb248-8"><a href="#cb248-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb248-9"><a href="#cb248-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb248-10"><a href="#cb248-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>members_of<span class="op">(^^</span>S, access_context<span class="op">::</span>current<span class="op">()).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">7</span><span class="op">)</span>;    <span class="co">// 6 special members, 1 public member, does not include base</span></span>
<span id="cb248-11"><a href="#cb248-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>members_of<span class="op">(^^</span>S, access_context<span class="op">::</span>unchecked<span class="op">()).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">8</span><span class="op">)</span>;  <span class="co">// all of the above, as well a reflection representing S::I</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb249"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb249-1"><a href="#cb249-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> bases_of<span class="op">(</span>info type, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_641" id="pnum_641">6</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
represents a class type that is complete from some point in the
evaluation context.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_642" id="pnum_642">7</a></span>
<em>Returns</em>: Let <code class="sourceCode cpp"><em>C</em></code> be
the class represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>.
A <code class="sourceCode cpp">vector</code> containing the reflections
of all the direct base class relationships
<code class="sourceCode cpp"><em>B</em></code>, if any, of
<code class="sourceCode cpp"><em>C</em></code> such that <code class="sourceCode cpp">is_accessible<span class="op">(^^</span><em>B</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>. The
direct base class relationships appear in the order in which the
corresponding base classes appear in the
<code class="sourceCode cpp"><em>base-specifier-list</em></code> of
<code class="sourceCode cpp"><em>C</em></code>.</p>
<div class="sourceCode" id="cb250"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb250-1"><a href="#cb250-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> static_data_members_of<span class="op">(</span>info type, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_643" id="pnum_643">8</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
represents a class type that is complete from some point in the
evaluation context.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_644" id="pnum_644">9</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing each element <code class="sourceCode cpp">e</code> of <code class="sourceCode cpp">members_of<span class="op">(</span>type, ctx<span class="op">)</span></code>
such that <code class="sourceCode cpp">is_variable<span class="op">(</span>e<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
preserving their order.</p>
<div class="sourceCode" id="cb251"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb251-1"><a href="#cb251-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> nonstatic_data_members_of<span class="op">(</span>info type, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_645" id="pnum_645">10</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
represents a class type that is complete from some point in the
evaluation context.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_646" id="pnum_646">11</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing each element <code class="sourceCode cpp">e</code> of <code class="sourceCode cpp">members_of<span class="op">(</span>type, ctx<span class="op">)</span></code>
such that <code class="sourceCode cpp">is_nonstatic_data_member<span class="op">(</span>e<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
preserving their order.</p>
<div class="sourceCode" id="cb252"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb252-1"><a href="#cb252-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> enumerators_of<span class="op">(</span>info type_enum<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_647" id="pnum_647">12</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>type_enum<span class="op">)</span></code>
represents an enumeration type and <code class="sourceCode cpp">is_enumerable_type<span class="op">(</span>type_enum<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_648" id="pnum_648">13</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing the reflections of each enumerator of the enumeration
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type_enum<span class="op">)</span></code>,
in the order in which they are declared.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.layout-reflection-layout-queries">[meta.reflection.layout]
Reflection layout queries<a href="#meta.reflection.layout-reflection-layout-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb253"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb253-1"><a href="#cb253-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> member_offset <span class="op">{</span></span>
<span id="cb253-2"><a href="#cb253-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ptrdiff_t</span> bytes;</span>
<span id="cb253-3"><a href="#cb253-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ptrdiff_t</span> bits;</span>
<span id="cb253-4"><a href="#cb253-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">ptrdiff_t</span> total_bits<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb253-5"><a href="#cb253-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&gt;(</span><span class="kw">const</span> member_offset<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb253-6"><a href="#cb253-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb253-7"><a href="#cb253-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb253-8"><a href="#cb253-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">ptrdiff_t</span> member_offset<span class="op">::</span>total_bits<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_649" id="pnum_649">1</a></span>
<em>Returns</em>: <code class="sourceCode cpp">bytes <span class="op">*</span> CHAR_BIT <span class="op">+</span> bits</code>.</p>
<div class="sourceCode" id="cb254"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb254-1"><a href="#cb254-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> member_offset offset_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_650" id="pnum_650">2</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">r</code> represents
a non-static data member, unnamed bit-field, or direct base class
relationship other than a virtual base class of an abstract class.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_651" id="pnum_651">3</a></span>
Let <code class="sourceCode cpp"><em>V</em></code> be the offset in bits
from the beginning of a complete object of type <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>
to the subobject associated with the entity represented by
<code class="sourceCode cpp">r</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_652" id="pnum_652">4</a></span>
<em>Returns</em>: <code class="sourceCode cpp"><span class="op">{</span><em>V</em> <span class="op">/</span> CHAR_BIT, <em>V</em> <span class="op">%</span> CHAR_BIT<span class="op">}</span></code>.</p>
<div class="sourceCode" id="cb255"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb255-1"><a href="#cb255-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> size_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_653" id="pnum_653">5</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of a type, object, value, variable of non-reference
type, non-static data member that is not a bit-field, direct base class
relationship, or data member description
(<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) ([class.mem.general])
where <code class="sourceCode cpp"><em>W</em></code> is not ⊥. If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type, then <code class="sourceCode cpp">is_complete_type<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_654" id="pnum_654">6</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> represents a
non-static data member of type
<code class="sourceCode cpp"><em>T</em></code>, a data member
description (<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>), or <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type <code class="sourceCode cpp"><em>T</em></code>, then
<code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span><em>LAT</em><span class="op">)</span></code>
where <code class="sourceCode cpp"><em>LAT</em></code> is the
layout-associated type ([class.member.general]) of a non-static data
member of type <code class="sourceCode cpp"><em>T</em></code>.
Otherwise, <code class="sourceCode cpp">size_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>.</p>
<p><span class="note"><span>[ <em>Note 1:</em> </span>It is possible
that while <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span><span class="dt">char</span><span class="op">)</span> <span class="op">==</span> size_of<span class="op">(^^</span><span class="dt">char</span><span class="op">)</span></code>
that <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span><span class="dt">char</span><span class="op">&amp;)</span> <span class="op">!=</span> size_of<span class="op">(^^</span><span class="dt">char</span><span class="op">&amp;)</span></code>.
If <code class="sourceCode cpp">b</code> represents a direct base class
relationship of an empty base class, then <code class="sourceCode cpp">size_of<span class="op">(</span>b<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">0</span></code>.<span>
— <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb256"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb256-1"><a href="#cb256-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> alignment_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_655" id="pnum_655">7</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of a type, object, variable of non-reference type,
non-static data member that is not a bit-field, direct base class
relationship, or data member description. If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type, then <code class="sourceCode cpp">is_complete_type<span class="op">(</span>r<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_656" id="pnum_656">8</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_657" id="pnum_657">(8.1)</a></span>
If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type <code class="sourceCode cpp"><em>T</em></code>, then
the alignment requirement for the layout-associated type
([class.mem.general]) for a non-static data member of type
<code class="sourceCode cpp"><em>T</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_658" id="pnum_658">(8.2)</a></span>
Otherwise, if <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a variable or object, then the alignment requirement of the
variable or object.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_659" id="pnum_659">(8.3)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship, then <code class="sourceCode cpp">alignment_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_660" id="pnum_660">(8.4)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a
non-static data member, then the alignment requirement of the subobject
associated with the represented entity within any object of type <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_661" id="pnum_661">(8.5)</a></span>
Otherwise, <code class="sourceCode cpp">r</code> represents a data
member description (<code class="sourceCode cpp"><em>TR</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) ([class.mem.general]).
If <code class="sourceCode cpp"><em>A</em></code> is not ⊥, then the
value <code class="sourceCode cpp"><em>A</em></code>. Otherwise <code class="sourceCode cpp"><span class="kw">alignof</span><span class="op">(</span><em>T</em><span class="op">)</span></code>
where the corresponding subobject of
<code class="sourceCode cpp"><em>TR</em></code> would have type
<code class="sourceCode cpp"><em>T</em></code>.</li>
</ul>
<div class="sourceCode" id="cb257"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb257-1"><a href="#cb257-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> bit_size_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_662" id="pnum_662">9</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of a type, object, value, variable of non-reference
type, non-static data member, unnamed bit-field, direct base class
relationship, or data member description. If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
represents a type <code class="sourceCode cpp"><em>T</em></code>, there
is a point within the evaluation context from which
<code class="sourceCode cpp"><em>T</em></code> is not incomplete.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_663" id="pnum_663">10</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_664" id="pnum_664">(10.1)</a></span>
If <code class="sourceCode cpp">r</code> represents a non-static data
member that is a bit-field or an unnamed bit-field with width
<code class="sourceCode cpp"><em>W</em></code>, then
<code class="sourceCode cpp"><em>W</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_665" id="pnum_665">(10.2)</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a data
member description (<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) ([class.mem.general])
and <code class="sourceCode cpp"><em>W</em></code> is not ⊥, then
<code class="sourceCode cpp"><em>W</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_666" id="pnum_666">(10.3)</a></span>
Otherwise, <code class="sourceCode cpp">CHAR_BIT <span class="op">*</span> size_of<span class="op">(</span>r<span class="op">)</span></code>.</li>
</ul>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.extract-value-extraction">[meta.reflection.extract]
Value extraction<a href="#meta.reflection.extract-value-extraction" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_667" id="pnum_667">1</a></span>
The <code class="sourceCode cpp">extract</code> function template may be
used to extract a value out of a reflection when its type is known.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_668" id="pnum_668">2</a></span>
The following are defined for exposition only to aid in the
specification of <code class="sourceCode cpp">extract</code>:</p>
<div class="sourceCode" id="cb258"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb258-1"><a href="#cb258-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb258-2"><a href="#cb258-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> T <em>extract-ref</em><span class="op">(</span>info r<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_669" id="pnum_669">3</a></span>
<span class="note"><span>[ <em>Note 1:</em>
</span><code class="sourceCode cpp">T</code> is a reference type.<span>
— <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_670" id="pnum_670">4</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_671" id="pnum_671">(4.1)</a></span>
<code class="sourceCode cpp">r</code> represents a variable or object of
type <code class="sourceCode cpp">U</code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_672" id="pnum_672">(4.2)</a></span>
<code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>U<span class="op">&gt;(*)[]</span>, remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;(*)[]&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, and
<span class="note"><span>[ <em>Note 2:</em> </span>The intent is to
allow only qualification conversions from
<code class="sourceCode cpp">U</code> to
<code class="sourceCode cpp">T</code>.<span> — <em>end
note</em> ]</span></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_673" id="pnum_673">(4.3)</a></span>
if <code class="sourceCode cpp">r</code> represents a variable, then
either that variable is usable in constant expressions or its lifetime
began within the core constant expression currently under
evaluation.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_674" id="pnum_674">5</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> represents an
object <code class="sourceCode cpp"><em>O</em></code>, then a reference
to <code class="sourceCode cpp"><em>O</em></code>. Otherwise, a
reference to the object declared, or referred to, by the variable
represented by <code class="sourceCode cpp">r</code>.</p>
<div class="sourceCode" id="cb259"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb259-1"><a href="#cb259-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb259-2"><a href="#cb259-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> T <em>extract-member-or-function</em><span class="op">(</span>info r<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_675" id="pnum_675">6</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_676" id="pnum_676">(6.1)</a></span>
<code class="sourceCode cpp">r</code> represents a non-static data
member with type <code class="sourceCode cpp">X</code>, that is not a
bit-field, that is a direct member of a class
<code class="sourceCode cpp">C</code> and
<code class="sourceCode cpp">T</code> is
<code class="sourceCode cpp">X C<span class="op">::*</span></code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_677" id="pnum_677">(6.2)</a></span>
<code class="sourceCode cpp">r</code> represents an implicit object
member function with type <code class="sourceCode cpp">F</code> or
<code class="sourceCode cpp">F <span class="kw">noexcept</span></code>
that is a direct member of a class <code class="sourceCode cpp">C</code>
and <code class="sourceCode cpp">T</code> is
<code class="sourceCode cpp">F C<span class="op">::*</span></code>;
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_678" id="pnum_678">(6.3)</a></span>
<code class="sourceCode cpp">r</code> represents a non-member function,
static member function, or explicit object member function of function
type <code class="sourceCode cpp">F</code> or
<code class="sourceCode cpp">F <span class="kw">noexcept</span></code>
and <code class="sourceCode cpp">T</code> is
<code class="sourceCode cpp">F<span class="op">*</span></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_679" id="pnum_679">7</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_680" id="pnum_680">(7.1)</a></span>
If <code class="sourceCode cpp">T</code> is a pointer type, then a
pointer value pointing to the function represented by
<code class="sourceCode cpp">r</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_681" id="pnum_681">(7.2)</a></span>
Otherwise, a pointer-to-member value designating the non-static data
member or function represented by
<code class="sourceCode cpp">r</code>.</li>
</ul>
<div class="sourceCode" id="cb260"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb260-1"><a href="#cb260-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb260-2"><a href="#cb260-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> T <em>extract-value</em><span class="op">(</span>info r<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_682" id="pnum_682">8</a></span>
Let <code class="sourceCode cpp">U</code> be the type of the value or
object that <code class="sourceCode cpp">r</code> represents.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_683" id="pnum_683">9</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_684" id="pnum_684">(9.1)</a></span>
<code class="sourceCode cpp">U</code> is a pointer type,
<code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code> are similar types ([conv.qual]),
and <code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>U, T<span class="op">&gt;</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_685" id="pnum_685">(9.2)</a></span>
<code class="sourceCode cpp">U</code> is not a pointer type and the
cv-unqualified types of <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code> are the same,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_686" id="pnum_686">(9.3)</a></span>
<code class="sourceCode cpp">U</code> is an array type,
<code class="sourceCode cpp">T</code> is pointer type, and the value
<code class="sourceCode cpp">r</code> represents is convertible to
<code class="sourceCode cpp">T</code>, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_687" id="pnum_687">(9.4)</a></span>
<code class="sourceCode cpp">U</code> is a closure type,
<code class="sourceCode cpp">T</code> is a function pointer type, and
the value that <code class="sourceCode cpp">r</code> represents is
convertible to <code class="sourceCode cpp">T</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_688" id="pnum_688">10</a></span>
<em>Returns</em>: <code class="sourceCode cpp"><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">&gt;([:</span><em>R</em><span class="op">:])</span></code>,
where <code class="sourceCode cpp"><em>R</em></code> is a constant
expression of type <code class="sourceCode cpp">info</code> such that
<code class="sourceCode cpp"><em>R</em> <span class="op">==</span> r</code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<div class="sourceCode" id="cb261"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb261-1"><a href="#cb261-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb261-2"><a href="#cb261-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> T extract<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_689" id="pnum_689">11</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb262"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb262-1"><a href="#cb262-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>is_reference_type<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb262-2"><a href="#cb262-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>extract-ref</em><span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span>;</span>
<span id="cb262-3"><a href="#cb262-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>is_nonstatic_data_member<span class="op">(</span>r<span class="op">)</span> <span class="op">||</span> is_function<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb262-4"><a href="#cb262-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>extract-member-or-function</em><span class="op">&lt;</span>T<span class="op">&gt;(</span>r<span class="op">)</span>;</span>
<span id="cb262-5"><a href="#cb262-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb262-6"><a href="#cb262-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>extract-value</em><span class="op">&lt;</span>T<span class="op">&gt;(</span>constant_of<span class="op">(</span>r<span class="op">))</span>;</span>
<span id="cb262-7"><a href="#cb262-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.substitute-reflection-substitution">[meta.reflection.substitute]
Reflection substitution<a href="#meta.reflection.substitute-reflection-substitution" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb263"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb263-1"><a href="#cb263-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> R<span class="op">&gt;</span></span>
<span id="cb263-2"><a href="#cb263-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> reflection_range <span class="op">=</span></span>
<span id="cb263-3"><a href="#cb263-3" aria-hidden="true" tabindex="-1"></a>  ranges<span class="op">::</span>input_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb263-4"><a href="#cb263-4" aria-hidden="true" tabindex="-1"></a>  same_as<span class="op">&lt;</span>ranges<span class="op">::</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, info<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb263-5"><a href="#cb263-5" aria-hidden="true" tabindex="-1"></a>  same_as<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span>, info<span class="op">&gt;</span>;</span></code></pre></div>
<div class="sourceCode" id="cb264"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb264-1"><a href="#cb264-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb264-2"><a href="#cb264-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> can_substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> arguments<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_690" id="pnum_690">1</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">templ</code>
represents a template and every reflection in
<code class="sourceCode cpp">arguments</code> represents a construct
usable as a template argument ([temp.arg]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_691" id="pnum_691">2</a></span>
Let <code class="sourceCode cpp">Z</code> be the template represented by
<code class="sourceCode cpp">templ</code> and let
<code class="sourceCode cpp">Args<span class="op">...</span></code> be a
sequence of prvalue constant expressions that compute the reflections
held by the elements of
<code class="sourceCode cpp">arguments</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_692" id="pnum_692">3</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">Z<span class="op">&lt;[:</span>Args<span class="op">:]...&gt;</span></code>
is a valid <code class="sourceCode cpp"><em>template-id</em></code>
([temp.names]) that does not name a function whose type contains an
undeduced placeholder type. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_693" id="pnum_693">4</a></span>
<span class="note"><span>[ <em>Note 1:</em> </span>If forming <code class="sourceCode cpp">Z<span class="op">&lt;[:</span>Args<span class="op">:]...&gt;</span></code>
leads to a failure outside of the immediate context, the program is
ill-formed.<span> — <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb265"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb265-1"><a href="#cb265-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb265-2"><a href="#cb265-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info substitute<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> arguments<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_694" id="pnum_694">5</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">can_substitute<span class="op">(</span>templ, arguments<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_695" id="pnum_695">6</a></span>
Let <code class="sourceCode cpp">Z</code> be the template represented by
<code class="sourceCode cpp">templ</code> and let
<code class="sourceCode cpp">Args<span class="op">...</span></code> be a
sequence of prvalue constant expressions that compute the reflections
held by the elements of
<code class="sourceCode cpp">arguments</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_696" id="pnum_696">7</a></span>
<em>Returns</em>: <code class="sourceCode cpp"><span class="op">^^</span>Z<span class="op">&lt;[:</span>Args<span class="op">:]...&gt;</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_697" id="pnum_697">8</a></span>
<span class="note"><span>[ <em>Note 2:</em> </span>If forming <code class="sourceCode cpp">Z<span class="op">&lt;[:</span>Args<span class="op">:]...&gt;</span></code>
leads to a failure outside of the immediate context, the program is
ill-formed.<span> — <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_698" id="pnum_698">9</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb266"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb266-1"><a href="#cb266-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="op">&gt;</span></span>
<span id="cb266-2"><a href="#cb266-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> fn1<span class="op">()</span>;</span>
<span id="cb266-3"><a href="#cb266-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb266-4"><a href="#cb266-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>can_substitute<span class="op">(^^</span>fn1, <span class="op">{^^</span><span class="dt">int</span><span class="op">}))</span>;  <span class="co">// OK</span></span>
<span id="cb266-5"><a href="#cb266-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> info r1 <span class="op">=</span> substitute<span class="op">(^^</span>fn1, <span class="op">{^^</span><span class="dt">int</span><span class="op">})</span>;</span>
<span id="cb266-6"><a href="#cb266-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: fn&lt;int&gt; contains an undeduced placeholder type</span></span>
<span id="cb266-7"><a href="#cb266-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb266-8"><a href="#cb266-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="cb266-9"><a href="#cb266-9" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> fn2<span class="op">()</span> <span class="op">{</span></span>
<span id="cb266-10"><a href="#cb266-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(^^</span>T <span class="op">!=</span> <span class="op">^^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb266-11"><a href="#cb266-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// static assertion failed during instantiation of fn&lt;int&gt;</span></span>
<span id="cb266-12"><a href="#cb266-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="dv">0</span>;</span>
<span id="cb266-13"><a href="#cb266-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb266-14"><a href="#cb266-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb266-15"><a href="#cb266-15" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> r2 <span class="op">=</span> can_substitute<span class="op">(^^</span>fn2, <span class="op">{^^</span><span class="dt">int</span><span class="op">})</span>;</span>
<span id="cb266-16"><a href="#cb266-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// error: instantiation of body of fn&lt;int&gt; is needed to deduce return type</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_699" id="pnum_699">10</a></span></p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<div class="sourceCode" id="cb267"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb267-1"><a href="#cb267-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info to_integral_constant<span class="op">(</span><span class="dt">unsigned</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb267-2"><a href="#cb267-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> substitute<span class="op">(^^</span>integral_constant, <span class="op">{^^</span><span class="dt">unsigned</span>, reflect_constant<span class="op">(</span>i<span class="op">)})</span>;</span>
<span id="cb267-3"><a href="#cb267-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb267-4"><a href="#cb267-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> info r <span class="op">=</span> to_integral_constant<span class="op">(</span><span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb267-5"><a href="#cb267-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, r represents the type integral_constant&lt;unsigned, 2&gt;</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.result-expression-result-reflection">[meta.reflection.result]
Expression result reflection<a href="#meta.reflection.result-expression-result-reflection" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_700" id="pnum_700">1</a></span>
An object <code class="sourceCode cpp"><em>O</em></code> of type
<code class="sourceCode cpp"><em>T</em></code> is
<em>meta-reflectable</em> if an lvalue expression denoting
<code class="sourceCode cpp"><em>O</em></code> is suitable for use as a
constant template argument for a constant template parameter of type
<code class="sourceCode cpp"><em>T</em><span class="op">&amp;</span></code>
([temp.arg.nontype]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_701" id="pnum_701">2</a></span>
The following are defined for exposition only to aid in the
specification of
<code class="sourceCode cpp">reflect_constant</code>:</p>
<div class="sourceCode" id="cb268"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb268-1"><a href="#cb268-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="op">&gt;</span></span>
<span id="cb268-2"><a href="#cb268-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info <em>reflect-constant-scalar</em><span class="op">(</span>T expr<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p>Let <code class="sourceCode cpp"><em>V</em></code> be the value of
<code class="sourceCode cpp">expr</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_702" id="pnum_702">3</a></span>
<em>Constant When</em>: If
<code class="sourceCode cpp"><em>V</em></code> is a pointer to an
object, then that object is meta-reflectable.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_703" id="pnum_703">4</a></span>
<em>Returns</em>: A reflection of a value of type
<code class="sourceCode cpp"><em>T</em></code> with the computed value
<code class="sourceCode cpp"><em>V</em></code>.</p>
<div class="sourceCode" id="cb269"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb269-1"><a href="#cb269-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="op">&gt;</span></span>
<span id="cb269-2"><a href="#cb269-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info <em>reflect-constant-class</em><span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> expr<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_704" id="pnum_704">5</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">is_copy_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp">T</code> is structural ([temp.param]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_705" id="pnum_705">6</a></span>
Let <code class="sourceCode cpp"><em>V</em></code> be an invented
variable that would be introduced by the declaration</p>
<div class="sourceCode" id="cb270"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb270-1"><a href="#cb270-1" aria-hidden="true" tabindex="-1"></a>T <em>V</em><span class="op">(</span>expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_706" id="pnum_706">7</a></span>
<em>Constant When</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_707" id="pnum_707">(7.1)</a></span>
<code class="sourceCode cpp"><em>V</em></code> satisfies the semantic
constraints for the definition of a constexpr variable with static
storage duration ([dcl.constexpr]) and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_708" id="pnum_708">(7.2)</a></span>
given the invented template</p>
<div class="sourceCode" id="cb271"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb271-1"><a href="#cb271-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>T P<span class="op">&gt;</span> <span class="kw">struct</span> TCls;</span></code></pre></div>
<p>the <code class="sourceCode cpp"><em>template-id</em></code> <code class="sourceCode cpp">TCls<span class="op">&lt;</span><em>V</em><span class="op">&gt;</span></code>
would be valid.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_709" id="pnum_709">8</a></span>
<em>Returns</em>: A reflection of the template parameter object that is
template-argument-equivalent to the object denoted by
<code class="sourceCode cpp"><em>V</em></code> ([temp.param]).</p>
<div class="sourceCode" id="cb272"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb272-1"><a href="#cb272-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="op">&gt;</span></span>
<span id="cb272-2"><a href="#cb272-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_constant<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_710" id="pnum_710">*</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb273"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb273-1"><a href="#cb273-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>is_class_type<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb273-2"><a href="#cb273-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>reflect-constant-class</em><span class="op">(</span>expr<span class="op">)</span>;</span>
<span id="cb273-3"><a href="#cb273-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb273-4"><a href="#cb273-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>reflect-constant-scalar</em><span class="op">(</span>expr<span class="op">)</span>;</span>
<span id="cb273-5"><a href="#cb273-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><span class="note"><span>[ <em>Note 1:</em> </span>Array-to-pointer
and function-to-function-pointer decay occur.<span> — <em>end
note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb274"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb274-1"><a href="#cb274-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> D<span class="op">&gt;</span></span>
<span id="cb274-2"><a href="#cb274-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb274-3"><a href="#cb274-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb274-4"><a href="#cb274-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> N <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb274-5"><a href="#cb274-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> K <span class="op">{</span> <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> p; <span class="op">}</span>;</span>
<span id="cb274-6"><a href="#cb274-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb274-7"><a href="#cb274-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> reflect_constant<span class="op">(</span><span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb274-8"><a href="#cb274-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_value<span class="op">(</span>r1<span class="op">))</span>;</span>
<span id="cb274-9"><a href="#cb274-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>r1 <span class="op">==</span> template_arguments_of<span class="op">(^^</span>A<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;)[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb274-10"><a href="#cb274-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb274-11"><a href="#cb274-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> reflect_constant<span class="op">(</span>N<span class="op">{</span><span class="dv">42</span><span class="op">})</span>;</span>
<span id="cb274-12"><a href="#cb274-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_object<span class="op">(</span>r2<span class="op">))</span>;</span>
<span id="cb274-13"><a href="#cb274-13" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>r2 <span class="op">==</span> template_arguments_of<span class="op">(^^</span>A<span class="op">&lt;</span>N<span class="op">{</span><span class="dv">42</span><span class="op">}&gt;)[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb274-14"><a href="#cb274-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb274-15"><a href="#cb274-15" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r3 <span class="op">=</span> reflect_constant<span class="op">(</span>K<span class="op">{</span><span class="kw">nullptr</span><span class="op">})</span>; <span class="co">// ok</span></span>
<span id="cb274-16"><a href="#cb274-16" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r4 <span class="op">=</span> reflect_constant<span class="op">(</span>K<span class="op">{</span><span class="st">&quot;ebab&quot;</span><span class="op">})</span>;  <span class="co">// error: constituent pointer points to string literal</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb275"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb275-1"><a href="#cb275-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="op">&gt;</span></span>
<span id="cb275-2"><a href="#cb275-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_object<span class="op">(</span>T<span class="op">&amp;</span> expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_711" id="pnum_711">9</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">T</code> is not a
function type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_712" id="pnum_712">10</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">expr</code>
designates a meta-reflectable object.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_713" id="pnum_713">11</a></span>
<em>Returns</em>: A reflection of the object designated by
<code class="sourceCode cpp">expr</code>.</p>
<div class="sourceCode" id="cb276"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb276-1"><a href="#cb276-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="op">&gt;</span></span>
<span id="cb276-2"><a href="#cb276-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_function<span class="op">(</span>T<span class="op">&amp;</span> fn<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_714" id="pnum_714">12</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">T</code> is a function
type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_715" id="pnum_715">13</a></span>
<em>Returns</em>: A reflection of the function designated by
<code class="sourceCode cpp">fn</code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.define.aggregate-reflection-class-definition-generation">[meta.reflection.define.aggregate]
Reflection class definition generation<a href="#meta.reflection.define.aggregate-reflection-class-definition-generation" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb277"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb277-1"><a href="#cb277-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> data_member_options <span class="op">{</span></span>
<span id="cb277-2"><a href="#cb277-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em>name-type</em> <span class="op">{</span> <span class="co">// exposition only</span></span>
<span id="cb277-3"><a href="#cb277-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>u8string, T<span class="op">&gt;</span></span>
<span id="cb277-4"><a href="#cb277-4" aria-hidden="true" tabindex="-1"></a>      <span class="kw">consteval</span> <em>name-type</em><span class="op">(</span>T <span class="op">&amp;&amp;)</span>;</span>
<span id="cb277-5"><a href="#cb277-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb277-6"><a href="#cb277-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>string, T<span class="op">&gt;</span></span>
<span id="cb277-7"><a href="#cb277-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">consteval</span> <em>name-type</em><span class="op">(</span>T <span class="op">&amp;&amp;)</span>;</span>
<span id="cb277-8"><a href="#cb277-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb277-9"><a href="#cb277-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb277-10"><a href="#cb277-10" aria-hidden="true" tabindex="-1"></a>    variant<span class="op">&lt;</span>u8string, string<span class="op">&gt;</span> <em>contents</em>;    <span class="co">// exposition only</span></span>
<span id="cb277-11"><a href="#cb277-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb277-12"><a href="#cb277-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb277-13"><a href="#cb277-13" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span><em>name-type</em><span class="op">&gt;</span> name;</span>
<span id="cb277-14"><a href="#cb277-14" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> alignment;</span>
<span id="cb277-15"><a href="#cb277-15" aria-hidden="true" tabindex="-1"></a>  optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> bit_width;</span>
<span id="cb277-16"><a href="#cb277-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> no_unique_address <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb277-17"><a href="#cb277-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_716" id="pnum_716">1</a></span>
The classes <code class="sourceCode cpp">data_member_options</code> and
<code class="sourceCode cpp">data_member_options<span class="op">::</span><em>name-type</em></code>
are consteval-only types ([basic.types.general]), and are not structural
types ([temp.param]).</p>
<div class="sourceCode" id="cb278"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb278-1"><a href="#cb278-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>u8string, T<span class="op">&gt;</span></span>
<span id="cb278-2"><a href="#cb278-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> data_member_options<span class="op">::</span><em>name-type</em><span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_717" id="pnum_717">2</a></span>
<em>Effects</em>: Initializes
<code class="sourceCode cpp"><em>contents</em></code> with <code class="sourceCode cpp">u8string<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>T<span class="op">&gt;(</span>value<span class="op">))</span></code>.</p>
<div class="sourceCode" id="cb279"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb279-1"><a href="#cb279-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>string, T<span class="op">&gt;</span></span>
<span id="cb279-2"><a href="#cb279-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> data_member_options<span class="op">::</span><em>name-type</em><span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_718" id="pnum_718">3</a></span>
<em>Effects</em>: Initializes
<code class="sourceCode cpp"><em>contents</em></code> with <code class="sourceCode cpp">string<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>T<span class="op">&gt;(</span>value<span class="op">))</span></code>.</p>
<div class="note">
<p><span>[ <em>Note 1:</em> </span>The class
<code class="sourceCode cpp"><em>name-type</em></code> allows the
function <code class="sourceCode cpp">data_member_spec</code> to accept
an ordinary string literal (or
<code class="sourceCode cpp">string_view</code>,
<code class="sourceCode cpp">string</code>, etc.) or a UTF-8 string
literal (or <code class="sourceCode cpp">u8string_view</code>,
<code class="sourceCode cpp">u8string</code>, etc.) equally well.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb280"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb280-1"><a href="#cb280-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">void</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb280-2"><a href="#cb280-2" aria-hidden="true" tabindex="-1"></a>  data_member_options o1 <span class="op">=</span> <span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;ordinary_literal_encoding&quot;</span><span class="op">}</span>;</span>
<span id="cb280-3"><a href="#cb280-3" aria-hidden="true" tabindex="-1"></a>  data_member_options o2 <span class="op">=</span> <span class="op">{.</span>name<span class="op">=</span><span class="st">u8&quot;utf8_encoding&quot;</span><span class="op">}</span>;</span>
<span id="cb280-4"><a href="#cb280-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<span> — <em>end note</em> ]</span>
</div>
<div class="sourceCode" id="cb281"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb281-1"><a href="#cb281-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info data_member_spec<span class="op">(</span>info type,</span>
<span id="cb281-2"><a href="#cb281-2" aria-hidden="true" tabindex="-1"></a>                                data_member_options options<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_719" id="pnum_719">4</a></span>
<em>Constant When</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_720" id="pnum_720">(4.1)</a></span>
<code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
represents either an object type or a reference type;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_721" id="pnum_721">(4.2)</a></span>
if
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
contains a value, then:
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_722" id="pnum_722">(4.2.1)</a></span>
<code class="sourceCode cpp">holds_alternative<span class="op">&lt;</span>u8string<span class="op">&gt;(</span>options<span class="op">.</span>name<span class="op">-&gt;</span><em>contents</em><span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp">get<span class="op">&lt;</span>u8string<span class="op">&gt;(</span>options<span class="op">.</span>name<span class="op">-&gt;</span><em>contents</em><span class="op">)</span></code>
contains a valid identifier ([lex.name]) that is not a keyword
([lex.key]) when interpreted with UTF-8, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_723" id="pnum_723">(4.2.2)</a></span>
<code class="sourceCode cpp">holds_alternative<span class="op">&lt;</span>string<span class="op">&gt;(</span>options<span class="op">.</span>name<span class="op">-&gt;</span><em>contents</em><span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> and
<code class="sourceCode cpp">get<span class="op">&lt;</span>string<span class="op">&gt;(</span>options<span class="op">.</span>name<span class="op">-&gt;</span><em>contents</em><span class="op">)</span></code>
contains a valid identifier that is not a keyword when interpreted with
the ordinary literal encoding;</li>
</ul>
<span class="note"><span>[ <em>Note 2:</em> </span>The name corresponds
to the spelling of an identifier token after phase 6 of translation
([lex.phases]). Lexical constructs like
<code class="sourceCode cpp"><em>universal-character-name</em></code>s
[lex.universal.char] are not processed and will cause evaluation to
fail. For example, <code class="sourceCode cpp"><span class="st">&quot;</span><span class="sc">\u03B1</span><span class="st">&quot;</span></code>
is an invalid identifier and is not interpreted as <code class="sourceCode cpp"><span class="st">&quot;α&quot;</span></code>.<span>
— <em>end note</em> ]</span></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_724" id="pnum_724">(4.3)</a></span>
if
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
does not contain a value, then <code class="sourceCode cpp">options<span class="op">.</span>bit_width</code>
contains a value;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_725" id="pnum_725">(4.4)</a></span>
if <code class="sourceCode cpp">options<span class="op">.</span>bit_width</code>
contains a value <code class="sourceCode cpp"><em>V</em></code>, then
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_726" id="pnum_726">(4.4.1)</a></span>
<code class="sourceCode cpp">is_integral_type<span class="op">(</span>type<span class="op">)</span> <span class="op">||</span> is_enumeration_type<span class="op">(</span>type<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_727" id="pnum_727">(4.4.2)</a></span>
<code class="sourceCode cpp">options<span class="op">.</span>alignment</code>
does not contain a value,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_728" id="pnum_728">(4.4.3)</a></span>
<code class="sourceCode cpp">options<span class="op">.</span>no_unique_address</code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>,
and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_729" id="pnum_729">(4.4.4)</a></span>
if <code class="sourceCode cpp"><em>V</em></code> equals
<code class="sourceCode cpp"><span class="dv">0</span></code> then
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
does not contain a value; and</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_730" id="pnum_730">(4.5)</a></span>
if <code class="sourceCode cpp">options<span class="op">.</span>alignment</code>
contains a value, it is an alignment value ([basic.align]) not less than
<code class="sourceCode cpp">alignment_of<span class="op">(</span>type<span class="op">)</span></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_731" id="pnum_731">5</a></span>
<em>Returns</em>: A reflection of a data member description
(<code class="sourceCode cpp"><em>T</em></code>,
<code class="sourceCode cpp"><em>N</em></code>,
<code class="sourceCode cpp"><em>A</em></code>,
<code class="sourceCode cpp"><em>W</em></code>,
<code class="sourceCode cpp"><em>NUA</em></code>) (<span>11.4.1 <a href="https://wg21.link/class.mem.general">[class.mem.general]</a></span>)
where</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_732" id="pnum_732">(5.1)</a></span>
<code class="sourceCode cpp"><em>T</em></code> is the type represented
by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_733" id="pnum_733">(5.2)</a></span>
<code class="sourceCode cpp"><em>N</em></code> is either the identifier
encoded by
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
or ⊥ if
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
does not contain a value,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_734" id="pnum_734">(5.3)</a></span>
<code class="sourceCode cpp"><em>A</em></code> is either the alignment
value held by <code class="sourceCode cpp">options<span class="op">.</span>alignment</code>
or ⊥ if <code class="sourceCode cpp">options<span class="op">.</span>alignment</code>
does not contain a value,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_735" id="pnum_735">(5.4)</a></span>
<code class="sourceCode cpp"><em>W</em></code> is either the value held
by <code class="sourceCode cpp">options<span class="op">.</span>bit_width</code>
or ⊥ if <code class="sourceCode cpp">options<span class="op">.</span>bit_width</code>
does not contain a value, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_736" id="pnum_736">(5.5)</a></span>
<code class="sourceCode cpp"><em>NUA</em></code> is the value held by
<code class="sourceCode cpp">options<span class="op">.</span>no_unique_address</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_737" id="pnum_737">6</a></span>
<span class="note"><span>[ <em>Note 3:</em> </span>The returned
reflection value is primarily useful in conjunction with
<code class="sourceCode cpp">define_aggregate</code>; it can also be
queried by certain other functions in
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
(e.g., <code class="sourceCode cpp">type_of</code>,
<code class="sourceCode cpp">identifier_of</code>).<span> — <em>end
note</em> ]</span></span></p>
<div class="sourceCode" id="cb282"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb282-1"><a href="#cb282-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_data_member_spec<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_738" id="pnum_738">7</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> represents a data member
description. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb283"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb283-1"><a href="#cb283-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb283-2"><a href="#cb283-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info define_aggregate<span class="op">(</span>info class_type, R<span class="op">&amp;&amp;</span> mdescrs<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_739" id="pnum_739">8</a></span>
Let <code class="sourceCode cpp"><em>C</em></code> be the class
represented by <code class="sourceCode cpp">class_type</code> and
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code> be the
<code class="sourceCode cpp"><em>K</em></code><sup>th</sup> reflection
value in <code class="sourceCode cpp">mdescrs</code>. For every
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code> in
<code class="sourceCode cpp">mdescrs</code>, let
(<code class="sourceCode cpp"><span class="math inline"><em>T</em></span><sub><span class="math inline"><em>K</em></span></sub></code>,
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub></code>,
<code class="sourceCode cpp"><span class="math inline"><em>A</em></span><sub><span class="math inline"><em>K</em></span></sub></code>,
<code class="sourceCode cpp"><span class="math inline"><em>W</em></span><sub><span class="math inline"><em>K</em></span></sub></code>,
<code class="sourceCode cpp"><span class="math inline"><em>N</em><em>U</em><em>A</em></span><sub><span class="math inline"><em>K</em></span></sub></code>) be the corresponding
data member description represented by
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_740" id="pnum_740">9</a></span>
<em>Constant When</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_741" id="pnum_741">(9.1)</a></span>
<code class="sourceCode cpp"><em>C</em></code> is incomplete from every
point in the evaluation context; <span class="note"><span>[ <em>Note
4:</em> </span><code class="sourceCode cpp"><em>C</em></code> can be a
class template specialization for which there is a reachable definition
of the primary class template. In this case, the injected declaration is
an explicit specialization.<span> — <em>end
note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_742" id="pnum_742">(9.2)</a></span>
<code class="sourceCode cpp">is_data_member_spec<span class="op">(</span><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub><span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> for
every
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code>;</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_743" id="pnum_743">(9.3)</a></span>
<code class="sourceCode cpp">is_complete_type<span class="op">(</span><span class="math inline"><em>T</em></span><sub><span class="math inline"><em>K</em></span></sub><span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code> for
every
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code>; and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_744" id="pnum_744">(9.4)</a></span>
for every pair
(<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code>,
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>L</em></span></sub></code>) where
<code class="sourceCode cpp">K <span class="op">&lt;</span> L</code>, if
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is not ⊥ and
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>L</em></span></sub></code> is not ⊥, then
either:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_745" id="pnum_745">(9.4.1)</a></span>
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub> <span class="op">!=</span> <span class="math inline"><em>N</em></span><sub><span class="math inline"><em>L</em></span></sub></code> is
<code class="sourceCode cpp"><span class="kw">true</span></code> or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_746" id="pnum_746">(9.4.2)</a></span>
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub> <span class="op">==</span> <span class="st">u8&quot;_&quot;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
<span class="note"><span>[ <em>Note 5:</em> </span>Every provided
identifier is unique or <code class="sourceCode cpp"><span class="st">&quot;_&quot;</span></code>.<span>
— <em>end note</em> ]</span></span></li>
</ul></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_747" id="pnum_747">10</a></span>
<em>Effects</em>: Produces an injected declaration
<code class="sourceCode cpp"><em>D</em></code> ([expr.const]) that
defines <code class="sourceCode cpp"><em>C</em></code> and has
properties as follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_748" id="pnum_748">(10.1)</a></span>
The target scope of <code class="sourceCode cpp"><em>D</em></code> is
the scope to which <code class="sourceCode cpp"><em>C</em></code>
belongs ([basic.scope.scope]).</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_749" id="pnum_749">(10.2)</a></span>
The locus of <code class="sourceCode cpp"><em>D</em></code> follows
immediately after the core constant expression currently under
evaluation.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_750" id="pnum_750">(10.3)</a></span>
If <code class="sourceCode cpp"><em>C</em></code> is a specialization of
a templated class <code class="sourceCode cpp"><em>T</em></code>, and
<code class="sourceCode cpp"><em>C</em></code> is not a local class,
then <code class="sourceCode cpp"><em>D</em></code> is an explicit
specialization of
<code class="sourceCode cpp"><em>T</em></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_751" id="pnum_751">(10.4)</a></span>
For each
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code>, there is a
corresponding entity
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> belonging to the
class scope of <code class="sourceCode cpp"><em>D</em></code> with the
following properties:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_752" id="pnum_752">(10.4.1)</a></span>
If
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is ⊥,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is an unnamed
bit-field. Otherwise,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is a non-static data
member whose name is the identifier determined by the character sequence
encoded by
<code class="sourceCode cpp"><span class="math inline"><em>N</em></span><sub><span class="math inline"><em>K</em></span></sub></code> in UTF-8.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_753" id="pnum_753">(10.4.2)</a></span>
The type of
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is
<code class="sourceCode cpp"><span class="math inline"><em>T</em></span><sub><span class="math inline"><em>K</em></span></sub></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_754" id="pnum_754">(10.4.3)</a></span>
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is declared with the
attribute <code class="sourceCode cpp"><span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></code>
if and only if <code class="sourceCode cpp"><span class="math inline"><em>N</em><em>U</em><em>A</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_755" id="pnum_755">(10.4.4)</a></span>
If
<code class="sourceCode cpp"><span class="math inline"><em>W</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is not ⊥,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is a bit-field whose
width is that value. Otherwise,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is not a
bit-field.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_756" id="pnum_756">(10.4.5)</a></span>
If
<code class="sourceCode cpp"><span class="math inline"><em>A</em></span><sub><span class="math inline"><em>K</em></span></sub></code> is not ⊥,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> has the
<code class="sourceCode cpp"><em>alignment-specifier</em></code> <code class="sourceCode cpp"><span class="kw">alignas</span><span class="op">(</span><span class="math inline"><em>A</em></span><sub><span class="math inline"><em>K</em></span></sub><span class="op">)</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="math inline"><em>M</em></span><sub><span class="math inline"><em>K</em></span></sub></code> has no
<code class="sourceCode cpp"><em>alignment-specifier</em></code>.</li>
</ul></li>
<li><p>For every
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>L</em></span></sub></code> in
<code class="sourceCode cpp">mdescrs</code> such that
<code class="sourceCode cpp"><em>K</em> <span class="op">&lt;</span> <em>L</em></code>,
the declaration corresponding to
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>K</em></span></sub></code> precedes the
declaration corresponding to
<code class="sourceCode cpp"><span class="math inline"><em>r</em></span><sub><span class="math inline"><em>L</em></span></sub></code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_757" id="pnum_757">11</a></span>
<em>Returns</em>: <code class="sourceCode cpp">class_type</code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.traits-reflection-type-traits">[meta.reflection.traits]
Reflection type traits<a href="#meta.reflection.traits-reflection-type-traits" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_758" id="pnum_758">1</a></span>
Subclause [meta.reflection.traits] specifies consteval functions to
query the properties of types ([meta.unary]), query the relationships
between types ([meta.rel]), or transform types ([meta.trans]) at compile
time. Each consteval function declared in this class has an associated
class template declared elsewhere in this document.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_759" id="pnum_759">2</a></span>
Every function and function template declared in this subclause has the
following conditions required for a call to that function or function
template to be a constant subexpression ([defns.const.subexpr]):</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_760" id="pnum_760">(2.1)</a></span>
For every parameter <code class="sourceCode cpp">p</code> of type
<code class="sourceCode cpp">info</code>, <code class="sourceCode cpp">is_type<span class="op">(</span>p<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_761" id="pnum_761">(2.2)</a></span>
For every parameter <code class="sourceCode cpp">r</code> whose type is
constrained on <code class="sourceCode cpp">reflection_range</code>,
<code class="sourceCode cpp">ranges<span class="op">::</span>all_of<span class="op">(</span>r, is_type<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_762" id="pnum_762">3</a></span>
Unless otherwise specified, each function and function template
described in this subclause has the following behavior based on the
signature of that function or function template. <span class="note"><span>[ <em>Note 1:</em> </span>The associated class
template need not be instantiated.<span> — <em>end
note</em> ]</span></span></p>
<table>
<tr>
<th>
Signature
</th>
<th>
<em>Returns</em>
</th>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb284"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb284-1"><a href="#cb284-1" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>UNARY</em><span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb284-2"><a href="#cb284-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>UNARY</em>_type<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
<code class="sourceCode cpp">std<span class="op">::</span><em>UNARY</em>_v<span class="op">&lt;</span><em>T</em><span class="op">&gt;</span></code>,
where <code class="sourceCode cpp"><em>T</em></code> is the type or type
alias represented by <code class="sourceCode cpp">type</code>
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb285"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb285-1"><a href="#cb285-1" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>BINARY</em><span class="op">(</span>info t1, info t2<span class="op">)</span>;</span>
<span id="cb285-2"><a href="#cb285-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>BINARY</em>_type<span class="op">(</span>info t1, info t2<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
<code class="sourceCode cpp">std<span class="op">::</span><em>BINARY</em>_v<span class="op">&lt;</span><em>T1</em>, <em>T2</em><span class="op">&gt;</span></code>,
where <code class="sourceCode cpp"><em>T1</em></code> and
<code class="sourceCode cpp"><em>T2</em></code> are the types or type
aliases represented by <code class="sourceCode cpp">t1</code> and
<code class="sourceCode cpp">t2</code>, respectively
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb286"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb286-1"><a href="#cb286-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R<span class="op">&gt;</span></span>
<span id="cb286-2"><a href="#cb286-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>VARIADIC</em>_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
<code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC</em>_v<span class="op">&lt;</span><em>T</em>, <em>U</em><span class="op">...&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type or type
alias represented by <code class="sourceCode cpp">type</code> and
<code class="sourceCode cpp"><em>U</em><span class="op">...</span></code>
is the pack of types or type aliases whose elements are represented by
the corresponding elements of <code class="sourceCode cpp">args</code>
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb287"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb287-1"><a href="#cb287-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R<span class="op">&gt;</span></span>
<span id="cb287-2"><a href="#cb287-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> meta<span class="op">::</span><em>VARIADIC</em>_type<span class="op">(</span>info t1, info t2, R<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
<code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC</em>_v<span class="op">&lt;</span><em>T1</em>, <em>T2</em>, <em>U</em><span class="op">...&gt;</span></code>
where <code class="sourceCode cpp"><em>T1</em></code> and
<code class="sourceCode cpp"><em>T2</em></code> are the types or type
aliases represented by <code class="sourceCode cpp">t1</code> and
<code class="sourceCode cpp">t2</code>, respectively, and
<code class="sourceCode cpp"><em>U</em><span class="op">...</span></code>
is the pack of types or type aliases whose elements are represented by
the corresponding elements of <code class="sourceCode cpp">args</code>
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb288"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb288-1"><a href="#cb288-1" aria-hidden="true" tabindex="-1"></a>info meta<span class="op">::</span><em>UNARY</em><span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
A reflection representing the type denoted by <code class="sourceCode cpp">std<span class="op">::</span><em>UNARY</em>_t<span class="op">&lt;</span><em>T</em><span class="op">&gt;</span></code>,
where <code class="sourceCode cpp"><em>T</em></code> is the type or type
alias represented by <code class="sourceCode cpp">type</code>
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb289"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb289-1"><a href="#cb289-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R<span class="op">&gt;</span></span>
<span id="cb289-2"><a href="#cb289-2" aria-hidden="true" tabindex="-1"></a>info meta<span class="op">::</span><em>VARIADIC</em><span class="op">(</span>R<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
A reflection representing the type denoted by <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC</em>_t<span class="op">&lt;</span><em>T</em><span class="op">...&gt;</span></code>
where
<code class="sourceCode cpp"><em>T</em><span class="op">...</span></code>
is the pack of types or type aliases whose elements are represented by
the corresponding elements of <code class="sourceCode cpp">args</code>
</td>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb290"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb290-1"><a href="#cb290-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R<span class="op">&gt;</span></span>
<span id="cb290-2"><a href="#cb290-2" aria-hidden="true" tabindex="-1"></a>info meta<span class="op">::</span><em>VARIADIC</em><span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span></code></pre></div>
</td>
<td>
A reflection representing the type denoted by <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC</em>_t<span class="op">&lt;</span><em>T</em>, <em>U</em><span class="op">...&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type or type
alias represented by <code class="sourceCode cpp">type</code> and
<code class="sourceCode cpp"><em>U</em><span class="op">...</span></code>
is the pack of types or type aliases whose elements are represented by
the corresponding elements of <code class="sourceCode cpp">args</code>
</td>
</tr>
</table>
<p><span class="note"><span>[ <em>Note 2:</em> </span>For those
functions or function templates which return a reflection, that
reflection always represents a type and never a type alias.<span>
— <em>end note</em> ]</span></span></p>
<div class="sourceCode" id="cb291"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb291-1"><a href="#cb291-1" aria-hidden="true" tabindex="-1"></a>  <span class="co">// associated with [meta.unary.cat], primary type categories</span></span>
<span id="cb291-2"><a href="#cb291-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_void_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-3"><a href="#cb291-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_null_pointer_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-4"><a href="#cb291-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_integral_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-5"><a href="#cb291-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_floating_point_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-6"><a href="#cb291-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_array_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-7"><a href="#cb291-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_pointer_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-8"><a href="#cb291-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_lvalue_reference_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-9"><a href="#cb291-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_rvalue_reference_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-10"><a href="#cb291-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_member_object_pointer_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-11"><a href="#cb291-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_member_function_pointer_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-12"><a href="#cb291-12" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_enum_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-13"><a href="#cb291-13" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_union_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-14"><a href="#cb291-14" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_class_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-15"><a href="#cb291-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_function_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-16"><a href="#cb291-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_reflection_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-17"><a href="#cb291-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-18"><a href="#cb291-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// associated with [meta.unary.comp], composite type categories</span></span>
<span id="cb291-19"><a href="#cb291-19" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_reference_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-20"><a href="#cb291-20" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_arithmetic_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-21"><a href="#cb291-21" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_fundamental_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-22"><a href="#cb291-22" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_object_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-23"><a href="#cb291-23" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_scalar_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-24"><a href="#cb291-24" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_compound_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-25"><a href="#cb291-25" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_member_pointer_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-26"><a href="#cb291-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-27"><a href="#cb291-27" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.unary.prop], type properties</span></span>
<span id="cb291-28"><a href="#cb291-28" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_const_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-29"><a href="#cb291-29" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_volatile_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-30"><a href="#cb291-30" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_copyable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-31"><a href="#cb291-31" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_relocatable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-32"><a href="#cb291-32" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_replaceable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-33"><a href="#cb291-33" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_standard_layout_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-34"><a href="#cb291-34" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_empty_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-35"><a href="#cb291-35" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_polymorphic_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-36"><a href="#cb291-36" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_abstract_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-37"><a href="#cb291-37" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_final_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-38"><a href="#cb291-38" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_aggregate_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-39"><a href="#cb291-39" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_consteval_only_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-40"><a href="#cb291-40" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_signed_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-41"><a href="#cb291-41" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_unsigned_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-42"><a href="#cb291-42" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_bounded_array_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-43"><a href="#cb291-43" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_unbounded_array_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-44"><a href="#cb291-44" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_scoped_enum_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-45"><a href="#cb291-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-46"><a href="#cb291-46" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb291-47"><a href="#cb291-47" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_constructible_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb291-48"><a href="#cb291-48" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_default_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-49"><a href="#cb291-49" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_copy_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-50"><a href="#cb291-50" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_move_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-51"><a href="#cb291-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-52"><a href="#cb291-52" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_assignable_type<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-53"><a href="#cb291-53" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_copy_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-54"><a href="#cb291-54" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_move_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-55"><a href="#cb291-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-56"><a href="#cb291-56" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_swappable_with_type<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-57"><a href="#cb291-57" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_swappable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-58"><a href="#cb291-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-59"><a href="#cb291-59" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_destructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-60"><a href="#cb291-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-61"><a href="#cb291-61" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb291-62"><a href="#cb291-62" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_constructible_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb291-63"><a href="#cb291-63" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_default_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-64"><a href="#cb291-64" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_copy_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-65"><a href="#cb291-65" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_move_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-66"><a href="#cb291-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-67"><a href="#cb291-67" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_assignable_type<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-68"><a href="#cb291-68" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_copy_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-69"><a href="#cb291-69" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_move_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-70"><a href="#cb291-70" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_trivially_destructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-71"><a href="#cb291-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-72"><a href="#cb291-72" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb291-73"><a href="#cb291-73" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_constructible_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb291-74"><a href="#cb291-74" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_default_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-75"><a href="#cb291-75" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_copy_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-76"><a href="#cb291-76" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_move_constructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-77"><a href="#cb291-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-78"><a href="#cb291-78" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_assignable_type<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-79"><a href="#cb291-79" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_copy_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-80"><a href="#cb291-80" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_move_assignable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-81"><a href="#cb291-81" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-82"><a href="#cb291-82" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_swappable_with_type<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-83"><a href="#cb291-83" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_swappable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-84"><a href="#cb291-84" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-85"><a href="#cb291-85" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_destructible_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-86"><a href="#cb291-86" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_relocatable_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-87"><a href="#cb291-87" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-88"><a href="#cb291-88" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_implicit_lifetime_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-89"><a href="#cb291-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-90"><a href="#cb291-90" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_virtual_destructor<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-91"><a href="#cb291-91" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-92"><a href="#cb291-92" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_unique_object_representations<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb291-93"><a href="#cb291-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb291-94"><a href="#cb291-94" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> reference_constructs_from_temporary<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb291-95"><a href="#cb291-95" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> reference_converts_from_temporary<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb292"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb292-1"><a href="#cb292-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> rank<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_763" id="pnum_763">4</a></span>
<em>Returns</em>: <code class="sourceCode cpp">rank_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
where <code class="sourceCode cpp">T</code> is the type represented by
<code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>.</p>
<div class="sourceCode" id="cb293"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb293-1"><a href="#cb293-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> extent<span class="op">(</span>info type, <span class="dt">unsigned</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_764" id="pnum_764">5</a></span>
<em>Returns</em>: <code class="sourceCode cpp">extent_v<span class="op">&lt;</span>T, I<span class="op">&gt;</span></code>,
where <code class="sourceCode cpp">T</code> is the type represented by
<code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
and <code class="sourceCode cpp">I</code> is a constant equal to
<code class="sourceCode cpp">i</code>.</p>
<div class="sourceCode" id="cb294"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb294-1"><a href="#cb294-1" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.rel], type relations</span></span>
<span id="cb294-2"><a href="#cb294-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_same_type<span class="op">(</span>info type1, info type2<span class="op">)</span>;</span>
<span id="cb294-3"><a href="#cb294-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_base_of_type<span class="op">(</span>info type_base, info type_derived<span class="op">)</span>;</span>
<span id="cb294-4"><a href="#cb294-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_virtual_base_of_type<span class="op">(</span>info type_base, info type_derived<span class="op">)</span>;</span>
<span id="cb294-5"><a href="#cb294-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_convertible_type<span class="op">(</span>info type_src, info type_dst<span class="op">)</span>;</span>
<span id="cb294-6"><a href="#cb294-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_convertible_type<span class="op">(</span>info type_src, info type_dst<span class="op">)</span>;</span>
<span id="cb294-7"><a href="#cb294-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_layout_compatible_type<span class="op">(</span>info type1, info type2<span class="op">)</span>;</span>
<span id="cb294-8"><a href="#cb294-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_pointer_interconvertible_base_of_type<span class="op">(</span>info type_base, info type_derived<span class="op">)</span>;</span>
<span id="cb294-9"><a href="#cb294-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb294-10"><a href="#cb294-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb294-11"><a href="#cb294-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_invocable_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb294-12"><a href="#cb294-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb294-13"><a href="#cb294-13" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_invocable_r_type<span class="op">(</span>info type_result, info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb294-14"><a href="#cb294-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb294-15"><a href="#cb294-15" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb294-16"><a href="#cb294-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_invocable_type<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb294-17"><a href="#cb294-17" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb294-18"><a href="#cb294-18" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_nothrow_invocable_r_type<span class="op">(</span>info type_result, info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_765" id="pnum_765">6</a></span>
<span class="note"><span>[ <em>Note 3:</em> </span>If
<code class="sourceCode cpp">t</code> is a reflection of the type
<code class="sourceCode cpp"><span class="dt">int</span></code> and
<code class="sourceCode cpp">u</code> is a reflection of an alias to the
type <code class="sourceCode cpp"><span class="dt">int</span></code>,
then <code class="sourceCode cpp">t <span class="op">==</span> u</code>
is <code class="sourceCode cpp"><span class="kw">false</span></code> but
<code class="sourceCode cpp">is_same_type<span class="op">(</span>t, u<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Also, <code class="sourceCode cpp">t <span class="op">==</span> dealias<span class="op">(</span>u<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>.<span>
— <em>end note</em> ]</span></span>.</p>
<div class="sourceCode" id="cb295"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb295-1"><a href="#cb295-1" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.cv], const-volatile modifications</span></span>
<span id="cb295-2"><a href="#cb295-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_const<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-3"><a href="#cb295-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_volatile<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-4"><a href="#cb295-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_cv<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-5"><a href="#cb295-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_const<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-6"><a href="#cb295-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_volatile<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-7"><a href="#cb295-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_cv<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-8"><a href="#cb295-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb295-9"><a href="#cb295-9" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.ref], reference modifications</span></span>
<span id="cb295-10"><a href="#cb295-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-11"><a href="#cb295-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_lvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-12"><a href="#cb295-12" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_rvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-13"><a href="#cb295-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb295-14"><a href="#cb295-14" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.sign], sign modifications</span></span>
<span id="cb295-15"><a href="#cb295-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info make_signed<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-16"><a href="#cb295-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info make_unsigned<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-17"><a href="#cb295-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb295-18"><a href="#cb295-18" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.arr], array modifications</span></span>
<span id="cb295-19"><a href="#cb295-19" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_extent<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-20"><a href="#cb295-20" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_all_extents<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-21"><a href="#cb295-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb295-22"><a href="#cb295-22" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.ptr], pointer modifications</span></span>
<span id="cb295-23"><a href="#cb295-23" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb295-24"><a href="#cb295-24" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info add_pointer<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: There
are four transformations that are deliberately omitted here.
<code class="sourceCode default">type_identity</code> and
<code class="sourceCode default">enable_if</code> are not useful,
<code class="sourceCode default">conditional(cond, t, f)</code> would
just be a long way of writing
<code class="sourceCode default">cond ? t : f</code>, and
<code class="sourceCode default">basic_common_reference</code> is a
class template intended to be specialized and not directly invoked.
]</span></p>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb296"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb296-1"><a href="#cb296-1" aria-hidden="true" tabindex="-1"></a><span class="co">// associated with [meta.trans.other], other transformations</span></span>
<span id="cb296-2"><a href="#cb296-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info remove_cvref<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb296-3"><a href="#cb296-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info decay<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb296-4"><a href="#cb296-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb296-5"><a href="#cb296-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info common_type<span class="op">(</span>R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb296-6"><a href="#cb296-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb296-7"><a href="#cb296-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info common_reference<span class="op">(</span>R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb296-8"><a href="#cb296-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info underlying_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb296-9"><a href="#cb296-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb296-10"><a href="#cb296-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info invoke_result<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb296-11"><a href="#cb296-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info unwrap_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb296-12"><a href="#cb296-12" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info unwrap_ref_decay<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
below inclusion of
<code class="sourceCode default">meta::type_order</code> assumes the
acceptance of <span class="citation" data-cites="P2830R10"><a href="https://wg21.link/p2830r10" role="doc-biblioref">[P2830R10]</a></span>. ]</span></p>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb297"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb297-1"><a href="#cb297-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> tuple_size<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_766" id="pnum_766">7</a></span>
<em>Returns</em>: <code class="sourceCode cpp">tuple_size_v<span class="op">&lt;</span><em>T</em><span class="op">&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>.</p>
<div class="sourceCode" id="cb298"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb298-1"><a href="#cb298-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info tuple_element<span class="op">(</span><span class="dt">size_t</span> index, info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_767" id="pnum_767">8</a></span>
<em>Returns</em>: A reflection representing the type denoted by <code class="sourceCode cpp">tuple_element_t<span class="op">&lt;</span><em>I</em>, <em>T</em><span class="op">&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
and <code class="sourceCode cpp"><em>I</em></code> is a constant equal
to <code class="sourceCode cpp">index</code>.</p>
<div class="sourceCode" id="cb299"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb299-1"><a href="#cb299-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">size_t</span> variant_size<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_768" id="pnum_768">9</a></span>
<em>Returns</em>: <code class="sourceCode cpp">variant_size_v<span class="op">&lt;</span><em>T</em><span class="op">&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>.</p>
<div class="sourceCode" id="cb300"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb300-1"><a href="#cb300-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info variant_alternative<span class="op">(</span><span class="dt">size_t</span> index, info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_769" id="pnum_769">10</a></span>
<em>Returns</em>: A reflection representing the type denoted by <code class="sourceCode cpp">variant_alterantive_t<span class="op">&lt;</span><em>I</em>, <em>T</em><span class="op">&gt;</span></code>
where <code class="sourceCode cpp"><em>T</em></code> is the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
and <code class="sourceCode cpp"><em>I</em></code> is a constant equal
to <code class="sourceCode cpp">index</code>.</p>
<div class="sourceCode" id="cb301"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb301-1"><a href="#cb301-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> strong_ordering type_order<span class="op">(</span>info t1, info t2<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_770" id="pnum_770">11</a></span>
<em>Returns</em>: <code class="sourceCode cpp">type_order_v<span class="op">&lt;</span><em>T1</em>, <em>T2</em><span class="op">&gt;</span></code>,
where <code class="sourceCode cpp"><em>T1</em></code> and
<code class="sourceCode cpp"><em>T2</em></code> are the types
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>t1<span class="op">)</span></code>
and <code class="sourceCode cpp">dealias<span class="op">(</span>t2<span class="op">)</span></code>,
respectively.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="bit.cast-function-template-bit_cast"><span>22.11.3 <a href="https://wg21.link/bit.cast">[bit.cast]</a></span> Function
template <code class="sourceCode cpp">bit_cast</code><a href="#bit.cast-function-template-bit_cast" class="self-link"></a></h3>
<p>And we have adjust the requirements of
<code class="sourceCode cpp">bit_cast</code> to not allow casting to or
from
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>,
in <span>22.11.3 <a href="https://wg21.link/bit.cast">[bit.cast]</a></span>/3, which we add
as a mandates (and then <em>Constant When</em> has to be before
<em>Returns</em>, but the <em>Returns</em> remains unchanged):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb302"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb302-1"><a href="#cb302-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> To, <span class="kw">class</span> From<span class="op">&gt;</span></span>
<span id="cb302-2"><a href="#cb302-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> To bit_cast<span class="op">(</span><span class="kw">const</span> From<span class="op">&amp;</span> from<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_771" id="pnum_771">1</a></span>
<em>Constraints</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_772" id="pnum_772">(1.1)</a></span>
<code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span>To<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">(</span>From<span class="op">)</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_773" id="pnum_773">(1.2)</a></span>
<code class="sourceCode cpp">is_trivially_copyable_v<span class="op">&lt;</span>To<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>;
and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_774" id="pnum_774">(1.3)</a></span>
<code class="sourceCode cpp">is_trivially_copyable_v<span class="op">&lt;</span>From<span class="op">&gt;</span></code>
is
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
</ul>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_775" id="pnum_775">*</a></span>
<em>Mandates</em>: Neither <code class="sourceCode cpp">To</code> nor
<code class="sourceCode cpp">From</code> are consteval-only types
([expr.const]).</p>
</div>
<div class="rm" style="color: #bf0303">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_776" id="pnum_776">2</a></span>
<em>Returns</em>: […]</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_777" id="pnum_777">3</a></span>
<span class="rm" style="color: #bf0303"><del><em>Remarks</em></del></span> <span class="addu"><em>Constant When</em></span>: <span class="rm" style="color: #bf0303"><del>This function is constexpr if and only
if</del></span> <code class="sourceCode cpp">To</code>,
<code class="sourceCode cpp">From</code>, and the types of all
subobjects of <code class="sourceCode cpp">To</code> and
<code class="sourceCode cpp">From</code> are types
<code class="sourceCode cpp">T</code> such that:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_778" id="pnum_778">(3.1)</a></span>
<code class="sourceCode cpp">is_union_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is
<code class="sourceCode cpp"><span class="kw">false</span></code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_779" id="pnum_779">(3.2)</a></span>
<code class="sourceCode cpp">is_pointer_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is
<code class="sourceCode cpp"><span class="kw">false</span></code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_780" id="pnum_780">(3.3)</a></span>
<code class="sourceCode cpp">is_member_pointer_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is
<code class="sourceCode cpp"><span class="kw">false</span></code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_781" id="pnum_781">(3.4)</a></span>
<code class="sourceCode cpp">is_volatile_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>;
and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_782" id="pnum_782">(3.5)</a></span>
<code class="sourceCode cpp">T</code> has no non-static data members of
reference type.</li>
</ul>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_783" id="pnum_783">4</a></span>
<em>Returns</em>: […]</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="diff.cpp23-annex-c-informative-compatibility"><span>C.1 <a href="https://wg21.link/diff.cpp23">[diff.cpp23]</a></span> Annex
C (informative) Compatibility<a href="#diff.cpp23-annex-c-informative-compatibility" class="self-link"></a></h3>
<p>Add a new Annex C entry:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Affected subclause</strong>: [lex.operators]</p>
<p><strong>Change</strong>: New operator
<code class="sourceCode cpp"><span class="op">^^</span></code>.</p>
<p><strong>Rationale</strong>: Required for new features.</p>
<p><strong>Effect on original feature</strong>: Valid C++23 code that
contains two consecutive
<code class="sourceCode cpp"><span class="op">^</span></code> tokens may
be ill-formed in this revision of C++.</p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb303"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb303-1"><a href="#cb303-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span> <span class="dt">int</span> <span class="kw">operator</span><span class="op">^(</span><span class="dt">int</span><span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb303-2"><a href="#cb303-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> <span class="kw">operator</span><span class="op">^(</span><span class="dt">int</span> <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span><span class="dt">int</span><span class="op">)</span>, C<span class="op">)</span>;</span>
<span id="cb303-3"><a href="#cb303-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i <span class="op">=</span> <span class="op">&amp;</span>C<span class="op">::</span><span class="kw">operator</span><span class="op">^^</span>C<span class="op">{}</span>; <span class="co">// ill-formed; previously well-formed</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<p>Modify [diff.cpp23.library]:</p>
<div class="std">
<blockquote>
<p><strong>Affected subclause</strong>: [headers]</p>
<p><strong>Change</strong>: New headers.</p>
<p><strong>Rationale</strong>: New functionality.</p>
<p><strong>Effect on original feature</strong>: The folowing C++ headers
are new: <code class="sourceCode cpp"><span class="op">&lt;</span>debugging<span class="op">&gt;</span></code>,
<code class="sourceCode cpp"><span class="op">&lt;</span>hazard_pointer<span class="op">&gt;</span></code>,
<code class="sourceCode cpp"><span class="op">&lt;</span>inplace_vector<span class="op">&gt;</span></code>,
<code class="sourceCode cpp"><span class="op">&lt;</span>linalg<span class="op">&gt;</span></code>,
<span class="addu"><code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>,</span>
<code class="sourceCode cpp"><span class="op">&lt;</span>rcu<span class="op">&gt;</span></code>,
<code class="sourceCode cpp"><span class="op">&lt;</span>simd<span class="op">&gt;</span></code>,
and <code class="sourceCode cpp"><span class="op">&lt;</span>text_encoding<span class="op">&gt;</span></code>.
Valid C++ 2023 code that
<code class="sourceCode cpp"><span class="pp">#include</span></code>s
headers with these names may be invalid in this revision of C++.</p>
</blockquote>
</div>
<h2 data-number="5.3" id="feature-test-macro"><span class="header-section-number">5.3</span> Feature-Test Macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>This is a feature with both a language and library component. Our
usual practice is to provide something like
<code class="sourceCode cpp">__cpp_impl_reflection</code> and
<code class="sourceCode cpp">__cpp_lib_reflection</code> for this. But
since the two pieces are so closely tied together, maybe it really only
makes sense to provide one?</p>
<p>For now, we’ll add both.</p>
<p>To <span>15.12 <a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb304"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb304-1"><a href="#cb304-1" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_coroutine 201902L</span>
<span id="cb304-2"><a href="#cb304-2" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_destroying_delete 201806L</span>
<span id="cb304-3"><a href="#cb304-3" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_three_way_comparison 201907L</span>
<span id="cb304-4"><a href="#cb304-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ __cpp_impl_reflection 2025XXL</span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>and <span>17.3.2 <a href="https://wg21.link/version.syn">[version.syn]</a></span>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb305"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb305-1"><a href="#cb305-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ #define __cpp_lib_reflection 2025XXL // also in &lt;meta&gt;</span></span></code></pre></div>
</div>
</blockquote>
</div>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="appendix-design-changes-approved-in-hagenberg"><span class="header-section-number">6</span> Appendix: Design changes approved
in Hagenberg<a href="#appendix-design-changes-approved-in-hagenberg" class="self-link"></a></h1>
<p><span class="citation" data-cites="P2996R4"><a href="https://wg21.link/p2996r4" role="doc-biblioref">[P2996R4]</a></span> was forwarded to CWG in
St. Louis (June 2024). In the time after, some minor design changes were
shown to be necessary. The following changes were confirmed by EWG
during the Hagenberg 2025 meeting.</p>
<p>One small change was needed to the reflection operator.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_784" id="pnum_784">1</a></span>
Application of the
<code class="sourceCode cpp"><span class="op">^^</span></code> operator
to a non-type template parameter
<ul>
<li><strong>P2996R4</strong>: Applying
<code class="sourceCode cpp"><span class="op">^^</span></code> to a
non-type template parameter, or to a
<code class="sourceCode cpp"><em>pack-index-expression</em></code>, gave
a reflection of the value or object computed or designated by the
operand ([expr.reflect]/10).</li>
<li><strong>D2996R10</strong>: Applying
<code class="sourceCode cpp"><span class="op">^^</span></code> to such
expressions is ill-formed ([expr.reflect]/6.4).</li>
<li><strong>Rationale</strong>: The operand following the
<code class="sourceCode cpp"><span class="op">^^</span></code> of a
<code class="sourceCode cpp"><em>reflect-expression</em></code> is an
unevaluated operand ([expr.context/1], [expr.reflect]/6.4). Supporting
this necessarily requires that we evaluate said operand, which is at
odds with its specification. Introducing some sort of “conditionally
evaluated” operand machinery would be novel and unnecessary.</li>
<li><strong>Instead</strong>: Just use <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_value</code>
or <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_object</code>,
as appropriate.</li>
</ul></li>
</ul>
<p>A few changes were needed to “consteval-only types” to ensure that
objects of such types cannot reach runtime.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_785" id="pnum_785">2</a></span>
Relaxed linkage restrictions on objects of consteval-only types
<ul>
<li><strong>P2996R4</strong>: Rigid rules prevented objects of
consteval-only type from having module or external linkage
([basic.link]/4.9, [basic.types.general]).
<ul>
<li>Included static data members, etc. Quite strict.</li>
</ul></li>
<li><strong>D2996R10</strong>: All such restrictions have been
removed.</li>
<li><strong>Rationale</strong>: Implementation experience at the
intersection of modules and reflection proved that reflections can be
imported across TUs and modules without issue.
<ul>
<li>Try it with <a href="https://godbolt.org/z/Y8cdd9sGo">Clang</a>.</li>
</ul></li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_786" id="pnum_786">3</a></span>
Immediate-escalation of expressions of consteval-only type
<ul>
<li><strong>D2996R10</strong>: Every expression of consteval-only type
is <em>immediate-escalating</em> ([expr.const]/25).</li>
<li><strong>Rationale</strong>: Prevent any need for <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
to persist to runtime (e.g., passing a reference to a <code class="sourceCode cpp"><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info</code>
to a runtime function).</li>
<li>Fully implemented; try it with Clang <a href="https://godbolt.org/z/5sfe7vdzE">here</a> and <a href="https://godbolt.org/z/T3MY1Yqo4">here</a>.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_787" id="pnum_787">4</a></span>
Immediate-escalation of non-constexpr variables of consteval-only type
<ul>
<li><strong>D2996R10</strong>: Immediate-escalating functions containing
non-constexpr variables of consteval-only type are immediate functions
([expr.const]/27.2.2).</li>
<li><strong>Rationale</strong>: Prevents default-constructed variables
of consteval-only type (for which an expression does not necessarily
appear) from reaching runtime.</li>
<li>Fully implemented; try it with <a href="https://godbolt.org/z/3asrnK13G">Clang</a>.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_788" id="pnum_788">5</a></span>
No “erasure” of consteval-only-ness from results of constant
expressions.
<ul>
<li><strong>D2996R10</strong>: Pointer or reference results of constant
expressions must have consteval-only type whenever the object that they
point or reference into does.
<ul>
<li>e.g., A <code class="sourceCode cpp"><span class="dt">void</span> <span class="op">*</span></code>
pointer to a <code class="sourceCode cpp"><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info</code>
cannot be a result of a constant expression.</li>
</ul></li>
<li>Fully implemented; try it with <a href="https://godbolt.org/z/n47ona1db">Clang</a>.</li>
<li>Still fine to type erase <em>within</em> a constant expression (as
seen <a href="https://godbolt.org/z/E4faezfr3">here</a>).</li>
</ul></li>
</ul>
<p>Two changes were needed for splicers.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_789" id="pnum_789">6</a></span>
A slight syntactic change is needed for template splicers.
<ul>
<li><strong>P2994R4</strong>:
<code class="sourceCode cpp"><em>splice-template-name</em></code>
handled template splicers.
<ul>
<li>Not the best distinction between “names” and “entities” (naturally,
CWG set us straight ❤️).</li>
<li>Wasn’t entirely clear how some cases (e.g., CTAD, placeholder types)
were supposed to work.</li>
</ul></li>
<li><strong>D2996R10</strong>: Type template splicers are folded into
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
([dcl.type.splice]). Simple rule:
<ul>
<li>Splicing a template as a type is spelled <code class="sourceCode cpp"><span class="kw">typename</span> <span class="op">[:</span>R<span class="op">:]</span></code>.</li>
<li>Splicing a template as an expression is spelled <code class="sourceCode cpp"><span class="kw">template</span> <span class="op">[:</span>R<span class="op">:]</span></code>.</li>
</ul></li>
<li>Try it on godbolt with <a href="https://godbolt.org/z/GKj5of839">Clang</a>.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_790" id="pnum_790">7</a></span>
Reflections of concepts cannot be spliced.
<ul>
<li><strong>P2996R4</strong>: Concepts could be spliced within both
<code class="sourceCode cpp"><em>type-constraint</em></code>s and
<code class="sourceCode cpp"><em>concept-id</em></code>s.</li>
<li><strong>D2996R10</strong>: Splicing a concept is ill-formed.</li>
<li><strong>Rationale</strong>: <span class="citation" data-cites="P2841R5"><a href="https://wg21.link/p2841r5" role="doc-biblioref">[P2841R5]</a></span> has already done the work to
figure out dependent concepts. CWG requested that we wait for that to
land first, and revisit concept splicers in a future paper.</li>
<li><strong>Instead</strong>: For the case of a
<code class="sourceCode cpp"><em>concept-id</em></code>,
<code class="sourceCode cpp">substitute</code> can still check whether a
concept is satisfied by a template argument list.</li>
</ul></li>
</ul>
<p>Our framework for code injection as performed by
<code class="sourceCode cpp">define_aggregate</code> evolved quite a bit
after P2996R4. When the evaluation of an expression calls
<code class="sourceCode cpp">define_aggregate</code>, we say that the
evaluation produces an <em>injected declaration</em> of the completed
type (try it on <a href="https://godbolt.org/z/PTeb9qqcW">godbolt</a>).</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_791" id="pnum_791">1</a></span>
Recent revisions lock down the context from which
<code class="sourceCode cpp">define_aggregate</code> can be called.
<ul>
<li><strong>P2996R4</strong>:
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
variable initializers, immediate invocations,
<code class="sourceCode cpp"><em>constant-expression</em></code>s, <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">constexpr</span></code>
conditions ([expr.const]/21).</li>
<li><strong>D2996R10</strong>: Only from
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
blocks ([dcl.pre]). No other expressions that would evaluate
<code class="sourceCode cpp">define_aggregate</code> can qualify as core
constant expressions ([expr.const/10.27+]).</li>
<li><strong>Rationale</strong>: Other constructs have proven unsuitable
for code injection due to e.g., template instantiation behavior,
immediate-escalating expression behavior, etc.</li>
<li>Fully implemented with Clang.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_792" id="pnum_792">2</a></span>
The scope that a given expression can inject a declaration <em>into</em>
has been constrained.
<ul>
<li><strong>P2996R4</strong>: The wild west: No restrictions.</li>
<li><strong>D2996R10</strong>: No intervening function or class scope is
allowed between the
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
block and the target scope of the injected declaration
([expr.const]/29).</li>
<li><strong>Rationale</strong>: Prevents the program from being able to
use <code class="sourceCode cpp">define_aggregate</code> to observe
failed substitutions, overload resolution order, etc.</li>
<li>Fully implemented in Clang.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_793" id="pnum_793">3</a></span>
Strengthening order of evaluation for core constant expressions removes
the need for more IFNDR.
<ul>
<li><strong>D2996R10</strong>: During the evaluation of an expression as
a core constant expresison, suboperands and subexpressions that are
otherwise unsequenced or indeterminately sequenced are evaluated in
lexical order.
<ul>
<li>All four major implementations already conform to this rule, and
representatives of each have expressed that they have no concerns.</li>
</ul></li>
</ul></li>
</ul>
<h1 data-number="7" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">7</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-CWG2701" class="csl-entry" role="doc-biblioentry">
[CWG2701] Richard Smith. 2020-11-20. Default arguments in multiple
scopes / inheritance of array bounds in the same scope. <a href="https://wg21.link/cwg2701"><div class="csl-block">https://wg21.link/cwg2701</div></a>
</div>
<div id="ref-N3980" class="csl-entry" role="doc-biblioentry">
[N3980] H. Hinnant, V. Falco, J. Byteway. 2014-05-24. Types don’t know
#. <a href="https://wg21.link/n3980"><div class="csl-block">https://wg21.link/n3980</div></a>
</div>
<div id="ref-P0784R7" class="csl-entry" role="doc-biblioentry">
[P0784R7] Daveed Vandevoorde, Peter Dimov,Louis Dionne, Nina Ranns,
Richard Smith, Daveed Vandevoorde. 2019-07-22. More constexpr
containers. <a href="https://wg21.link/p0784r7"><div class="csl-block">https://wg21.link/p0784r7</div></a>
</div>
<div id="ref-P1061R10" class="csl-entry" role="doc-biblioentry">
[P1061R10] Barry Revzin, Jonathan Wakely. 2024-11-24. Structured
Bindings can introduce a Pack. <a href="https://wg21.link/p1061r10"><div class="csl-block">https://wg21.link/p1061r10</div></a>
</div>
<div id="ref-P1240R0" class="csl-entry" role="doc-biblioentry">
[P1240R0] Andrew Sutton, Faisal Vali, Daveed Vandevoorde. 2018-10-08.
Scalable Reflection in C++. <a href="https://wg21.link/p1240r0"><div class="csl-block">https://wg21.link/p1240r0</div></a>
</div>
<div id="ref-P1240R2" class="csl-entry" role="doc-biblioentry">
[P1240R2] Daveed Vandevoorde, Wyatt Childers, Andrew Sutton, Faisal
Vali. 2022-01-14. Scalable Reflection. <a href="https://wg21.link/p1240r2"><div class="csl-block">https://wg21.link/p1240r2</div></a>
</div>
<div id="ref-P1306R2" class="csl-entry" role="doc-biblioentry">
[P1306R2] Dan Katz, Andrew Sutton, Sam Goodrick, Daveed Vandevoorde.
2024-05-07. Expansion statements. <a href="https://wg21.link/p1306r2"><div class="csl-block">https://wg21.link/p1306r2</div></a>
</div>
<div id="ref-P1887R1" class="csl-entry" role="doc-biblioentry">
[P1887R1] Corentin Jabot. 2020-01-13. Reflection on attributes. <a href="https://wg21.link/p1887r1"><div class="csl-block">https://wg21.link/p1887r1</div></a>
</div>
<div id="ref-P1974R0" class="csl-entry" role="doc-biblioentry">
[P1974R0] Jeff Snyder, Louis Dionne, Daveed Vandevoorde. 2020-05-15.
Non-transient constexpr allocation using propconst. <a href="https://wg21.link/p1974r0"><div class="csl-block">https://wg21.link/p1974r0</div></a>
</div>
<div id="ref-P2237R0" class="csl-entry" role="doc-biblioentry">
[P2237R0] Andrew Sutton. 2020-10-15. Metaprogramming. <a href="https://wg21.link/p2237r0"><div class="csl-block">https://wg21.link/p2237r0</div></a>
</div>
<div id="ref-P2564R3" class="csl-entry" role="doc-biblioentry">
[P2564R3] Barry Revzin. 2022-11-11. consteval needs to propagate up. <a href="https://wg21.link/p2564r3"><div class="csl-block">https://wg21.link/p2564r3</div></a>
</div>
<div id="ref-P2670R1" class="csl-entry" role="doc-biblioentry">
[P2670R1] Barry Revzin. 2023-02-03. Non-transient constexpr allocation.
<a href="https://wg21.link/p2670r1"><div class="csl-block">https://wg21.link/p2670r1</div></a>
</div>
<div id="ref-P2686R5" class="csl-entry" role="doc-biblioentry">
[P2686R5] Corentin Jabot, Brian Bi. 2024-11-12. constexpr structured
bindings and references to constexpr variables. <a href="https://wg21.link/p2686r5"><div class="csl-block">https://wg21.link/p2686r5</div></a>
</div>
<div id="ref-P2758R4" class="csl-entry" role="doc-biblioentry">
[P2758R4] Barry Revzin. 2025-01-07. Emitting messages at compile time.
<a href="https://wg21.link/p2758r4"><div class="csl-block">https://wg21.link/p2758r4</div></a>
</div>
<div id="ref-P2786R13" class="csl-entry" role="doc-biblioentry">
[P2786R13] Alisdair Meredith, Mungo Gill, Joshua Berne, Corentin Jabot,
Pablo Halpern, and Lori Hughes. 2025-02-14. Trivial Relocatability For
C++26. <a href="https://wg21.link/p2786r13"><div class="csl-block">https://wg21.link/p2786r13</div></a>
</div>
<div id="ref-P2830R10" class="csl-entry" role="doc-biblioentry">
[P2830R10] Gašper Ažman, Nathan Nichols. 2025-03-15. Standardized
Constexpr Type Ordering. <a href="https://wg21.link/p2830r10"><div class="csl-block">https://wg21.link/p2830r10</div></a>
</div>
<div id="ref-P2841R5" class="csl-entry" role="doc-biblioentry">
[P2841R5] Corentin Jabot, Gašper Ažman, James Touton. 2024-10-16.
Concept and variable-template template-parameters. <a href="https://wg21.link/p2841r5"><div class="csl-block">https://wg21.link/p2841r5</div></a>
</div>
<div id="ref-P2996R0" class="csl-entry" role="doc-biblioentry">
[P2996R0] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde. 2023-10-15. Reflection for C++26. <a href="https://wg21.link/p2996r0"><div class="csl-block">https://wg21.link/p2996r0</div></a>
</div>
<div id="ref-P2996R1" class="csl-entry" role="doc-biblioentry">
[P2996R1] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde. 2023-12-18. Reflection for C++26. <a href="https://wg21.link/p2996r1"><div class="csl-block">https://wg21.link/p2996r1</div></a>
</div>
<div id="ref-P2996R10" class="csl-entry" role="doc-biblioentry">
[P2996R10] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2025-02-27. Reflection for
C++26. <a href="https://wg21.link/p2996r10"><div class="csl-block">https://wg21.link/p2996r10</div></a>
</div>
<div id="ref-P2996R11" class="csl-entry" role="doc-biblioentry">
[P2996R11] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2025-04-16. Reflection for
C++26. <a href="https://wg21.link/p2996r11"><div class="csl-block">https://wg21.link/p2996r11</div></a>
</div>
<div id="ref-P2996R2" class="csl-entry" role="doc-biblioentry">
[P2996R2] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-02-15. Reflection for
C++26. <a href="https://wg21.link/p2996r2"><div class="csl-block">https://wg21.link/p2996r2</div></a>
</div>
<div id="ref-P2996R3" class="csl-entry" role="doc-biblioentry">
[P2996R3] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-05-22. Reflection for
C++26. <a href="https://wg21.link/p2996r3"><div class="csl-block">https://wg21.link/p2996r3</div></a>
</div>
<div id="ref-P2996R4" class="csl-entry" role="doc-biblioentry">
[P2996R4] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-06-26. Reflection for
C++26. <a href="https://wg21.link/p2996r4"><div class="csl-block">https://wg21.link/p2996r4</div></a>
</div>
<div id="ref-P2996R5" class="csl-entry" role="doc-biblioentry">
[P2996R5] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-08-14. Reflection for
C++26. <a href="https://wg21.link/p2996r5"><div class="csl-block">https://wg21.link/p2996r5</div></a>
</div>
<div id="ref-P2996R6" class="csl-entry" role="doc-biblioentry">
[P2996R6] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-10-10. Reflection for
C++26. <a href="https://wg21.link/p2996r6"><div class="csl-block">https://wg21.link/p2996r6</div></a>
</div>
<div id="ref-P2996R7" class="csl-entry" role="doc-biblioentry">
[P2996R7] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-10-13. Reflection for
C++26. <a href="https://wg21.link/p2996r7"><div class="csl-block">https://wg21.link/p2996r7</div></a>
</div>
<div id="ref-P2996R8" class="csl-entry" role="doc-biblioentry">
[P2996R8] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-12-17. Reflection for
C++26. <a href="https://wg21.link/p2996r8"><div class="csl-block">https://wg21.link/p2996r8</div></a>
</div>
<div id="ref-P2996R9" class="csl-entry" role="doc-biblioentry">
[P2996R9] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2025-01-13. Reflection for
C++26. <a href="https://wg21.link/p2996r9"><div class="csl-block">https://wg21.link/p2996r9</div></a>
</div>
<div id="ref-P3068R1" class="csl-entry" role="doc-biblioentry">
[P3068R1] Hana Dusíková. 2024-03-30. Allowing exception throwing in
constant-evaluation. <a href="https://wg21.link/p3068r1"><div class="csl-block">https://wg21.link/p3068r1</div></a>
</div>
<div id="ref-P3096R2" class="csl-entry" role="doc-biblioentry">
[P3096R2] Adam Lach, Walter Genovese. 2024-07-16. Function Parameter
Reflection in Reflection for C++26. <a href="https://wg21.link/p3096r2"><div class="csl-block">https://wg21.link/p3096r2</div></a>
</div>
<div id="ref-P3289R1" class="csl-entry" role="doc-biblioentry">
[P3289R1] Daveed Vandevoorde, Wyatt Childers, Dan Katz, Barry Revzin.
2025-01-13. Consteval blocks. <a href="https://wg21.link/p3289r1"><div class="csl-block">https://wg21.link/p3289r1</div></a>
</div>
<div id="ref-P3293R1" class="csl-entry" role="doc-biblioentry">
[P3293R1] Barry Revzin, Peter Dimov, Dan Katz, Daveed Vandevoorde.
2024-10-13. Splicing a base class subobject. <a href="https://wg21.link/p3293r1"><div class="csl-block">https://wg21.link/p3293r1</div></a>
</div>
<div id="ref-P3294R2" class="csl-entry" role="doc-biblioentry">
[P3294R2] Barry Revzin, Andrei Alexandrescu, Daveed Vandevoorde.
2024-10-15. Code Injection with Token Sequences. <a href="https://wg21.link/p3294r2"><div class="csl-block">https://wg21.link/p3294r2</div></a>
</div>
<div id="ref-P3295R0" class="csl-entry" role="doc-biblioentry">
[P3295R0] Ben Craig. 2024-05-21. Freestanding constexpr containers and
constexpr exception types. <a href="https://wg21.link/p3295r0"><div class="csl-block">https://wg21.link/p3295r0</div></a>
</div>
<div id="ref-P3381R0" class="csl-entry" role="doc-biblioentry">
[P3381R0] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-09-17. Syntax for
Reflection. <a href="https://wg21.link/p3381r0"><div class="csl-block">https://wg21.link/p3381r0</div></a>
</div>
<div id="ref-P3394R2" class="csl-entry" role="doc-biblioentry">
[P3394R2] Wyatt Childers, Dan Katz, Barry Revzin, and Daveed
Vandevoorde. 2025-03-10. Annotations for Reflection. <a href="https://wg21.link/p3394r2"><div class="csl-block">https://wg21.link/p3394r2</div></a>
</div>
<div id="ref-P3547R1" class="csl-entry" role="doc-biblioentry">
[P3547R1] Dan Katz, Ville Voutilainen. 2025-02-09. Modeling Access
Control With Reflection. <a href="https://wg21.link/p3547r1"><div class="csl-block">https://wg21.link/p3547r1</div></a>
</div>
<div id="ref-P3554R0" class="csl-entry" role="doc-biblioentry">
[P3554R0] Barry Revzin, Peter Dimov. 2025-01-06. Non-transient
allocation with vector and basic_string. <a href="https://wg21.link/p3554r0"><div class="csl-block">https://wg21.link/p3554r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
