<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-06-26" />
  <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;
}
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.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.std blockquote del { 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>P2996R4</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-06-26</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG, LEWG<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>
<li><a href="#emulating-typeful-reflection" id="toc-emulating-typeful-reflection"><span class="toc-section-number">3.18</span> Emulating typeful
reflection<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="#linkage-of-reflections-and-templates-specialized-by-reflections" id="toc-linkage-of-reflections-and-templates-specialized-by-reflections"><span class="toc-section-number">4.3.2</span> Linkage of reflections and
templates specialized by 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.3</span> The associated
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
namespace<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="#freestanding-implementations" id="toc-freestanding-implementations"><span class="toc-section-number">4.4.6</span> Freestanding
implementations<span></span></a></li>
<li><a href="#synopsis" id="toc-synopsis"><span class="toc-section-number">4.4.7</span> Synopsis<span></span></a></li>
<li><a href="#name-loc" id="toc-name-loc"><span class="toc-section-number">4.4.8</span>
<code class="sourceCode cpp">name_of</code>,
<code class="sourceCode cpp">display_name_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.9</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-value_of" id="toc-object_of-value_of"><span class="toc-section-number">4.4.10</span>
<code class="sourceCode cpp">object_of</code>,
<code class="sourceCode cpp">value_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.11</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.12</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>,
<code class="sourceCode cpp">subobjects_of</code><span></span></a></li>
<li><a href="#member-access" id="toc-member-access"><span class="toc-section-number">4.4.13</span> Member Access
Reflection<span></span></a></li>
<li><a href="#substitute" id="toc-substitute"><span class="toc-section-number">4.4.14</span>
<code class="sourceCode cpp">substitute</code><span></span></a></li>
<li><a href="#reflect_invoke" id="toc-reflect_invoke"><span class="toc-section-number">4.4.15</span>
<code class="sourceCode cpp">reflect_invoke</code><span></span></a></li>
<li><a href="#reflect-expression-results" id="toc-reflect-expression-results"><span class="toc-section-number">4.4.16</span>
<code class="sourceCode cpp">reflect_value</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.17</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="#test_trait" id="toc-test_trait"><span class="toc-section-number">4.4.18</span>
<code class="sourceCode cpp">test_trait</code><span></span></a></li>
<li><a href="#data_member_spec-define_class" id="toc-data_member_spec-define_class"><span class="toc-section-number">4.4.19</span>
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_class</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="#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.4
<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.12
<span>[lex.operators]</span></span> Operators and
punctuators<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.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.link-program-and-linkage" id="toc-basic.link-program-and-linkage">[basic.link] 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="#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.qual-qualified-names" id="toc-expr.prim.id.qual-qualified-names"><span>7.5.4.3
<span>[expr.prim.id.qual]</span></span> Qualified
names<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">[expr.ref] 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.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.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.splice-type-splicing" id="toc-dcl.type.splice-type-splicing">9.2.9* [dcl.type.splice] Type
splicing<span></span></a></li>
<li><a href="#dcl.init.general-initializers-general" id="toc-dcl.init.general-initializers-general"><span>9.4.1
<span>[dcl.init.general]</span></span> Initializers
(General)<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.def.delete-deleted-definitions" id="toc-dcl.fct.def.delete-deleted-definitions"><span>9.5.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.7.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.udir-using-namespace-directive" id="toc-namespace.udir-using-namespace-directive"><span>9.8.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.12.1
<span>[dcl.attr.grammar]</span></span> Attribute syntax and
semantics<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-template-non-type-arguments" id="toc-temp.arg.nontype-template-non-type-arguments"><span>13.4.3
<span>[temp.arg.nontype]</span></span> Template non-type
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.concept-concept-definitions" id="toc-temp.concept-concept-definitions"><span>13.7.9
<span>[temp.concept]</span></span> Concept
definitions<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>
</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="#namespace.std-namespace-std" id="toc-namespace.std-namespace-std"><span class="toc-section-number">5.2.1</span> <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 class="toc-section-number">5.2.2</span> <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 class="toc-section-number">5.2.3</span> <span>21.3.5.2
<span>[meta.unary.cat]</span></span> Primary type
categories<span></span></a></li>
<li><a href="#meta.synop-header-meta-synopsis" id="toc-meta.synop-header-meta-synopsis">[meta.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.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.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.member.access-reflection-member-access-queries" id="toc-meta.reflection.member.access-reflection-member-access-queries"><span class="toc-section-number">5.2.4</span> [meta.reflection.member.access],
Reflection member access 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_class-reflection-class-definition-generation" id="toc-meta.reflection.define_class-reflection-class-definition-generation">[meta.reflection.define_class]
Reflection class definition generation<span></span></a></li>
<li><a href="#meta.reflection.unary-unary-type-traits" id="toc-meta.reflection.unary-unary-type-traits">[meta.reflection.unary]
Unary type traits<span></span></a>
<ul>
<li><a href="#meta.reflection.unary.cat-primary-type-categories" id="toc-meta.reflection.unary.cat-primary-type-categories">[meta.reflection.unary.cat]
Primary type categories<span></span></a></li>
<li><a href="#meta.reflection.unary.comp-composite-type-categories" id="toc-meta.reflection.unary.comp-composite-type-categories">[meta.reflection.unary.comp]
Composite type categories<span></span></a></li>
<li><a href="#meta.reflection.unary.prop-type-properties" id="toc-meta.reflection.unary.prop-type-properties">[meta.reflection.unary.prop]
Type properties<span></span></a></li>
<li><a href="#meta.reflection.unary.prop.query-type-property-queries" id="toc-meta.reflection.unary.prop.query-type-property-queries">[meta.reflection.unary.prop.query]
Type property queries<span></span></a></li>
</ul></li>
<li><a href="#meta.reflection.rel-type-relations" id="toc-meta.reflection.rel-type-relations">[meta.reflection.rel], Type
relations<span></span></a></li>
<li><a href="#meta.reflection.trans-transformations-between-types" id="toc-meta.reflection.trans-transformations-between-types">[meta.reflection.trans],
Transformations between types<span></span></a>
<ul>
<li><a href="#meta.reflection.trans.cv-const-volatile-modifications" id="toc-meta.reflection.trans.cv-const-volatile-modifications">[meta.reflection.trans.cv],
Const-volatile modifications<span></span></a></li>
<li><a href="#meta.reflection.trans.ref-reference-modifications" id="toc-meta.reflection.trans.ref-reference-modifications">[meta.reflection.trans.ref],
Reference modifications<span></span></a></li>
<li><a href="#meta.reflection.trans.sign-sign-modifications" id="toc-meta.reflection.trans.sign-sign-modifications">[meta.reflection.trans.sign],
Sign modifications<span></span></a></li>
<li><a href="#meta.reflection.trans.arr-array-modifications" id="toc-meta.reflection.trans.arr-array-modifications">[meta.reflection.trans.arr],
Array modifications<span></span></a></li>
<li><a href="#meta.reflection.trans.ptr-pointer-modifications" id="toc-meta.reflection.trans.ptr-pointer-modifications">[meta.reflection.trans.ptr],
Pointer modifications<span></span></a></li>
<li><a href="#meta.reflection.trans.other-other-transformations" id="toc-meta.reflection.trans.other-other-transformations">[meta.reflection.trans.other],
Other transformations<span></span></a></li>
</ul></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="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</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="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
produces 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_value<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>name_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>name_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>expansion statements <span class="citation" data-cites="P1306R2">[<a href="https://wg21.link/p1306r2" role="doc-biblioref">P1306R2</a>]</span></li>
<li>non-transient constexpr allocation <span class="citation" data-cites="P0784R7">[<a href="https://wg21.link/p0784r7" role="doc-biblioref">P0784R7</a>]</span> <span class="citation" data-cites="P1974R0">[<a href="https://wg21.link/p1974r0" role="doc-biblioref">P1974R0</a>]</span> <span class="citation" data-cites="P2670R1">[<a href="https://wg21.link/p2670r1" role="doc-biblioref">P2670R1</a>]</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/13anqE1Pa">EDG</a>, <a href="https://godbolt.org/z/zn4vnjqzb">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/WEYae451z">EDG</a>, <a href="https://godbolt.org/z/dYGaMKEx5">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 denotes 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="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>nonstatic_data_members_of<span class="op">(^</span>S<span class="op">)[</span>n<span class="op">]</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8" 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-9"><a href="#cb7-9" 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-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">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-11"><a href="#cb7-11" 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/Wb1vx7jqb">EDG</a>, <a href="https://godbolt.org/z/TeGrhv7nz">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>name_of</code>,
which returns a <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>
describing the unqualified name of an entity denoted by a given
reflection value. 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="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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>name_of<span class="op">(</span>field<span class="op">)</span> <span class="op">==</span> name<span class="op">)</span> <span class="cf">return</span> field;</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-10"><a href="#cb8-10" 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-11"><a href="#cb8-11" 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-12"><a href="#cb8-12" 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-13"><a href="#cb8-13" 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/Yhh5hbcrn">EDG</a>, <a href="https://godbolt.org/z/vM46x4abW">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>views<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/4xz9Wsa8f">EDG</a>, <a href="https://godbolt.org/z/EPY93bTxv">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_value<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/bvPeqvaK5">EDG</a>, <a href="https://godbolt.org/z/ae3n8Phnn">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> members <span class="op">=</span> nonstatic_data_members_of<span class="op">(^</span>S<span class="op">)</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array<span class="op">&lt;</span>member_descriptor, members<span class="op">.</span>size<span class="op">()&gt;</span> layout;</span>
<span id="cb12-12"><a href="#cb12-12" 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-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>      layout<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> <span class="op">{.</span>offset<span class="op">=</span>offset_of<span class="op">(</span>members<span class="op">[</span>i<span class="op">])</span>, <span class="op">.</span>size<span class="op">=</span>size_of<span class="op">(</span>members<span class="op">[</span>i<span class="op">])}</span>;</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> layout;</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X</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="dt">char</span> a;</span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> b;</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">double</span> c;</span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-25"><a href="#cb12-25" 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-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a><span class="co">/*</span></span>
<span id="cb12-28"><a href="#cb12-28" 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-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a><span class="co">  { 0, 1 }, { 4, 4 }, { 8, 8 }</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a><span class="co">}}</span></span>
<span id="cb12-31"><a href="#cb12-31" 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/rbbWY99TM">EDG</a>, <a href="https://godbolt.org/z/YEn3ojjWq">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="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 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="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="cb13-5"><a href="#cb13-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="cb13-6"><a href="#cb13-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>name_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="op">}</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  <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="kw">enum</span> Color <span class="op">{</span> red, green, blue <span class="op">}</span>;</span>
<span id="cb13-14"><a href="#cb13-14" 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-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">42</span><span class="op">))</span> <span class="op">==</span> <span class="st">&quot;&lt;unnamed&gt;&quot;</span><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="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="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="cb14-5"><a href="#cb14-5" 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>name_of<span class="op">(</span>e<span class="op">))</span> <span class="op">{</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <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="op">}</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <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>name_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/Y5va8MqzG">EDG</a>, <a href="https://godbolt.org/z/3doherKx8">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 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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" 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-6"><a href="#cb16-6" 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-7"><a href="#cb16-7" 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> name_of<span class="op">(</span>dm<span class="op">)</span>;</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">})</span>;</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-10"><a href="#cb16-10" 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-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>      <span class="co">// no option provided, use default</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">continue</span>;</span>
<span id="cb16-13"><a href="#cb16-13" 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-14"><a href="#cb16-14" 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-15"><a href="#cb16-15" 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-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-18"><a href="#cb16-18" 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-19"><a href="#cb16-19" 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-20"><a href="#cb16-20" 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-21"><a href="#cb16-21" 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_name_of<span class="op">(^</span>T<span class="op">))</span>;</span>
<span id="cb16-22"><a href="#cb16-22" 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-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> opts;</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>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> MyOpts <span class="op">{</span></span>
<span id="cb16-29"><a href="#cb16-29" 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-30"><a href="#cb16-30" 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-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-33"><a href="#cb16-33" 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-34"><a href="#cb16-34" 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-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb16-36"><a href="#cb16-36" 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/G4dh3jq8a">EDG</a>, <a href="https://godbolt.org/z/v1PvGnafx">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>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>define_class<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>  storage data;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>  Tuple<span class="op">():</span> data<span class="op">{}</span> <span class="op">{}</span></span>
<span id="cb17-10"><a href="#cb17-10" 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-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-13"><a href="#cb17-13" 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-14"><a href="#cb17-14" 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-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-16"><a href="#cb17-16" 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-17"><a href="#cb17-17" 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-18"><a href="#cb17-18" 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-19"><a href="#cb17-19" 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-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-22"><a href="#cb17-22" 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-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> nonstatic_data_members_of<span class="op">(</span>r<span class="op">)[</span>n<span class="op">]</span>;</span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-26"><a href="#cb17-26" 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-27"><a href="#cb17-27" 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-28"><a href="#cb17-28" 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-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb17-30"><a href="#cb17-30" 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_class</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_class</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/YK35d8MMx">EDG</a>, <a href="https://godbolt.org/z/cT116Wb31">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_class</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_class</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_class"><code class="sourceCode cpp">define_class</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">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>define_class<span class="op">(^</span>Storage, <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7" 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-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>        data_member_spec<span class="op">(^</span>Ts<span class="op">)...</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">})))</span>;</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-11"><a href="#cb20-11" 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-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> nonstatic_data_members_of<span class="op">(^</span>Storage<span class="op">)[</span>n<span class="op">+</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>    Storage storage_;</span>
<span id="cb20-16"><a href="#cb20-16" 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-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>    <span class="co">// cheat: use libstdc++&#39;s implementation</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb20-20"><a href="#cb20-20" 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-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a></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">class</span> F<span class="op">&gt;</span></span>
<span id="cb20-23"><a href="#cb20-23" 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-24"><a href="#cb20-24" 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-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-28"><a href="#cb20-28" 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-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a>        <span class="co">// should this work: storage_{. [: get_nth_field(0) :]{} }</span></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-33"><a href="#cb20-33" 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-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-36"><a href="#cb20-36" 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-37"><a href="#cb20-37" 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-38"><a href="#cb20-38" 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-39"><a href="#cb20-39" 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-40"><a href="#cb20-40" 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-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb20-42"><a href="#cb20-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-43"><a href="#cb20-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-44"><a href="#cb20-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-45"><a href="#cb20-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="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-46"><a href="#cb20-46" 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-47"><a href="#cb20-47" 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-48"><a href="#cb20-48" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-49"><a href="#cb20-49" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb20-50"><a href="#cb20-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-51"><a href="#cb20-51" 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-52"><a href="#cb20-52" 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-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></span>
<span id="cb20-55"><a href="#cb20-55" 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-56"><a href="#cb20-56" 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-57"><a href="#cb20-57" 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-58"><a href="#cb20-58" 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-59"><a href="#cb20-59" 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-60"><a href="#cb20-60" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> storage_<span class="op">{.</span>empty<span class="op">={}}</span></span>
<span id="cb20-61"><a href="#cb20-61" aria-hidden="true" tabindex="-1"></a>        , index_<span class="op">(-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb20-62"><a href="#cb20-62" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-63"><a href="#cb20-63" 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-64"><a href="#cb20-64" 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-65"><a href="#cb20-65" 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-66"><a href="#cb20-66" aria-hidden="true" tabindex="-1"></a>            index_ <span class="op">=</span> I;</span>
<span id="cb20-67"><a href="#cb20-67" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb20-68"><a href="#cb20-68" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-69"><a href="#cb20-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-70"><a href="#cb20-70" 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-71"><a href="#cb20-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-72"><a href="#cb20-72" 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-73"><a href="#cb20-73" 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-74"><a href="#cb20-74" 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-75"><a href="#cb20-75" 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-76"><a href="#cb20-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-77"><a href="#cb20-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-78"><a href="#cb20-78" 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-79"><a href="#cb20-79" 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-80"><a href="#cb20-80" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb20-81"><a href="#cb20-81" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-82"><a href="#cb20-82" 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="P3293R0">[<a href="https://wg21.link/p3293r0" role="doc-biblioref">P3293R0</a>]</span>.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/Efz5vsjaa">EDG</a>, <a href="https://godbolt.org/z/faEaq16Kh">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, std<span class="op">::</span><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>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> make_struct_of_arrays<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info type,</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>                                     std<span class="op">::</span>meta<span class="op">::</span>info N<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="cb23-9"><a href="#cb23-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> old_members <span class="op">=</span> nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span>;</span>
<span id="cb23-10"><a href="#cb23-10" 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-11"><a href="#cb23-11" 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-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> type_array <span class="op">=</span> substitute<span class="op">(^</span>std<span class="op">::</span>array, <span class="op">{</span>type_of<span class="op">(</span>member<span class="op">)</span>, N <span class="op">})</span>;</span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> mem_descr <span class="op">=</span> data_member_spec<span class="op">(</span>type_array, <span class="op">{.</span>name <span class="op">=</span> name_of<span class="op">(</span>member<span class="op">)})</span>;</span>
<span id="cb23-14"><a href="#cb23-14" 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-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>define_class<span class="op">(</span></span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>    substitute<span class="op">(^</span>struct_of_arrays_impl, <span class="op">{</span>type, N<span class="op">})</span>,</span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>    new_members<span class="op">)</span>;</span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-21"><a href="#cb23-21" 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-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> struct_of_arrays <span class="op">=</span> <span class="op">[:</span> make_struct_of_arrays<span class="op">(^</span>T, <span class="op">^</span>N<span class="op">)</span> <span class="op">:]</span>;</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_class</code> is put to good use.</p>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/Whdvs3j1n">EDG</a>, <a href="https://godbolt.org/z/senWPW3eY">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_class</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="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">struct</span> Args <span class="op">:</span> Clap <span class="op">{</span></span>
<span id="cb25-2"><a href="#cb25-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="cb25-3"><a href="#cb25-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="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-6"><a href="#cb25-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="cb25-7"><a href="#cb25-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="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-9"><a href="#cb25-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="cb25-10"><a href="#cb25-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="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb25-12"><a href="#cb25-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="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">struct</span> Flags <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> use_short;</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> use_long;</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-6"><a href="#cb26-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="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Option <span class="op">{</span></span>
<span id="cb26-8"><a href="#cb26-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="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// some suitable constructors and accessors for flags</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-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="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a><span class="co">// to a type that is just the appropriate members.</span></span>
<span id="cb26-15"><a href="#cb26-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="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a><span class="co">// function would evaluate to a reflection of the type</span></span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a><span class="co">// struct {</span></span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a><span class="co">//   std::string name;</span></span>
<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a><span class="co">//   int count;</span></span>
<span id="cb26-20"><a href="#cb26-20" aria-hidden="true" tabindex="-1"></a><span class="co">// }</span></span>
<span id="cb26-21"><a href="#cb26-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="cb26-22"><a href="#cb26-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="cb26-23"><a href="#cb26-23" 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="cb26-24"><a href="#cb26-24" 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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb26-25"><a href="#cb26-25" 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="cb26-26"><a href="#cb26-26" 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>name_of<span class="op">(</span>member<span class="op">)}))</span>;</span>
<span id="cb26-27"><a href="#cb26-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb26-28"><a href="#cb26-28" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> define_class<span class="op">(</span>opts, new_members<span class="op">)</span>;</span>
<span id="cb26-29"><a href="#cb26-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb26-30"><a href="#cb26-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-31"><a href="#cb26-31" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Clap <span class="op">{</span></span>
<span id="cb26-32"><a href="#cb26-32" 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="cb26-33"><a href="#cb26-33" 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="cb26-34"><a href="#cb26-34" 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="cb26-35"><a href="#cb26-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-36"><a href="#cb26-36" aria-hidden="true" tabindex="-1"></a>    <span class="co">// check if cmdline contains --help, etc.</span></span>
<span id="cb26-37"><a href="#cb26-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-38"><a href="#cb26-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Opts;</span>
<span id="cb26-39"><a href="#cb26-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>spec_to_opts<span class="op">(^</span>Opts, <span class="op">^</span>Spec<span class="op">)))</span>;</span>
<span id="cb26-40"><a href="#cb26-40" aria-hidden="true" tabindex="-1"></a>    Opts opts;</span>
<span id="cb26-41"><a href="#cb26-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-42"><a href="#cb26-42" 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> std<span class="op">::</span>views<span class="op">::</span>zip<span class="op">(</span>nonstatic_data_members_of<span class="op">(^</span>Spec<span class="op">)</span>,</span>
<span id="cb26-43"><a href="#cb26-43" aria-hidden="true" tabindex="-1"></a>                                                            nonstatic_data_members_of<span class="op">(^</span>Opts<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb26-44"><a href="#cb26-44" 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="cb26-45"><a href="#cb26-45" 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="cb26-46"><a href="#cb26-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-47"><a href="#cb26-47" aria-hidden="true" tabindex="-1"></a>      <span class="co">// find the argument associated with this option</span></span>
<span id="cb26-48"><a href="#cb26-48" 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="cb26-49"><a href="#cb26-49" 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="cb26-50"><a href="#cb26-50" 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> name_of<span class="op">(</span>sm<span class="op">)[</span><span class="dv">0</span><span class="op">])</span></span>
<span id="cb26-51"><a href="#cb26-51" 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> name_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb26-52"><a href="#cb26-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb26-53"><a href="#cb26-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-54"><a href="#cb26-54" aria-hidden="true" tabindex="-1"></a>      <span class="co">// no such argument</span></span>
<span id="cb26-55"><a href="#cb26-55" 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="cb26-56"><a href="#cb26-56" 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="cb26-57"><a href="#cb26-57" aria-hidden="true" tabindex="-1"></a>          <span class="co">// the type is optional, so the argument is too</span></span>
<span id="cb26-58"><a href="#cb26-58" aria-hidden="true" tabindex="-1"></a>          <span class="cf">continue</span>;</span>
<span id="cb26-59"><a href="#cb26-59" 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="cb26-60"><a href="#cb26-60" 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="cb26-61"><a href="#cb26-61" 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="cb26-62"><a href="#cb26-62" aria-hidden="true" tabindex="-1"></a>          <span class="cf">continue</span>;</span>
<span id="cb26-63"><a href="#cb26-63" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb26-64"><a href="#cb26-64" 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>, name_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb26-65"><a href="#cb26-65" 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="cb26-66"><a href="#cb26-66" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-67"><a href="#cb26-67" 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="cb26-68"><a href="#cb26-68" 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, name_of<span class="op">(</span>sm<span class="op">))</span>;</span>
<span id="cb26-69"><a href="#cb26-69" 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="cb26-70"><a href="#cb26-70" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb26-71"><a href="#cb26-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-72"><a href="#cb26-72" aria-hidden="true" tabindex="-1"></a>      <span class="co">// found our argument, try to parse it</span></span>
<span id="cb26-73"><a href="#cb26-73" 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="cb26-74"><a href="#cb26-74" 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="cb26-75"><a href="#cb26-75" 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="cb26-76"><a href="#cb26-76" aria-hidden="true" tabindex="-1"></a>          it<span class="op">[</span><span class="dv">1</span><span class="op">]</span>, name_of<span class="op">(</span>sm<span class="op">)</span>, display_name_of<span class="op">(</span>type<span class="op">))</span>;</span>
<span id="cb26-77"><a href="#cb26-77" 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="cb26-78"><a href="#cb26-78" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb26-79"><a href="#cb26-79" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-80"><a href="#cb26-80" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> opts;</span>
<span id="cb26-81"><a href="#cb26-81" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb26-82"><a href="#cb26-82" 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/MWfqvMeTx">EDG</a>, <a href="https://godbolt.org/z/79MrYvPP3">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="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> universal_formatter <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-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="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-4"><a href="#cb27-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="cb27-5"><a href="#cb27-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="cb27-6"><a href="#cb27-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>, name_of<span class="op">(^</span>T<span class="op">))</span>;</span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-8"><a href="#cb27-8" 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="cb27-9"><a href="#cb27-9" 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="cb27-10"><a href="#cb27-10" 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="cb27-11"><a href="#cb27-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="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>      first <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-16"><a href="#cb27-16" 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> bases_of<span class="op">(^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a>      delim<span class="op">()</span>;</span>
<span id="cb27-18"><a href="#cb27-18" 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="cb27-19"><a href="#cb27-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-20"><a href="#cb27-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-21"><a href="#cb27-21" 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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb27-22"><a href="#cb27-22" aria-hidden="true" tabindex="-1"></a>      delim<span class="op">()</span>;</span>
<span id="cb27-23"><a href="#cb27-23" 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>, name_of<span class="op">(</span>mem<span class="op">)</span>, t<span class="op">.[:</span>mem<span class="op">:])</span>;</span>
<span id="cb27-24"><a href="#cb27-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-25"><a href="#cb27-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-26"><a href="#cb27-26" 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="cb27-27"><a href="#cb27-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> out;</span>
<span id="cb27-28"><a href="#cb27-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb27-29"><a href="#cb27-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb27-30"><a href="#cb27-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-31"><a href="#cb27-31" 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="cb27-32"><a href="#cb27-32" 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="cb27-33"><a href="#cb27-33" 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="cb27-34"><a href="#cb27-34" 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="cb27-35"><a href="#cb27-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-36"><a href="#cb27-36" 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="cb27-37"><a href="#cb27-37" 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="cb27-38"><a href="#cb27-38" 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="cb27-39"><a href="#cb27-39" 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="cb27-40"><a href="#cb27-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-41"><a href="#cb27-41" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb27-42"><a href="#cb27-42" 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="cb27-43"><a href="#cb27-43" 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="cb27-44"><a href="#cb27-44" 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/r7f8h38fq">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="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">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="cb28-2"><a href="#cb28-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="cb28-3"><a href="#cb28-3" 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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb28-4"><a href="#cb28-4" 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="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<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="P1061R5">[<a href="https://wg21.link/p1061r5" role="doc-biblioref">P1061R5</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="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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</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> 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="cb29-3"><a href="#cb29-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="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-5"><a href="#cb29-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="cb29-6"><a href="#cb29-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="cb29-7"><a href="#cb29-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="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> indices;</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-11"><a href="#cb29-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="cb29-12"><a href="#cb29-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="cb29-13"><a href="#cb29-13" 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="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">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="cb30-2"><a href="#cb30-2" 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="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>                    nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></span>
<span id="cb30-4"><a href="#cb30-4" 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="cb30-5"><a href="#cb30-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_remove_cvref<span class="op">)</span></span>
<span id="cb30-6"><a href="#cb30-6" 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="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-9"><a href="#cb30-9" 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="cb30-10"><a href="#cb30-10" 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="cb30-11"><a href="#cb30-11" 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="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-14"><a href="#cb30-14" 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="cb30-15"><a href="#cb30-15" 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="cb30-16"><a href="#cb30-16" 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="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-18"><a href="#cb30-18" 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="cb30-19"><a href="#cb30-19" 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<span class="op">))</span> <span class="op">{</span></span>
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a>    args<span class="op">.</span>push_back<span class="op">(</span>reflect_value<span class="op">(</span>mem<span class="op">))</span>;</span>
<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">/*</span></span>
<span id="cb30-24"><a href="#cb30-24" aria-hidden="true" tabindex="-1"></a><span class="co">  Alternatively, with Ranges:</span></span>
<span id="cb30-25"><a href="#cb30-25" aria-hidden="true" tabindex="-1"></a><span class="co">  args.append_range(</span></span>
<span id="cb30-26"><a href="#cb30-26" aria-hidden="true" tabindex="-1"></a><span class="co">    nonstatic_data_members_of(^From)</span></span>
<span id="cb30-27"><a href="#cb30-27" aria-hidden="true" tabindex="-1"></a><span class="co">    | std::views::transform(std::meta::reflect_value)</span></span>
<span id="cb30-28"><a href="#cb30-28" aria-hidden="true" tabindex="-1"></a><span class="co">    );</span></span>
<span id="cb30-29"><a href="#cb30-29" aria-hidden="true" tabindex="-1"></a><span class="co">  */</span></span>
<span id="cb30-30"><a href="#cb30-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-31"><a href="#cb30-31" 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="cb30-32"><a href="#cb30-32" aria-hidden="true" tabindex="-1"></a>    substitute<span class="op">(^</span>struct_to_tuple_helper, args<span class="op">))</span>;</span>
<span id="cb30-33"><a href="#cb30-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-34"><a href="#cb30-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-35"><a href="#cb30-35" 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="cb30-36"><a href="#cb30-36" 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="cb30-37"><a href="#cb30-37" 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="cb30-38"><a href="#cb30-38" 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/Moqf84nc1">EDG</a>, <a href="https://godbolt.org/z/1s7aj5r69">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/EajGPdf9q">on compiler explorer</a>:</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>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="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Indexer <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-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="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>   <span class="co">// Can use tuple indexing instead of tuple of tuples</span></span>
<span id="cb31-5"><a href="#cb31-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="cb31-6"><a href="#cb31-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="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>       std<span class="op">::</span>tuple_element_t<span class="op">&lt;</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>         indices<span class="op">.</span>second,</span>
<span id="cb31-9"><a href="#cb31-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="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>       <span class="op">&gt;...</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>     <span class="op">&gt;</span>;</span>
<span id="cb31-12"><a href="#cb31-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="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-16"><a href="#cb31-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="cb31-17"><a href="#cb31-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="cb31-18"><a href="#cb31-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="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb31-20"><a href="#cb31-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="cb31-21"><a href="#cb31-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="cb31-22"><a href="#cb31-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_value<span class="op">(</span>x<span class="op">))</span>;</span>
<span id="cb31-23"><a href="#cb31-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb31-24"><a href="#cb31-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-25"><a href="#cb31-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="cb31-26"><a href="#cb31-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb31-27"><a href="#cb31-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-28"><a href="#cb31-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="cb31-29"><a href="#cb31-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="cb31-30"><a href="#cb31-30" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb31-31"><a href="#cb31-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="cb31-32"><a href="#cb31-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-33"><a href="#cb31-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="cb31-34"><a href="#cb31-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="cb31-35"><a href="#cb31-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="cb31-36"><a href="#cb31-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb31-37"><a href="#cb31-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb31-38"><a href="#cb31-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-39"><a href="#cb31-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="cb31-40"><a href="#cb31-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb31-41"><a href="#cb31-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-42"><a href="#cb31-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="cb31-43"><a href="#cb31-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="cb31-44"><a href="#cb31-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>type_tuple_size<span class="op">(</span>type_remove_cvref<span class="op">(^</span>Tuples<span class="op">))...})</span> <span class="op">:]</span> indexer;</span>
<span id="cb31-45"><a href="#cb31-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="cb31-46"><a href="#cb31-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="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-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_value<span class="op">(</span><span class="st">&quot;x&quot;</span><span class="op">)</span>,</span>
<span id="cb32-2"><a href="#cb32-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_value<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_class</code> (given a suitable
<code class="sourceCode cpp">fixed_string</code> type):</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><span class="kw">class</span> T, fixed_string Name<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> pair <span class="op">{</span></span>
<span id="cb33-3"><a href="#cb33-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="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-7"><a href="#cb33-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="cb33-8"><a href="#cb33-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="cb33-9"><a href="#cb33-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="cb33-10"><a href="#cb33-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="cb33-11"><a href="#cb33-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="cb33-12"><a href="#cb33-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="cb33-13"><a href="#cb33-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="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb33-16"><a href="#cb33-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="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> define_class<span class="op">(</span>type, nsdms<span class="op">)</span>;</span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> R;</span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>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="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-23"><a href="#cb33-23" 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<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="cb33-24"><a href="#cb33-24" 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<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="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb33-27"><a href="#cb33-27" 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="cb33-28"><a href="#cb33-28" 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/nMx4M9sdT">EDG</a>, <a href="https://godbolt.org/z/TK71ThhM5">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="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">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="cb34-2"><a href="#cb34-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="cb34-3"><a href="#cb34-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="cb34-4"><a href="#cb34-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="cb34-5"><a href="#cb34-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="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> define_class<span class="op">(</span>type, nsdms<span class="op">)</span>;</span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> R;</span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>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="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-13"><a href="#cb34-13" 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<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="cb34-14"><a href="#cb34-14" 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<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="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb34-17"><a href="#cb34-17" 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="cb34-18"><a href="#cb34-18" 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/dPcsaTEv6">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>).</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="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">class</span> TU_Ticket <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" 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="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">int</span> next<span class="op">()</span> <span class="op">{</span></span>
<span id="cb35-5"><a href="#cb35-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="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="co">// Search for the next incomplete &#39;Helper&lt;k&gt;&#39;.</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>meta<span class="op">::</span>info r;</span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(!</span>is_incomplete_type<span class="op">(</span>r <span class="op">=</span> substitute<span class="op">(^</span>Helper,</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>                                             <span class="op">{</span> std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">(</span>k<span class="op">)</span> <span class="op">})))</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>      <span class="op">++</span>k;</span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Define &#39;Helper&lt;k&gt;&#39; and return its index.</span></span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>    define_class<span class="op">(</span>r, <span class="op">{})</span>;</span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> k;</span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-19"><a href="#cb35-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>next<span class="op">()</span>;</span>
<span id="cb35-20"><a href="#cb35-20" 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="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-22"><a href="#cb35-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>next<span class="op">()</span>;</span>
<span id="cb35-23"><a href="#cb35-23" 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="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="dt">int</span> z <span class="op">=</span> TU_Ticket<span class="op">::</span>next<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>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/MEYd3771Y">EDG</a>, <a href="https://godbolt.org/z/K4KWEqevv">Clang</a>.</p>
<h2 data-number="3.18" id="emulating-typeful-reflection"><span class="header-section-number">3.18</span> Emulating typeful reflection<a href="#emulating-typeful-reflection" class="self-link"></a></h2>
<p>Although we believe a single opaque <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
type to be the best and most scalable foundation for reflection, we
acknowledge the desire expressed by SG7 for future support for “typeful
reflection”. The following demonstrates one possible means of assembling
a typeful reflection library, in which different classes of reflections
are represented by distinct types, on top of the facilities proposed
here.</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="co">// Represents a &#39;std::meta::info&#39; constrained by a predicate.</span></span>
<span id="cb36-2"><a href="#cb36-2" 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 Pred<span class="op">&gt;</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span>test_trait<span class="op">(^</span>std<span class="op">::</span>predicate, <span class="op">{</span>type_of<span class="op">(</span>Pred<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="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> metatype <span class="op">{</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>meta<span class="op">::</span>info value;</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Construction is ill-formed unless predicate is satisfied.</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> metatype<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">:</span> value<span class="op">(</span>r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(![:</span>Pred<span class="op">:](</span>r<span class="op">))</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <span class="st">&quot;Reflection is not a member of this metatype&quot;</span>;</span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Cast to &#39;std::meta::info&#39; allows values of this type to be spliced.</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">operator</span> std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> value; <span class="op">}</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> check<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">[:</span>Pred<span class="op">:](</span>r<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a><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="co">// Type representing a &quot;failure to match&quot; any known metatypes.</span></span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> unmatched <span class="op">{</span></span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> unmatched<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> <span class="dt">bool</span> check<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="cf">return</span> <span class="kw">true</span>; <span class="op">}</span></span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-25"><a href="#cb36-25" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns the given reflection &quot;enriched&quot; with a more descriptive type.</span></span>
<span id="cb36-26"><a href="#cb36-26" 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> Choices<span class="op">&gt;</span></span>
<span id="cb36-27"><a href="#cb36-27" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>meta<span class="op">::</span>info enrich<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-28"><a href="#cb36-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Because we control the type, we know that the constructor taking info is</span></span>
<span id="cb36-29"><a href="#cb36-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// the first constructor. The copy/move constructors are added at the }, so</span></span>
<span id="cb36-30"><a href="#cb36-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// will be the last ones in the list.</span></span>
<span id="cb36-31"><a href="#cb36-31" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array ctors <span class="op">=</span> <span class="op">{</span>members_of<span class="op">(^</span>Choices, std<span class="op">::</span>meta<span class="op">::</span>is_constructor<span class="op">)[</span><span class="dv">0</span><span class="op">]...</span>,</span>
<span id="cb36-32"><a href="#cb36-32" aria-hidden="true" tabindex="-1"></a>                      members_of<span class="op">(^</span>unmatched, std<span class="op">::</span>meta<span class="op">::</span>is_constructor<span class="op">)[</span><span class="dv">0</span><span class="op">]}</span>;</span>
<span id="cb36-33"><a href="#cb36-33" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>array checks <span class="op">=</span> <span class="op">{^</span>Choices<span class="op">::</span>check<span class="op">...</span>, <span class="op">^</span>unmatched<span class="op">::</span>check<span class="op">}</span>;</span>
<span id="cb36-34"><a href="#cb36-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-35"><a href="#cb36-35" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="op">[</span>check, ctor<span class="op">]</span> <span class="op">:</span> std<span class="op">::</span>views<span class="op">::</span>zip<span class="op">(</span>checks, ctors<span class="op">))</span></span>
<span id="cb36-36"><a href="#cb36-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>reflect_invoke<span class="op">(</span>check, <span class="op">{</span>reflect_value<span class="op">(</span>r<span class="op">)})))</span></span>
<span id="cb36-37"><a href="#cb36-37" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> reflect_invoke<span class="op">(</span>ctor, <span class="op">{</span>reflect_value<span class="op">(</span>r<span class="op">)})</span>;</span>
<span id="cb36-38"><a href="#cb36-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-39"><a href="#cb36-39" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>unreachable<span class="op">()</span>;</span>
<span id="cb36-40"><a href="#cb36-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We can leverage this machinery to select different function overloads
based on the “type” of reflection provided as an argument.</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">using</span> type_t <span class="op">=</span> metatype<span class="op">&lt;^</span>std<span class="op">::</span>meta<span class="op">::</span>is_type<span class="op">&gt;</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> template_t <span class="op">=</span> metatype<span class="op">&lt;^</span>std<span class="op">::</span>meta<span class="op">::</span>is_template<span class="op">&gt;</span>;</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Example of a function overloaded for different &quot;types&quot; of reflections.</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> PrintKind<span class="op">(</span>type_t<span class="op">)</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;type&quot;</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> PrintKind<span class="op">(</span>template_t<span class="op">)</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;template&quot;</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> PrintKind<span class="op">(</span>unmatched<span class="op">)</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;unknown kind&quot;</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Classifies any reflection as one of: Type, Function, or Unmatched.</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> enrich <span class="op">=</span> <span class="op">[](</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">::</span>enrich<span class="op">&lt;</span>type_t,</span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a>                                                        template_t<span class="op">&gt;(</span>r<span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Demonstration of using &#39;enrich&#39; to select an overload.</span></span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a>  PrintKind<span class="op">([:</span>enrich<span class="op">(^</span>metatype<span class="op">):])</span>;                   <span class="co">// &quot;template&quot;</span></span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a>  PrintKind<span class="op">([:</span>enrich<span class="op">(^</span>type_t<span class="op">):])</span>;                     <span class="co">// &quot;type&quot;</span></span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a>  PrintKind<span class="op">([:</span>enrich<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">(</span><span class="dv">3</span><span class="op">):])</span>;  <span class="co">// &quot;unknown kind&quot;</span></span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Note that the <code class="sourceCode cpp">metatype</code> class can
be generalized to wrap values of any literal type, or to wrap multiple
values of possibly different types. This has been used, for instance, to
select compile-time overloads based on: whether two integers share the
same parity, the presence or absence of a value in an
<code class="sourceCode cpp">optional</code>, the type of the value held
by a <code class="sourceCode cpp">variant</code> or an
<code class="sourceCode cpp">any</code>, or the syntactic form of a
compile-time string.</p>
<p>Achieving the same in C++23, with the same generality, would require
spelling the argument(s) twice: first to obtain a “classification tag”
to use as a template argument, and again to call the function, i.e.,</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>Printer<span class="op">::</span>PrintKind<span class="op">&lt;</span>classify<span class="op">(^</span><span class="dt">int</span><span class="op">)&gt;(^</span><span class="dt">int</span><span class="op">).</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="co">// or worse...</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>fn<span class="op">&lt;</span>classify<span class="op">(</span>Arg1, Arg2, Arg3<span class="op">)&gt;(</span>Arg1, Arg2, Arg3<span class="op">).</span></span></code></pre></div>
</blockquote>
</div>
<p>On Compiler Explorer: <a href="https://godbolt.org/z/q88dWYq8v">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"><em>unary-expression</em>:<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>
<em>namespace-name</em><br />
      <code class="sourceCode cpp"><span class="op">^</span></code>
<em>type-id</em><br />
      <code class="sourceCode cpp"><span class="op">^</span></code>
<em>id-expression</em></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
<em>namespace-name</em> or <em>type-id</em>, the resulting value is a
reflection of the designated namespace or type.</p>
<p>When the operand is an <em>id-expression</em>, 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 or member function</li>
<li>a non-static data member</li>
<li>a template or 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 <em>cast-expression</em> 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="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">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="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-3"><a href="#cb39-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="cb39-4"><a href="#cb39-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="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-6"><a href="#cb39-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="cb39-7"><a href="#cb39-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="cb39-8"><a href="#cb39-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="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-10"><a href="#cb39-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="cb39-11"><a href="#cb39-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>
<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_value</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>value_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>
<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="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">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 or member 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>
reflects:</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> C <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-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="cb41-3"><a href="#cb41-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="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-6"><a href="#cb41-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="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f1 <span class="op">=</span> members_of<span class="op">(^</span>C, <span class="co">/* function templates named f */</span><span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f2 <span class="op">=</span> members_of<span class="op">(^</span>C, <span class="co">/* functions named f */</span><span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb41-10"><a href="#cb41-10" 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="cb41-11"><a href="#cb41-11" 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="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">struct</span> X <span class="op">{</span></span>
<span id="cb42-2"><a href="#cb42-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="cb42-3"><a href="#cb42-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="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> 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="cb43-2"><a href="#cb43-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="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">auto</span> pc <span class="op">=</span> <span class="op">&amp;[:</span> rc <span class="op">:]</span>;</span>
<span id="cb44-2"><a href="#cb44-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="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">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="cb44-5"><a href="#cb44-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="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">namespace</span> A <span class="op">{}</span></span>
<span id="cb45-2"><a href="#cb45-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="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> B <span class="op">{</span></span>
<span id="cb45-5"><a href="#cb45-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="cb45-6"><a href="#cb45-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="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></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="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>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="cb46-2"><a href="#cb46-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="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb46-5"><a href="#cb46-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="cb46-6"><a href="#cb46-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="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></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="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><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="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-3"><a href="#cb47-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="cb47-4"><a href="#cb47-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="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>What kind of parameter is <code class="sourceCode cpp">S</code>? If
<code class="sourceCode cpp">R</code> reflects a class template, then it
is a non-type template parameter of deduced type, but if
<code class="sourceCode cpp">R</code> reflects 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="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">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="cb48-2"><a href="#cb48-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 class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></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="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">struct</span> S <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-3"><a href="#cb49-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="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>
<span id="cb50-5"><a href="#cb50-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="cb50-6"><a href="#cb50-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="cb50-7"><a href="#cb50-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="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> indices;</span>
<span id="cb50-9"><a href="#cb50-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb50-10"><a href="#cb50-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-11"><a href="#cb50-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="cb50-12"><a href="#cb50-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="cb50-13"><a href="#cb50-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb51-2"><a href="#cb51-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="cb51-3"><a href="#cb51-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="cb51-4"><a href="#cb51-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="cb51-5"><a href="#cb51-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="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> <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="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-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="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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb54-2"><a href="#cb54-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="cb54-3"><a href="#cb54-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="cb54-4"><a href="#cb54-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="cb54-5"><a href="#cb54-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="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb54-7"><a href="#cb54-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="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">namespace</span> std <span class="op">{</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> meta <span class="op">{</span></span>
<span id="cb55-3"><a href="#cb55-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="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb55-5"><a href="#cb55-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="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">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="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span></span>
<span id="cb56-4"><a href="#cb56-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="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span></span>
<span id="cb56-6"><a href="#cb56-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="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb56-8"><a href="#cb56-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="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="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="cb57-2"><a href="#cb57-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="cb57-3"><a href="#cb57-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="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-5"><a href="#cb57-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="cb57-6"><a href="#cb57-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="cb57-7"><a href="#cb57-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="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-9"><a href="#cb57-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="cb57-10"><a href="#cb57-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="cb57-11"><a href="#cb57-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>
reflects 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="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x;</span>
<span id="cb58-2"><a href="#cb58-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="cb58-3"><a href="#cb58-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="cb58-4"><a href="#cb58-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="cb58-5"><a href="#cb58-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="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">using</span> Alias1 <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb59-2"><a href="#cb59-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="cb59-3"><a href="#cb59-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="cb59-4"><a href="#cb59-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="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">^</span>Alias;</span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</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>Alias1 <span class="op">==</span> <span class="op">^</span>Alias1<span class="op">)</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>Alias1 <span class="op">!=</span> <span class="op">^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb59-9"><a href="#cb59-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="cb59-10"><a href="#cb59-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="cb59-11"><a href="#cb59-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="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="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="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb60-3"><a href="#cb60-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="cb60-4"><a href="#cb60-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="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb60-6"><a href="#cb60-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="cb60-7"><a href="#cb60-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>value_of<span class="op">(^</span>i<span class="op">)</span> <span class="op">==</span> value_of<span class="op">(^</span>j<span class="op">))</span>;  <span class="co">// Two equivalent values.</span></span>
<span id="cb60-8"><a href="#cb60-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="cb60-9"><a href="#cb60-9" aria-hidden="true" tabindex="-1"></a>                                                   <span class="co">// object it designates.</span></span>
<span id="cb60-10"><a href="#cb60-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_value<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="cb60-11"><a href="#cb60-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="linkage-of-reflections-and-templates-specialized-by-reflections"><span class="header-section-number">4.3.2</span> Linkage of reflections and
templates specialized by reflections<a href="#linkage-of-reflections-and-templates-specialized-by-reflections" class="self-link"></a></h3>
<p>Nontype template arguments of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
are permitted (and frequently useful!), but since reflections represent
internal compiler state while processing a single translation unit, they
cannot be allowed to leak across TUs. Therefore both variables of
<em>consteval-only type</em>, and entities specialized by a non-type
template argument of <em>consteval-only type</em>, cannot have module or
external linkage (i.e., they must have either internal or no linkage).
While this can lead to some code bloat, we aren’t aware of any organic
use cases for reflection that are harmed by this limitation.</p>
<p>A corollary of this rule is that static data members of a class
cannot have consteval-only types - such members always have external
linkage, and to do otherwise would be an ODR violation. Again, we aren’t
aware of any affected use-cases that absolutely require this.</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="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> R<span class="op">&gt;</span> <span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x;</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> fn<span class="op">()</span> <span class="op">{</span> <span class="dt">int</span> k; <span class="cf">return</span> <span class="op">^</span>k; <span class="op">}</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^</span><span class="dt">int</span>;  <span class="co">// r has internal name linkage.</span></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;^</span>x<span class="op">&gt;</span> sx;  <span class="co">// S&lt;^x&gt; has internal name linkage.</span></span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>fn<span class="op">()&gt;</span> sy;  <span class="co">// S&lt;^y&gt; has internal name linkage.</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.3.3" id="the-associated-stdmeta-namespace"><span class="header-section-number">4.3.3</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 type 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="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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb62-3"><a href="#cb62-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>name_of<span class="op">(^</span>S<span class="op">)</span>;  <span class="co">// Okay.</span></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string name1 <span class="op">=</span> name_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="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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb63-3"><a href="#cb63-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="cb63-4"><a href="#cb63-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>
<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_class</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="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="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S;</span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span></span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>define_class<span class="op">(^</span>S, <span class="op">{})))</span>;</span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a>  S s;  <span class="co">// S should be defined at this point.</span></span>
<span id="cb64-7"><a href="#cb64-7" 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, we identify a subset of manifestly constant-evaluated
expressions and conversions characterized by the fact that their
evaluation must occur and must succeed in a valid C++ program: We call
these <em>plainly constant-evaluated</em>. We require that a programmer
can count on those evaluations occurring exactly once and completing at
translation time.</p>
<p>Second, we sequence plainly constant-evaluated expressions and
conversions within the lexical order. Specifically, we require that the
evaluation of a plainly constant-evaluated expression or conversion
occurs before the implementation checks the validity of source
constructs lexically following that expression or conversion.</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="citation" data-cites="P2758R1">[<a href="https://wg21.link/p2758r1" role="doc-biblioref">P2758R1</a>]</span> (“Emitting messages at compile
time”) 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 <span class="citation" data-cites="P2758R1">[<a href="https://wg21.link/p2758r1" role="doc-biblioref">P2758R1</a>]</span>.</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 reflected template
for us to 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="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">typename</span> T<span class="op">&gt;</span></span>
<span id="cb65-2"><a href="#cb65-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="cb65-3"><a href="#cb65-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/p3293r0" 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>. 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="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb66-2"><a href="#cb66-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="cb66-3"><a href="#cb66-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="cb66-4"><a href="#cb66-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="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb66-7"><a href="#cb66-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="cb66-8"><a href="#cb66-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/vnzWv6vG3">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="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">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="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> substitute<span class="op">(</span></span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">^</span>tuple,</span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a>        nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></span>
<span id="cb67-5"><a href="#cb67-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="cb67-6"><a href="#cb67-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>type_remove_cvref<span class="op">)</span></span>
<span id="cb67-7"><a href="#cb67-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="cb67-8"><a href="#cb67-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<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">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="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> substitute<span class="op">(</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">^</span>tuple,</span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a>        nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></span>
<span id="cb68-5"><a href="#cb68-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="cb68-6"><a href="#cb68-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>type_remove_cvref<span class="op">)</span></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span>;</span>
<span id="cb68-8"><a href="#cb68-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="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> <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="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb69-4"><a href="#cb69-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="cb69-5"><a href="#cb69-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="cb69-6"><a href="#cb69-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> as_span <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;(</span>args<span class="op">)</span>;</span>
<span id="cb69-7"><a href="#cb69-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">__builtin_substitute</span><span class="op">(</span>tmpl, as_span<span class="op">.</span>data<span class="op">()</span>, as_span<span class="op">.</span>size<span class="op">())</span>;</span>
<span id="cb69-8"><a href="#cb69-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb69-9"><a href="#cb69-9" 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="cb69-10"><a href="#cb69-10" 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="cb69-11"><a href="#cb69-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-12"><a href="#cb69-12" 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="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">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="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">using</span> A <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb71-2"><a href="#cb71-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="cb71-3"><a href="#cb71-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>
<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="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="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb72-3"><a href="#cb72-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="cb72-4"><a href="#cb72-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 string 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">name_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="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="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;meta&gt;</span></span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb73-4"><a href="#cb73-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="cb73-5"><a href="#cb73-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> name_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 name_of produces a std::string.</span></span>
<span id="cb73-6"><a href="#cb73-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">name_of</code> do produce “string view”
results. For example:</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><span class="kw">consteval</span> std<span class="op">::</span>string_view name_of<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> std<span class="op">::</span>u8string_view name_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="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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> source_text_info <span class="op">{</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb75-4"><a href="#cb75-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="cb75-5"><a href="#cb75-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="cb75-6"><a href="#cb75-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="cb75-7"><a href="#cb75-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">consteval</span> T as<span class="op">()</span>;</span>
<span id="cb75-8"><a href="#cb75-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb75-9"><a href="#cb75-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb75-10"><a href="#cb75-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">name_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
string literal encoding.</p>
<h3 data-number="4.4.6" id="freestanding-implementations"><span class="header-section-number">4.4.6</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="citation" data-cites="P3295R0">[<a href="https://wg21.link/p3295r0" role="doc-biblioref">P3295R0</a>]</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.7" id="synopsis"><span class="header-section-number">4.4.7</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="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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb76-2"><a href="#cb76-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="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-4"><a href="#cb76-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="cb76-5"><a href="#cb76-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="cb76-6"><a href="#cb76-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-7"><a href="#cb76-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#name-loc">name and location</a></span></span>
<span id="cb76-8"><a href="#cb76-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb76-9"><a href="#cb76-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> qualified_name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb76-10"><a href="#cb76-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> display_name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb76-11"><a href="#cb76-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-12"><a href="#cb76-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb76-13"><a href="#cb76-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8display_name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb76-14"><a href="#cb76-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8qualified_name_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb76-15"><a href="#cb76-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-16"><a href="#cb76-16" 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="cb76-17"><a href="#cb76-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-18"><a href="#cb76-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#type_of-parent_of-dealias">type queries</a></span></span>
<span id="cb76-19"><a href="#cb76-19" 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="cb76-20"><a href="#cb76-20" 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="cb76-21"><a href="#cb76-21" 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="cb76-22"><a href="#cb76-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-23"><a href="#cb76-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#object_of-value_of">object and value queries</a></span></span>
<span id="cb76-24"><a href="#cb76-24" 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="cb76-25"><a href="#cb76-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> value_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-26"><a href="#cb76-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-27"><a href="#cb76-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#template_of-template_arguments_of">template queries</a></span></span>
<span id="cb76-28"><a href="#cb76-28" 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="cb76-29"><a href="#cb76-29" 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="cb76-30"><a href="#cb76-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-31"><a href="#cb76-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#member-queries">member queries</a></span></span>
<span id="cb76-32"><a href="#cb76-32" 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>Fs<span class="op">&gt;</span></span>
<span id="cb76-33"><a href="#cb76-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> members_of<span class="op">(</span>info type_class, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-34"><a href="#cb76-34" 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>Fs<span class="op">&gt;</span></span>
<span id="cb76-35"><a href="#cb76-35" 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, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-36"><a href="#cb76-36" 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="cb76-37"><a href="#cb76-37" 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="cb76-38"><a href="#cb76-38" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> subobjects_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="cb76-39"><a href="#cb76-39" 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="cb76-40"><a href="#cb76-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-41"><a href="#cb76-41" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#member-access">member access</a></span></span>
<span id="cb76-42"><a href="#cb76-42" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> access_context<span class="op">()</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-43"><a href="#cb76-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-44"><a href="#cb76-44" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> access_pair <span class="op">{</span></span>
<span id="cb76-45"><a href="#cb76-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> access_pair<span class="op">(</span>info target, info from <span class="op">=</span> access_context<span class="op">())</span>;</span>
<span id="cb76-46"><a href="#cb76-46" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb76-47"><a href="#cb76-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-48"><a href="#cb76-48" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_accessible<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-49"><a href="#cb76-49" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_accessible<span class="op">(</span>info r, info from<span class="op">)</span>;</span>
<span id="cb76-50"><a href="#cb76-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-51"><a href="#cb76-51" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Pred<span class="op">&gt;</span></span>
<span id="cb76-52"><a href="#cb76-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>access_pair p, Pred pred<span class="op">)</span>;</span>
<span id="cb76-53"><a href="#cb76-53" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Pred<span class="op">&gt;</span></span>
<span id="cb76-54"><a href="#cb76-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>info target, info from, Pred pred<span class="op">)</span>;</span>
<span id="cb76-55"><a href="#cb76-55" 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> Preds<span class="op">&gt;</span></span>
<span id="cb76-56"><a href="#cb76-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>access_pair p,</span>
<span id="cb76-57"><a href="#cb76-57" aria-hidden="true" tabindex="-1"></a>                                         Preds<span class="op">...</span> preds<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-58"><a href="#cb76-58" 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> Preds<span class="op">&gt;</span></span>
<span id="cb76-59"><a href="#cb76-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>info target, info from,</span>
<span id="cb76-60"><a href="#cb76-60" aria-hidden="true" tabindex="-1"></a>                                         Preds<span class="op">...</span> preds<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-61"><a href="#cb76-61" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-62"><a href="#cb76-62" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>info target, info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-63"><a href="#cb76-63" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-64"><a href="#cb76-64" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Pred<span class="op">&gt;</span></span>
<span id="cb76-65"><a href="#cb76-65" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>access_pair p, Pred pred<span class="op">)</span>;</span>
<span id="cb76-66"><a href="#cb76-66" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Pred<span class="op">&gt;</span></span>
<span id="cb76-67"><a href="#cb76-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>info target, info from, Pred pred<span class="op">)</span>;</span>
<span id="cb76-68"><a href="#cb76-68" 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> Preds<span class="op">&gt;</span></span>
<span id="cb76-69"><a href="#cb76-69" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>access_pair p,</span>
<span id="cb76-70"><a href="#cb76-70" aria-hidden="true" tabindex="-1"></a>                                       Preds<span class="op">...</span> preds<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-71"><a href="#cb76-71" 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> Preds<span class="op">&gt;</span></span>
<span id="cb76-72"><a href="#cb76-72" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>info target, info from,</span>
<span id="cb76-73"><a href="#cb76-73" aria-hidden="true" tabindex="-1"></a>                                       Preds<span class="op">...</span> preds<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-74"><a href="#cb76-74" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-75"><a href="#cb76-75" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>info target, info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-76"><a href="#cb76-76" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-77"><a href="#cb76-77" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_nonstatic_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span></span>
<span id="cb76-78"><a href="#cb76-78" aria-hidden="true" tabindex="-1"></a>      <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-79"><a href="#cb76-79" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_nonstatic_data_members_of<span class="op">(</span>info target,</span>
<span id="cb76-80"><a href="#cb76-80" aria-hidden="true" tabindex="-1"></a>                                                      info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-81"><a href="#cb76-81" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_static_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-82"><a href="#cb76-82" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_static_data_members_of<span class="op">(</span>info target,</span>
<span id="cb76-83"><a href="#cb76-83" aria-hidden="true" tabindex="-1"></a>                                                   info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-84"><a href="#cb76-84" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_subobjects_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-85"><a href="#cb76-85" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_subobjects_of<span class="op">(</span>info target,</span>
<span id="cb76-86"><a href="#cb76-86" aria-hidden="true" tabindex="-1"></a>                                         info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb76-87"><a href="#cb76-87" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-88"><a href="#cb76-88" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#substitute">substitute</a></span></span>
<span id="cb76-89"><a href="#cb76-89" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-90"><a href="#cb76-90" 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="cb76-91"><a href="#cb76-91" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-92"><a href="#cb76-92" 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="cb76-93"><a href="#cb76-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-94"><a href="#cb76-94" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#reflect_invoke">reflect_invoke</a></span></span>
<span id="cb76-95"><a href="#cb76-95" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-96"><a href="#cb76-96" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> reflect_invoke<span class="op">(</span>info target, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-97"><a href="#cb76-97" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R1 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;</span>, reflection_range R2 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-98"><a href="#cb76-98" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> reflect_invoke<span class="op">(</span>info target, R1<span class="op">&amp;&amp;</span> tmpl_args, R2<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-99"><a href="#cb76-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-100"><a href="#cb76-100" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#reflect-expression-results">reflect expression results</a></span></span>
<span id="cb76-101"><a href="#cb76-101" 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="cb76-102"><a href="#cb76-102" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> reflect_value<span class="op">(</span>T value<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-103"><a href="#cb76-103" 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="cb76-104"><a href="#cb76-104" 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="cb76-105"><a href="#cb76-105" 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="cb76-106"><a href="#cb76-106" 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="cb76-107"><a href="#cb76-107" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-108"><a href="#cb76-108" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#extractt">extract<T></a></span></span>
<span id="cb76-109"><a href="#cb76-109" 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="cb76-110"><a href="#cb76-110" 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="cb76-111"><a href="#cb76-111" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-112"><a href="#cb76-112" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#test_trait">test_trait</a></span></span>
<span id="cb76-113"><a href="#cb76-113" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> test_trait<span class="op">(</span>info templ, info type<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-114"><a href="#cb76-114" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-115"><a href="#cb76-115" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> test_trait<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> arguments<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-116"><a href="#cb76-116" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-117"><a href="#cb76-117" 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="cb76-118"><a href="#cb76-118" 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="cb76-119"><a href="#cb76-119" 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="cb76-120"><a href="#cb76-120" 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="cb76-121"><a href="#cb76-121" 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="cb76-122"><a href="#cb76-122" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_pure_virtual<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-123"><a href="#cb76-123" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_override<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-124"><a href="#cb76-124" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_deleted<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-125"><a href="#cb76-125" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_defaulted<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-126"><a href="#cb76-126" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_explicit<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-127"><a href="#cb76-127" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_noexcept<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-128"><a href="#cb76-128" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_bit_field<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-129"><a href="#cb76-129" 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="cb76-130"><a href="#cb76-130" 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="cb76-131"><a href="#cb76-131" 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="cb76-132"><a href="#cb76-132" 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="cb76-133"><a href="#cb76-133" 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="cb76-134"><a href="#cb76-134" 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="cb76-135"><a href="#cb76-135" 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="cb76-136"><a href="#cb76-136" 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="cb76-137"><a href="#cb76-137" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_class_member<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-138"><a href="#cb76-138" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_namespace_member<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-139"><a href="#cb76-139" 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 entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-140"><a href="#cb76-140" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_static_member<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-141"><a href="#cb76-141" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_base<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-142"><a href="#cb76-142" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_namespace<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-143"><a href="#cb76-143" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_function<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-144"><a href="#cb76-144" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_variable<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-145"><a href="#cb76-145" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_type<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-146"><a href="#cb76-146" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_alias<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-147"><a href="#cb76-147" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_incomplete_type<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-148"><a href="#cb76-148" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_template<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-149"><a href="#cb76-149" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_function_template<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-150"><a href="#cb76-150" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_variable_template<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-151"><a href="#cb76-151" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_class_template<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-152"><a href="#cb76-152" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_alias_template<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-153"><a href="#cb76-153" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_concept<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-154"><a href="#cb76-154" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_structured_binding<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-155"><a href="#cb76-155" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_value<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-156"><a href="#cb76-156" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_object<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-157"><a href="#cb76-157" 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="cb76-158"><a href="#cb76-158" 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="cb76-159"><a href="#cb76-159" 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="cb76-160"><a href="#cb76-160" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_special_member<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb76-161"><a href="#cb76-161" 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="cb76-162"><a href="#cb76-162" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-163"><a href="#cb76-163" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#data_member_spec-define_class">define_class</a></span></span>
<span id="cb76-164"><a href="#cb76-164" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> data_member_options_t;</span>
<span id="cb76-165"><a href="#cb76-165" 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="cb76-166"><a href="#cb76-166" aria-hidden="true" tabindex="-1"></a>                                  data_member_options_t options <span class="op">=</span> <span class="op">{})</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-167"><a href="#cb76-167" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb76-168"><a href="#cb76-168" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> define_class<span class="op">(</span>info type_class, R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb76-169"><a href="#cb76-169" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-170"><a href="#cb76-170" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <a href="#data-layout-reflection">data layout</a></span></span>
<span id="cb76-171"><a href="#cb76-171" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> offset_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb76-172"><a href="#cb76-172" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> size_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb76-173"><a href="#cb76-173" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> alignment_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb76-174"><a href="#cb76-174" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_offset_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb76-175"><a href="#cb76-175" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_size_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb76-176"><a href="#cb76-176" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb76-177"><a href="#cb76-177" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.8" id="name-loc"><span class="header-section-number">4.4.8</span>
<code class="sourceCode cpp">name_of</code>,
<code class="sourceCode cpp">display_name_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="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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb77-3"><a href="#cb77-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> qualified_name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb77-4"><a href="#cb77-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> display_name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb77-5"><a href="#cb77-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-6"><a href="#cb77-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb77-7"><a href="#cb77-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8qualified_name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb77-8"><a href="#cb77-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> u8display_name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> u8string_view;</span>
<span id="cb77-9"><a href="#cb77-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb77-10"><a href="#cb77-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="cb77-11"><a href="#cb77-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If a <code class="sourceCode cpp">string_view</code> is returned, its
contents consist of characters representable by the ordinary string
literal encoding only; if any character cannot be represented, it is not
a constant expression.</p>
<p>Given a reflection <code class="sourceCode cpp">r</code> that
designates a declared entity <code class="sourceCode cpp">X</code>,
<code class="sourceCode cpp">name_of<span class="op">(</span>r<span class="op">)</span></code>
and <code class="sourceCode cpp">qualified_name_of<span class="op">(</span>r<span class="op">)</span></code>
return a <code class="sourceCode cpp">string_view</code> holding the
unqualified and qualified name of <code class="sourceCode cpp">X</code>,
respectively. <code class="sourceCode cpp">u8name_of<span class="op">(</span>r<span class="op">)</span></code>
and <code class="sourceCode cpp">qualified_name_of<span class="op">(</span>r<span class="op">)</span></code>
return the same, respectively, as a
<code class="sourceCode cpp">u8string_view</code>. For all other
reflections, an empty string view is produced. For template instances,
the name does not include the template argument list.</p>
<p>Given a reflection <code class="sourceCode cpp">r</code>, <code class="sourceCode cpp">display_name_of<span class="op">(</span>r<span class="op">)</span></code>
and <code class="sourceCode cpp">u8display_name_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.</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.9" id="type_of-parent_of-dealias"><span class="header-section-number">4.4.9</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="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">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="cb78-3"><a href="#cb78-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="cb78-4"><a href="#cb78-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="cb78-5"><a href="#cb78-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="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">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="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> type_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="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="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>If <code class="sourceCode cpp">r</code> designates a member of a
class or namespace, <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection designating its immediately enclosing class or (possibly
inline or anonymous) namespace.</p>
<p>If <code class="sourceCode cpp">r</code> designates an alias, <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
designates 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="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">using</span> X <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Y <span class="op">=</span> X;</span>
<span id="cb80-3"><a href="#cb80-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="cb80-4"><a href="#cb80-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="cb80-5"><a href="#cb80-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.10" id="object_of-value_of"><span class="header-section-number">4.4.10</span>
<code class="sourceCode cpp">object_of</code>,
<code class="sourceCode cpp">value_of</code><a href="#object_of-value_of" class="self-link"></a></h3>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb81-2"><a href="#cb81-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="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> value_of<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb81-4"><a href="#cb81-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="cb82"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x;</span>
<span id="cb82-2"><a href="#cb82-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="cb82-3"><a href="#cb82-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-4"><a href="#cb82-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="cb82-5"><a href="#cb82-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">value_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 <code class="sourceCode cpp">value_of<span class="op">(</span>r<span class="op">)</span></code>
is a reflection of the value of the object. For all other inputs, <code class="sourceCode cpp">value_of<span class="op">(</span>r<span class="op">)</span></code>
is not a constant expression.</p>
<h3 data-number="4.4.11" id="template_of-template_arguments_of"><span class="header-section-number">4.4.11</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="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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb83-2"><a href="#cb83-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="cb83-3"><a href="#cb83-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="cb83-4"><a href="#cb83-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="cb84"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb84-1"><a href="#cb84-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="cb84-2"><a href="#cb84-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="cb84-3"><a href="#cb84-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.12" id="member-queries"><span class="header-section-number">4.4.12</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>,
<code class="sourceCode cpp">subobjects_of</code><a href="#member-queries" class="self-link"></a></h3>
<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">template</span><span class="op">&lt;</span><span class="kw">typename</span> <span class="op">...</span>Fs<span class="op">&gt;</span></span>
<span id="cb85-3"><a href="#cb85-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> members_of<span class="op">(</span>info type_class, Fs <span class="op">...</span>filters<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-4"><a href="#cb85-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb85-5"><a href="#cb85-5" 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>Fs<span class="op">&gt;</span></span>
<span id="cb85-6"><a href="#cb85-6" 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, Fs <span class="op">...</span>filters<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-7"><a href="#cb85-7" aria-hidden="true" tabindex="-1"></a></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> 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 class="op">{</span></span>
<span id="cb85-9"><a href="#cb85-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> members_of<span class="op">(</span>type_class, is_variable<span class="op">)</span>;</span>
<span id="cb85-10"><a href="#cb85-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb85-11"><a href="#cb85-11" aria-hidden="true" tabindex="-1"></a></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> 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 class="op">{</span></span>
<span id="cb85-13"><a href="#cb85-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> members_of<span class="op">(</span>type_class, is_nonstatic_data_member<span class="op">)</span>;</span>
<span id="cb85-14"><a href="#cb85-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></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="kw">consteval</span> <span class="kw">auto</span> subobjects_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 class="op">{</span></span>
<span id="cb85-17"><a href="#cb85-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> subobjects <span class="op">=</span> bases_of<span class="op">(</span>type_class<span class="op">)</span>;</span>
<span id="cb85-18"><a href="#cb85-18" aria-hidden="true" tabindex="-1"></a>    subobjects<span class="op">.</span>append_range<span class="op">(</span>nonstatic_data_members_of<span class="op">(</span>type_class<span class="op">))</span>;</span>
<span id="cb85-19"><a href="#cb85-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> subobjects;</span>
<span id="cb85-20"><a href="#cb85-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb85-21"><a href="#cb85-21" aria-hidden="true" tabindex="-1"></a></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> 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-23"><a href="#cb85-23" 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
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. If any
<code class="sourceCode cpp">Filters<span class="op">...</span></code>
argument is specified, a member is dropped from the result if any filter
applied to that members reflection returns
<code class="sourceCode cpp"><span class="kw">false</span></code>. E.g.,
<code class="sourceCode cpp">members_of<span class="op">(^</span>C, std<span class="op">::</span>meta<span class="op">::</span>is_type<span class="op">)</span></code>
will only return types nested in the definition of
<code class="sourceCode cpp">C</code> and <code class="sourceCode cpp">members_of<span class="op">(^</span>C, std<span class="op">::</span>meta<span class="op">::</span>is_type, std<span class="op">::</span>meta<span class="op">::</span>is_variable<span class="op">)</span></code>
will return an empty vector since a member cannot be both a type and a
variable.</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 the
equivalent of <code class="sourceCode cpp">members_of<span class="op">(^</span>C, std<span class="op">::</span>meta<span class="op">::</span>is_nonstatic_data_member<span class="op">)</span></code>
and <code class="sourceCode cpp">members_of<span class="op">(^</span>C, std<span class="op">::</span>meta<span class="op">::</span>is_variable<span class="op">)</span></code>,
respectively.</p>
<p><code class="sourceCode cpp">subobjects_of</code> returns the base
class subobjects and the non-static data members of a type, in
declaration order. Note that the term <a href="https://eel.is/c++draft/intro.object#def:subobject">subobject</a>
also includes <em>array elements</em>, which we are excluding here. Such
reflections would currently be of minimal use since you could not splice
them with access (e.g. <code class="sourceCode cpp">arr<span class="op">.[:</span>elem<span class="op">:]</span></code>
is not supported), so would need some more thought first.</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.13" id="member-access"><span class="header-section-number">4.4.13</span> Member Access Reflection<a href="#member-access" 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> access_context<span class="op">()</span> <span class="op">-&gt;</span> info;</span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> access_pair <span class="op">{</span></span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> access_pair<span class="op">(</span>info target, info from <span class="op">=</span> access_context<span class="op">())</span>;</span>
<span id="cb86-6"><a href="#cb86-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</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> is_accessible<span class="op">(</span>access_pair p<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">template</span><span class="op">&lt;</span><span class="kw">typename</span> <span class="op">...</span>Fs<span class="op">&gt;</span></span>
<span id="cb86-11"><a href="#cb86-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>access_pair p, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-12"><a href="#cb86-12" 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>Fs<span class="op">&gt;</span></span>
<span id="cb86-13"><a href="#cb86-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_members_of<span class="op">(</span>info target, info from, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-14"><a href="#cb86-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-15"><a href="#cb86-15" 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>Fs<span class="op">&gt;</span></span>
<span id="cb86-16"><a href="#cb86-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>access_pair p, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-17"><a href="#cb86-17" 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>Fs<span class="op">&gt;</span></span>
<span id="cb86-18"><a href="#cb86-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> accessible_bases_of<span class="op">(</span>info target, info from, Fs <span class="op">...</span>filters<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-19"><a href="#cb86-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-20"><a href="#cb86-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_static_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-21"><a href="#cb86-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_static_data_members_of<span class="op">(</span>info target, info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-22"><a href="#cb86-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-23"><a href="#cb86-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_nonstatic_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-24"><a href="#cb86-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_nonstatic_data_members_of<span class="op">(</span>info target, info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-25"><a href="#cb86-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-26"><a href="#cb86-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_subobjects_of<span class="op">(</span>access_pair p<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-27"><a href="#cb86-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> accessible_subobjects_of<span class="op">(</span>info target, info from<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb86-28"><a href="#cb86-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The <code class="sourceCode cpp">access_context<span class="op">()</span></code>
function returns a reflection of the function, class, or namespace whose
scope encloses the function call.</p>
<p>The type <code class="sourceCode cpp">access_pair</code> represents
the operands of a check for access to
<code class="sourceCode cpp">target</code> from the scope introduced by
the function, class, or namespace reflected by
<code class="sourceCode cpp">from</code>. If
<code class="sourceCode cpp">from</code> is not specified, the
<code class="sourceCode cpp">access_pair</code> constructor captures the
current access context of the caller via the default argument. Each
function also provides an overload whereby
<code class="sourceCode cpp">target</code> and
<code class="sourceCode cpp">from</code> may be specified as distinct
arguments.</p>
<p>Each function named
<code class="sourceCode cpp">accessible_meow_of</code> returns the
result of <code class="sourceCode cpp">meow_of</code> filtered on
<code class="sourceCode cpp">is_accessible</code>.</p>
<p>For example:</p>
<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">class</span> C <span class="op">{</span></span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> k;</span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>is_accessible<span class="op">(^</span>C<span class="op">::</span>k<span class="op">))</span>;  <span class="co">// ok: context is &#39;C&#39;.</span></span>
<span id="cb87-4"><a href="#cb87-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb87-5"><a href="#cb87-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> fn<span class="op">()</span>;</span>
<span id="cb87-6"><a href="#cb87-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb87-7"><a href="#cb87-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb87-8"><a href="#cb87-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>accessible_subobjects_of<span class="op">(^</span>C<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb87-9"><a href="#cb87-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>accessible_subobjects_of<span class="op">(^</span>C, <span class="op">^</span>fn<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="4.4.14" id="substitute"><span class="header-section-number">4.4.14</span>
<code class="sourceCode cpp">substitute</code><a href="#substitute" class="self-link"></a></h3>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb88-3"><a href="#cb88-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="cb88-4"><a href="#cb88-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb88-5"><a href="#cb88-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="cb88-6"><a href="#cb88-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="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">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="cb89-2"><a href="#cb89-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="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">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="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb90-3"><a href="#cb90-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="cb90-4"><a href="#cb90-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.15" id="reflect_invoke"><span class="header-section-number">4.4.15</span>
<code class="sourceCode cpp">reflect_invoke</code><a href="#reflect_invoke" class="self-link"></a></h3>
<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="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> reflect_invoke<span class="op">(</span>info target, R<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R1 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;</span>, reflection_range R2 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb91-5"><a href="#cb91-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> reflect_invoke<span class="op">(</span>info target, R1<span class="op">&amp;&amp;</span> tmpl_args, R2<span class="op">&amp;&amp;</span> args<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb91-6"><a href="#cb91-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>These metafunctions produce a reflection of the result of a call
expression.</p>
<p>For the first overload: Letting <code class="sourceCode cpp">F</code>
be the entity reflected by <code class="sourceCode cpp">target</code>,
and <code class="sourceCode cpp">A<sub>0</sub>, A<sub>1</sub>, <span class="op">...</span>, A<sub>N</sub></code>
be the sequence of entities reflected by the values held by
<code class="sourceCode cpp">args</code>: if the expression <code class="sourceCode cpp">F<span class="op">(</span>A<sub>0</sub>, A<sub>1</sub>, <span class="op">...</span>, A<sub>N</sub><span class="op">)</span></code>
is a well-formed constant expression evaluating to a structural type
that is not
<code class="sourceCode cpp"><span class="dt">void</span></code>, and if
every value in <code class="sourceCode cpp">args</code> is a reflection
of a value or object usable in constant expressions, then <code class="sourceCode cpp">reflect_invoke<span class="op">(</span>target, args<span class="op">)</span></code>
evaluates to a reflection of the result of <code class="sourceCode cpp">F<span class="op">(</span>A<sub>0</sub>, A<sub>1</sub>, <span class="op">...</span>, A<sub>N</sub><span class="op">)</span></code>.
For all other invocations, <code class="sourceCode cpp">reflect_invoke<span class="op">(</span>target, args<span class="op">)</span></code>
is not a constant expression.</p>
<p>The second overload behaves the same as the first overload, except
instead of evaluating <code class="sourceCode cpp">F<span class="op">(</span>A<sub>0</sub>, A<sub>1</sub>, <span class="op">...</span>, A<sub>N</sub><span class="op">)</span></code>,
we require that <code class="sourceCode cpp">F</code> be a reflection of
a template and evaluate <code class="sourceCode cpp">F<span class="op">&lt;</span>T<sub>0</sub>, T<sub>1</sub>, <span class="op">...</span>, T<sub>M</sub><span class="op">&gt;(</span>A<sub>0</sub>, A<sub>1</sub>, <span class="op">...</span>, A<sub>N</sub><span class="op">)</span></code>.
This allows evaluating <code class="sourceCode cpp">reflect_invoke<span class="op">(^</span>std<span class="op">::</span>get, <span class="op">{</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">(</span><span class="dv">0</span><span class="op">)}</span>, <span class="op">{</span>e<span class="op">})</span></code>
to evaluate to, approximately, <code class="sourceCode cpp"><span class="op">^</span>std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;([:</span> e <span class="op">:])</span></code>.</p>
<p>If the returned reflection is of a value (rather than an object), the
type of the reflected value is the cv-qualified (de-aliased) type of
what’s returned by the function.</p>
<p>A few possible extensions for
<code class="sourceCode cpp">reflect_invoke</code> have been discussed
among the authors. Given the advent of constant evaluations with
side-effects, it may be worth allowing
<code class="sourceCode cpp"><span class="dt">void</span></code>-returning
functions, but this would require some representation of “a returned
value of type
<code class="sourceCode cpp"><span class="dt">void</span></code>”.
Construction of runtime call expressions is another exciting
possibility. Both extensions require more thought and implementation
experience, and we are not proposing either at this time.</p>
<h3 data-number="4.4.16" id="reflect-expression-results"><span class="header-section-number">4.4.16</span>
<code class="sourceCode cpp">reflect_value</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="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">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_value<span class="op">(</span>T expr<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">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="cb92-4"><a href="#cb92-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="cb92-5"><a href="#cb92-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_value<span class="op">(</span>expr<span class="op">)</span></code>
produces a reflection of the value computed by an lvalue-to-rvalue
conversion on <code class="sourceCode cpp">expr</code>. The type of the
reflected value is the cv-unqualified (de-aliased) type of
<code class="sourceCode cpp">expr</code>. The result needs to be a
permitted result of a constant expression, and
<code class="sourceCode cpp">T</code> cannot be of reference type.</p>
<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><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_value<span class="op">(</span><span class="dv">5</span><span class="op">)})</span> <span class="op">==</span></span>
<span id="cb93-2"><a href="#cb93-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="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">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="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb94-3"><a href="#cb94-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="cb94-4"><a href="#cb94-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="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">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="cb95-2"><a href="#cb95-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="cb95-3"><a href="#cb95-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb95-4"><a href="#cb95-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="cb95-5"><a href="#cb95-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.4.17" id="extractt"><span class="header-section-number">4.4.17</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="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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb96-2"><a href="#cb96-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="cb96-3"><a href="#cb96-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 reflected by
its operand.</p>
<h3 data-number="4.4.18" id="test_trait"><span class="header-section-number">4.4.18</span>
<code class="sourceCode cpp">test_trait</code><a href="#test_trait" class="self-link"></a></h3>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> test_trait<span class="op">(</span>info templ, info type<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb97-3"><a href="#cb97-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> test_trait<span class="op">(</span>templ, <span class="op">{</span>type<span class="op">})</span>;</span>
<span id="cb97-4"><a href="#cb97-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb97-5"><a href="#cb97-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-6"><a href="#cb97-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb97-7"><a href="#cb97-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> test_trait<span class="op">(</span>info templ, R<span class="op">&amp;&amp;</span> types<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb97-8"><a href="#cb97-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>substitute<span class="op">(</span>templ, <span class="op">(</span>R<span class="op">&amp;&amp;)</span>types<span class="op">))</span>;</span>
<span id="cb97-9"><a href="#cb97-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb97-10"><a href="#cb97-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This utility translates existing metaprogramming predicates
(expressed as constexpr variable templates or concept templates) to the
reflection domain. For example:</p>
<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">struct</span> S <span class="op">{}</span>;</span>
<span id="cb98-2"><a href="#cb98-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>test_trait<span class="op">(^</span>std<span class="op">::</span>is_class_v, <span class="op">^</span>S<span class="op">))</span>;</span>
<span id="cb98-3"><a href="#cb98-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>test_trait<span class="op">(^</span>std<span class="op">::</span>is_same_v, <span class="op">{^</span>S, <span class="op">^</span>S<span class="op">})</span></span></code></pre></div>
</blockquote>
</div>
<p>An implementation is permitted to recognize standard predicate
templates and implement <code class="sourceCode cpp">test_trait</code>
without actually instantiating the predicate template. In fact, that is
recommended practice.</p>
<h3 data-number="4.4.19" id="data_member_spec-define_class"><span class="header-section-number">4.4.19</span>
<code class="sourceCode cpp">data_member_spec</code>,
<code class="sourceCode cpp">define_class</code><a href="#data_member_spec-define_class" class="self-link"></a></h3>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb99-2"><a href="#cb99-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> data_member_options_t <span class="op">{</span></span>
<span id="cb99-3"><a href="#cb99-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> name_type <span class="op">{</span></span>
<span id="cb99-4"><a href="#cb99-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="cb99-5"><a href="#cb99-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="cb99-6"><a href="#cb99-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb99-7"><a href="#cb99-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="cb99-8"><a href="#cb99-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="cb99-9"><a href="#cb99-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb99-10"><a href="#cb99-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb99-11"><a href="#cb99-11" aria-hidden="true" tabindex="-1"></a>    optional<span class="op">&lt;</span>name_type<span class="op">&gt;</span> name;</span>
<span id="cb99-12"><a href="#cb99-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="cb99-13"><a href="#cb99-13" aria-hidden="true" tabindex="-1"></a>    optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> width;</span>
<span id="cb99-14"><a href="#cb99-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="cb99-15"><a href="#cb99-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb99-16"><a href="#cb99-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="cb99-17"><a href="#cb99-17" aria-hidden="true" tabindex="-1"></a>                                  data_member_options_t options <span class="op">=</span> <span class="op">{})</span> <span class="op">-&gt;</span> info;</span>
<span id="cb99-18"><a href="#cb99-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb99-19"><a href="#cb99-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> define_class<span class="op">(</span>info type_class, R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb99-20"><a href="#cb99-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 description of a data member of given type. Optional
alignment, bit-field-width, static-ness, 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 UTF-8 code-units (after
converting any contained UCNs to UTF-8). Otherwise, the name of the data
member is unspecified.</p>
<p><code class="sourceCode cpp">define_class</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="cb100"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb100-1"><a href="#cb100-1" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U;</span>
<span id="cb100-2"><a href="#cb100-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>define_class<span class="op">(^</span>U, <span class="op">{</span></span>
<span id="cb100-3"><a href="#cb100-3" 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="cb100-4"><a href="#cb100-4" 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="cb100-5"><a href="#cb100-5" 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="cb100-6"><a href="#cb100-6" aria-hidden="true" tabindex="-1"></a><span class="op">})))</span>;</span>
<span id="cb100-7"><a href="#cb100-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb100-8"><a href="#cb100-8" aria-hidden="true" tabindex="-1"></a><span class="co">// U is now defined to the equivalent of</span></span>
<span id="cb100-9"><a href="#cb100-9" aria-hidden="true" tabindex="-1"></a><span class="co">// union U {</span></span>
<span id="cb100-10"><a href="#cb100-10" aria-hidden="true" tabindex="-1"></a><span class="co">//   int <em>_0</em>;</span></span>
<span id="cb100-11"><a href="#cb100-11" aria-hidden="true" tabindex="-1"></a><span class="co">//   char <em>_1</em>;</span></span>
<span id="cb100-12"><a href="#cb100-12" aria-hidden="true" tabindex="-1"></a><span class="co">//   double <em>_2</em>;</span></span>
<span id="cb100-13"><a href="#cb100-13" aria-hidden="true" tabindex="-1"></a><span class="co">// };</span></span>
<span id="cb100-14"><a href="#cb100-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb100-15"><a href="#cb100-15" 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="cb100-16"><a href="#cb100-16" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> s_int_refl <span class="op">=</span> define_class<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="cb100-17"><a href="#cb100-17" 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="cb100-18"><a href="#cb100-18" 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>alignment<span class="op">=</span><span class="dv">64</span><span class="op">})</span>,</span>
<span id="cb100-19"><a href="#cb100-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;v</span><span class="sc">\\</span><span class="st">N{LATIN SMALL LETTER AE}rs</span><span class="sc">\\</span><span class="st">u{e5}god&quot;</span><span class="op">})</span></span>
<span id="cb100-20"><a href="#cb100-20" aria-hidden="true" tabindex="-1"></a><span class="op">})</span>;</span>
<span id="cb100-21"><a href="#cb100-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb100-22"><a href="#cb100-22" aria-hidden="true" tabindex="-1"></a><span class="co">// S&lt;int&gt; is now defined to the equivalent of</span></span>
<span id="cb100-23"><a href="#cb100-23" aria-hidden="true" tabindex="-1"></a><span class="co">// template&lt;&gt; struct S&lt;int&gt; {</span></span>
<span id="cb100-24"><a href="#cb100-24" aria-hidden="true" tabindex="-1"></a><span class="co">//   alignas(64) int i;</span></span>
<span id="cb100-25"><a href="#cb100-25" aria-hidden="true" tabindex="-1"></a><span class="co">//   alignas(64) int こんにち;</span></span>
<span id="cb100-26"><a href="#cb100-26" aria-hidden="true" tabindex="-1"></a><span class="co">//               int værsågod;</span></span>
<span id="cb100-27"><a href="#cb100-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_class</code> for
member functions.</p>
<p>If <code class="sourceCode cpp">type_class</code> is a reflection of
a type that already has a definition, or which is in the process of
being defined, the call to
<code class="sourceCode cpp">define_class</code> is not a constant
expression.</p>
<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="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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb101-2"><a href="#cb101-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> offset_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb101-3"><a href="#cb101-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> size_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb101-4"><a href="#cb101-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> alignment_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb101-5"><a href="#cb101-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb101-6"><a href="#cb101-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_offset_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb101-7"><a href="#cb101-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> bit_size_of<span class="op">(</span>info entity<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span>;</span>
<span id="cb101-8"><a href="#cb101-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb101-9"><a href="#cb101-9" 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.</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> and
<code class="sourceCode cpp">bit_offset_of</code> give the size and
offset of a base class subobject or non-static data member, except in
bits. Note that the <code class="sourceCode cpp">bit_offset_of</code> is
a value between
<code class="sourceCode cpp"><span class="dv">0</span></code> and
<code class="sourceCode cpp"><span class="dv">7</span></code>,
inclusive:</li>
</ul>
<div class="std">
<blockquote>
<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">struct</span> Msg <span class="op">{</span></span>
<span id="cb102-2"><a href="#cb102-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="cb102-3"><a href="#cb102-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="cb102-4"><a href="#cb102-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="cb102-5"><a href="#cb102-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="cb102-6"><a href="#cb102-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb102-7"><a href="#cb102-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb102-8"><a href="#cb102-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>a<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb102-9"><a href="#cb102-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>b<span class="op">)</span> <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb102-10"><a href="#cb102-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>c<span class="op">)</span> <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb102-11"><a href="#cb102-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>d<span class="op">)</span> <span class="op">==</span> <span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb102-12"><a href="#cb102-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb102-13"><a href="#cb102-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="cb102-14"><a href="#cb102-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="cb102-15"><a href="#cb102-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="cb102-16"><a href="#cb102-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="cb102-17"><a href="#cb102-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb102-18"><a href="#cb102-18" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> total_bit_offset_of<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info m<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">size_t</span> <span class="op">{</span></span>
<span id="cb102-19"><a href="#cb102-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> offset_of<span class="op">(</span>m<span class="op">)</span> <span class="op">*</span> <span class="dv">8</span> <span class="op">+</span> bit_offset_of<span class="op">(</span>m<span class="op">)</span>;</span>
<span id="cb102-20"><a href="#cb102-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb102-21"><a href="#cb102-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb102-22"><a href="#cb102-22" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>total_bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>a<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb102-23"><a href="#cb102-23" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>total_bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>b<span class="op">)</span> <span class="op">==</span> <span class="dv">10</span><span class="op">)</span>;</span>
<span id="cb102-24"><a href="#cb102-24" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>total_bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>c<span class="op">)</span> <span class="op">==</span> <span class="dv">18</span><span class="op">)</span>;</span>
<span id="cb102-25"><a href="#cb102-25" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>total_bit_offset_of<span class="op">(^</span>Msg<span class="op">::</span>d<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>type_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="cb103"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb103-1"><a href="#cb103-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>meta<span class="op">::</span>type_remove_cvref<span class="op">(</span>type<span class="op">)</span></span></code></pre></div>

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

<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>std<span class="op">::</span>meta<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="cb105"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb105-1"><a href="#cb105-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>meta<span class="op">::</span>type_is_const<span class="op">(</span>type<span class="op">)</span></span></code></pre></div>

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

<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>std<span class="op">::</span>meta<span class="op">::</span>extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>std<span class="op">::</span>meta<span class="op">::</span>substitute<span class="op">(^</span>std<span class="op">::</span>is_const_v, <span class="op">{</span>type<span class="op">}))</span></span>
<span id="cb106-2"><a href="#cb106-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>meta<span class="op">::</span>test_trait<span class="op">(^</span>std<span class="op">::</span>is_const_v, type<span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<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 the current wording in this
revision does. However, we’ve run into a conflict. 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. But this is no longer the case.
Consider <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 is currently actually specified twice in our wording having two
different meanings:</p>
<ol type="1">
<li>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> reflect a type and
checks if that type is a function type. This is the same category of
type trait as the ones mentioned above.</li>
<li>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>.</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). So
what do we do?</p>
<p>Probably the most straightforward choice would be to either prefix or
suffix all of the type traits with
<code class="sourceCode cpp">_type</code>. We think prefix is a little
bit better because it groups all the type traits together and perhaps
make it clearer that the argument(s) must be types. That is: <code class="sourceCode cpp">std<span class="op">::</span>is_pointer<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
because <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_is_pointer<span class="op">(^</span>T<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>is_arithmetic<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
becomes <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_is_arithmetic<span class="op">(^</span>T<span class="op">)</span></code>,
and so forth. The advantage of this approach is that it very likely just
works, also opening the door to making a more general <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_const<span class="op">(</span>e<span class="op">)</span></code>
that checks not just if <code class="sourceCode cpp">e</code> is a
<code class="sourceCode cpp"><span class="kw">const</span></code>-qualified
type but also if it’s a
<code class="sourceCode cpp"><span class="kw">const</span></code>-qualified
object or a
<code class="sourceCode cpp"><span class="kw">const</span></code>-qualified
member, etc. The disadvantage is that the suffixed names would not be
familiar - we’re much more familiar with the name
<code class="sourceCode cpp">is_copy_constructible</code> than we would
be with
<code class="sourceCode cpp">type_is_copy_constructible</code>.</p>
<p>That said, it’s not too much added mental overhead to remember
<code class="sourceCode cpp">type_is_copy_constructible</code> and this
avoids have to remember which type traits have the suffix and which
don’t. Not to mention that <em>many</em> of the type traits read as if
they would accept objects just fine
(e.g. <code class="sourceCode cpp">is_trivially_copyable</code>). So we
propose that simply all the type traits be suffixed with
<code class="sourceCode cpp"><span class="op">*</span>_type</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="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="co">// File &#39;cls.h&#39;</span></span>
<span id="cb107-2"><a href="#cb107-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Cls <span class="op">{</span></span>
<span id="cb107-3"><a href="#cb107-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="cb107-4"><a href="#cb107-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="cb107-5"><a href="#cb107-5" aria-hidden="true" tabindex="-1"></a>      branch_1<span class="op">()</span>;</span>
<span id="cb107-6"><a href="#cb107-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span></span>
<span id="cb107-7"><a href="#cb107-7" aria-hidden="true" tabindex="-1"></a>      branch_2<span class="op">()</span>;</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 class="op">}</span>;</span></code></pre></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_incomplete_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="P3096R1">[<a href="https://wg21.link/p3096r1" role="doc-biblioref">P3096R1</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>
<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="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>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_1" id="pnum_1">7</a></span>
Whitespace characters separating tokens are no longer significant. Each
preprocessing token is converted into a token (5.6). The resulting
tokens constitute a translation unit and are syntactically and
semantically analyzed and translated. <span class="addu">Plainly
constant-evaluated expressions ([expr.const]) appearing outside template
declarations are evaluated in lexical order. Diagnosable rules
(<span>4.1.1 <a href="https://wg21.link/intro.compliance.general">[intro.compliance.general]</a></span>)
that apply to constructs whose syntactic end point occurs lexically
after the syntactic end point of a plainly constant-evaluated expression
X are considered in a context where X has been evaluated.</span> […]</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">8</a></span>
[…] All the required instantiations are performed to produce
instantiation units. <span class="addu">Plainly constant-evaluated
expressions ([expr.const]) appearing in those instantiation units are
evaluated in lexical order as part of the instantiation process.
Diagnosable rules (<span>4.1.1 <a href="https://wg21.link/intro.compliance.general">[intro.compliance.general]</a></span>)
that apply to constructs whose syntactic end point occurs lexically
after the syntactic end point of a plainly constant-evaluated expression
X are considered in a context where X has been evaluated.</span> […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="lex.pptoken-preprocessing-tokens"><span>5.4
<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 <span>5.4 <a href="https://wg21.link/lex.pptoken">[lex.pptoken]</a></span> bullet
(3.2):</p>
<div class="std">
<blockquote>
<p>…</p>
<p>— 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>
<div class="addu">
<p>— 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>.</p>
</div>
<p>…</p>
</blockquote>
</div>
<h3 class="unnumbered" id="lex.operators-operators-and-punctuators"><span>5.12 <a href="https://wg21.link/lex.operators">[lex.operators]</a></span>
Operators and punctuators<a href="#lex.operators-operators-and-punctuators" class="self-link"></a></h3>
<p>Change the grammar for
<code class="sourceCode cpp"><em>operator-or-punctuator</em></code> in
paragraph 1 of <span>5.12 <a href="https://wg21.link/lex.operators">[lex.operators]</a></span> to
include splicer delimiters:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb108"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb108-1"><a href="#cb108-1" aria-hidden="true" tabindex="-1"></a>  <em>operator-or-punctuator</em>: <em>one of</em></span>
<span id="cb108-2"><a href="#cb108-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="cb108-3"><a href="#cb108-3" aria-hidden="true" tabindex="-1"></a>         &lt;:       :&gt;       &lt;%       %&gt;       ;        :        ...</span>
<span id="cb108-4"><a href="#cb108-4" aria-hidden="true" tabindex="-1"></a>         ?        ::       .       .*        -&gt;       -&gt;*      ~</span>
<span id="cb108-5"><a href="#cb108-5" aria-hidden="true" tabindex="-1"></a>         !        +        -        *        /        %        ^        &amp;        |</span>
<span id="cb108-6"><a href="#cb108-6" aria-hidden="true" tabindex="-1"></a>         =        +=       -=       *=       /=       %=       ^=       &amp;=       |=</span>
<span id="cb108-7"><a href="#cb108-7" aria-hidden="true" tabindex="-1"></a>         ==       !=       &lt;        &gt;        &lt;=       &gt;=       &lt;=&gt;      &amp;&amp;       ||</span>
<span id="cb108-8"><a href="#cb108-8" aria-hidden="true" tabindex="-1"></a>         &lt;&lt;       &gt;&gt;       &lt;&lt;=      &gt;&gt;=      ++       --       ,</span>
<span id="cb108-9"><a href="#cb108-9" aria-hidden="true" tabindex="-1"></a>         and      or       xor      not      bitand   bitor    compl</span>
<span id="cb108-10"><a href="#cb108-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.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>Modify paragraph 4.1 to cover splicing of functions:</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(4.1)</a></span>
A function is named by an expression or conversion 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, <span class="addu">or if it is denoted by a
<em>splice-expression</em> ([expr.prim.splice]),</span> unless it is a
pure virtual function and either the expression is not an
<em>id-expression</em> naming the function with an explicitly qualified
name or the expression forms a pointer to member ([expr.unary.op]).</li>
</ul>
</blockquote>
</div>
<p>Modify the first sentence of paragraph 5 to cover splicing of
variables:</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">5</a></span>
A variable is named by an expression if the expression is an
<em>id-expression</em> <span class="addu">or <em>splice-expression</em>
([expr.prim.splice])</span> that denotes it.</li>
</ul>
</blockquote>
</div>
<p>Modify paragraph 6 to cover splicing of structured bindings:</p>
<div class="std">
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">6</a></span>
A structured binding is odr-used if it appears as a
potentially-evaluated expression<span class="addu">, or if a reflection
of it is the operand of a potentially-evaluated
<em>splice-expression</em> ([expr.prim.splice])</span>.</li>
</ul>
</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_6" id="pnum_6">15pre</a></span>
If a class <code class="sourceCode cpp">C</code> is defined in a
translation unit with a call to <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_class</code>,
every definition of that class shall be the result of a call to <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>define_class</code>
such that its respective members are equal in number and have
respectively the same types, alignments, <code class="sourceCode cpp"><span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></code>
attributes (if any), bit-field widths (if any), and specified names (if
any).</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">15</a></span>
<span class="addu">Otherwise, for</span> <span class="rm" style="color: #bf0303"><del>For</del></span> any definable item D with
definitions …</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>Add a bullet to paragraph 3 of <span>6.5.4 <a href="https://wg21.link/basic.lookup.argdep">[basic.lookup.argdep]</a></span>
as follows <span class="ednote" style="color: #0000ff">[ Editor&#39;s note:
this must precede the fundamental type bullet, because
<code class="sourceCode default">meta::info</code> is a fundamental type
]</span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">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>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(3.0)</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>,
its associated set of entities is the singleton containing the function
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_type</code>.</li>
</ul>
</div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(3.1)</a></span>
If <code class="sourceCode cpp">T</code> is a fundamental type, its
associated set of entities is empty.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(3.2)</a></span>
If <code class="sourceCode cpp">T</code> is a class type …</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 <span>6.5.5.1 <a href="https://wg21.link/basic.lookup.qual.general">[basic.lookup.qual.general]</a></span>/1-2
to cover
<code class="sourceCode cpp"><em>splice-name-qualifer</em></code>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">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="rm" style="color: #bf0303"><del>or</del></span>
<code class="sourceCode cpp"><em>computed-type-specifier</em></code><span class="addu">, or
<code class="sourceCode cpp"><em>splice-name-qualifier</em></code></span>
is followed by a
​<code class="sourceCode cpp"><span class="op">::</span></code>​, it shall
designate a namespace, class, enumeration, or dependent type, and the ​::​
is never interpreted as a complete nested-name-specifier.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">2</a></span>
A member-qualified name is the (unique) component name
([expr.prim.id.unqual]), if any, of</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(2.1)</a></span>
an <em>unqualified-id</em> or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(2.2)</a></span>
a <code class="sourceCode cpp"><em>nested-name-specifier</em></code> of
the form <code class="sourceCode cpp"><em>type-name</em> <span class="op">::</span></code>
<span class="rm" style="color: #bf0303"><del>or</del></span><span class="addu">,</span> <code class="sourceCode cpp"><em>namespace-name</em> <span class="op">::</span></code><span class="addu">, or <code class="sourceCode cpp"><em>splice-name-qualifier</em> <span class="op">::</span></code></span></li>
</ul>
<p>in the <em>id-expression</em> of a class member access expression
([expr.ref]). […]</p>
</blockquote>
</div>
<h3 class="unnumbered" id="basic.link-program-and-linkage">[basic.link]
Program and Linkage<a href="#basic.link-program-and-linkage" class="self-link"></a></h3>
<p>Add a bullet to paragraph 4, and renumber accordingly:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">4</a></span>
An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage. All other namespaces
have external linkage. The name of an entity that belongs to a namespace
scope that has not been given internal linkage above and that is the
name of * <span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">(4.1)</a></span>
a variable; or</p>
<p>…</p>
<p>has its linkage determined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(4.7)</a></span>
if the enclosing namespace has internal linkage, the name has internal
linkage;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">(4.8)</a></span>
otherwise, if the declaration of the name is attached to a named module
([module.unit]) and is not exported ([module.interface]), the name has
module linkage;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">(4.9)</a></span>
<span class="addu">otherwise, if the declaration is a variable having
<em>consteval-only type</em> ([basic.types.general]), or is of a class
template specialization type having a <em>consteval-only type</em> as a
non-type template argument, the name has internal linkage.</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">(4.10)</a></span>
otherwise, the name has external linkage.</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_22" id="pnum_22">9</a></span>
Arithmetic types (6.8.2), enumeration types, pointer types,
pointer-to-member types (6.8.4), <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 (6.8.5) versions of these types are collectively called
scalar types.</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_23" id="pnum_23">*</a></span>
A <em>consteval-only type</em> is one of the following:</p>
<ul>
<li><code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
or</li>
<li>a pointer or reference to a consteval-only type, or</li>
<li>an (possibly multi-dimensional) array of a consteval-only type,
or</li>
<li>a pointer-to-member type to a class
<code class="sourceCode cpp">C</code> of type
<code class="sourceCode cpp">M</code> where either
<code class="sourceCode cpp">C</code> or
<code class="sourceCode cpp">M</code> is a consteval-only type, or</li>
<li>a function type with a consteval-only return type or a
consteval-only parameter type, or</li>
<li>a class type with a consteval-only base class type or consteval-only
non-static data member type.</li>
</ul>
<p>An object of consteval-only type shall either end its lifetime during
the evaluation of a manifestly constant-evaluated expression or
conversion (<span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span>), or be a
constexpr variable that is not odr-used (<span>6.3 <a href="https://wg21.link/basic.def.odr">[basic.def.odr]</a></span>).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">*</a></span>
Consteval-only types may not be used to declare a static data member of
a class having module or external linkage. Furthermore, specializations
of a class template having a non-type template argument of
consteval-only type may not be used to declare a static data member of a
class having module or external linkage.</p>
</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 a new paragraph 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>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">*</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> and represents a language element such
as a type, a value, an object, a non-static data member, etc. An
expression convertible to <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
is said to <em>reflect</em> the language element represented by the
resulting value; the language element is said to be <em>reflected
by</em> the expression. <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>
shall be equal to <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span><span class="dt">void</span><span class="op">*)</span></code>.
<span class="note"><span>[ <em>Note 1:</em> </span>Reflections are only
meaningful during translation. The notion of consteval-only types (see
<span>6.8.1 <a href="https://wg21.link/basic.types.general">[basic.types.general]</a></span>)
exists to diagnose attempts at using such values outside the translation
process.<span> — <em>end note</em> ]</span></span></p>
</div>
</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>Change the grammar for
<code class="sourceCode cpp"><em>primary-expression</em></code> in
<span>7.5 <a href="https://wg21.link/expr.prim">[expr.prim]</a></span>
as follows:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb109"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb109-1"><a href="#cb109-1" aria-hidden="true" tabindex="-1"></a>  <em>primary-expression</em>:</span>
<span id="cb109-2"><a href="#cb109-2" aria-hidden="true" tabindex="-1"></a>     <em>literal</em></span>
<span id="cb109-3"><a href="#cb109-3" aria-hidden="true" tabindex="-1"></a>     this</span>
<span id="cb109-4"><a href="#cb109-4" aria-hidden="true" tabindex="-1"></a>     ( <em>expression</em> )</span>
<span id="cb109-5"><a href="#cb109-5" aria-hidden="true" tabindex="-1"></a>     <em>id-expression</em></span>
<span id="cb109-6"><a href="#cb109-6" aria-hidden="true" tabindex="-1"></a>     <em>lambda-expression</em></span>
<span id="cb109-7"><a href="#cb109-7" aria-hidden="true" tabindex="-1"></a>     <em>fold-expression</em></span>
<span id="cb109-8"><a href="#cb109-8" aria-hidden="true" tabindex="-1"></a>     <em>requires-expression</em></span>
<span id="cb109-9"><a href="#cb109-9" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-expression</em></span></span>
<span id="cb109-10"><a href="#cb109-10" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb109-11"><a href="#cb109-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-expression</em></span></span>
<span id="cb109-12"><a href="#cb109-12" aria-hidden="true" tabindex="-1"></a><span class="va">+    [: <em>constant-expression</em> :]</span></span>
<span id="cb109-13"><a href="#cb109-13" aria-hidden="true" tabindex="-1"></a><span class="va">+    template[: <em>constant-expression</em> :] &lt; <em>template-argument-list</em><sub><em>opt</em></sub> &gt;</span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.prim.id.qual-qualified-names"><span>7.5.4.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>Add a production to 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="cb110"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb110-1"><a href="#cb110-1" aria-hidden="true" tabindex="-1"></a>  <em>nested-name-specifier</em>:</span>
<span id="cb110-2"><a href="#cb110-2" aria-hidden="true" tabindex="-1"></a>      ::</span>
<span id="cb110-3"><a href="#cb110-3" aria-hidden="true" tabindex="-1"></a>      <em>type-name</em> ::</span>
<span id="cb110-4"><a href="#cb110-4" aria-hidden="true" tabindex="-1"></a>      <em>namespace-name</em> ::</span>
<span id="cb110-5"><a href="#cb110-5" aria-hidden="true" tabindex="-1"></a>      <em>computed-type-specifier</em> ::</span>
<span id="cb110-6"><a href="#cb110-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-name-qualifier</em> ::</span></span>
<span id="cb110-7"><a href="#cb110-7" aria-hidden="true" tabindex="-1"></a>      <em>nested-name-specifier</em> <em>identifier</em> ::</span>
<span id="cb110-8"><a href="#cb110-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="cb110-9"><a href="#cb110-9" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb110-10"><a href="#cb110-10" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-name-qualifier</em>:</span></span>
<span id="cb110-11"><a href="#cb110-11" aria-hidden="true" tabindex="-1"></a><span class="va">+     [: <em>constant-expression</em> :]</span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Extend <span>7.5.4.3 <a href="https://wg21.link/expr.prim.id.qual">[expr.prim.id.qual]</a></span>/1
to also cover splices:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">1</a></span>
The component names of a
<code class="sourceCode cpp"><em>qualified-id</em></code> are those of
its <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
and <code class="sourceCode cpp"><em>unqualified-id</em></code>. The
component names of a
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> are
its <code class="sourceCode cpp"><em>identifier</em></code> (if any) and
those of its <code class="sourceCode cpp"><em>type-name</em></code>,
<code class="sourceCode cpp"><em>namespace-name</em></code>,
<code class="sourceCode cpp"><em>simple-template-id</em></code>, <span class="rm" style="color: #bf0303"><del>and/or</del></span>
<code class="sourceCode cpp"><em>nested-name-specifier</em></code><span class="addu">, and/or the
<code class="sourceCode cpp"><em>type-name</em></code> or
<code class="sourceCode cpp"><em>namespace-name</em></code> of the
entity reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code> of its
<code class="sourceCode cpp"><em>splice-name-qualifier</em></code>. For
a <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
having a
<code class="sourceCode cpp"><em>splice-name-qualifier</em></code> with
a <code class="sourceCode cpp"><em>constant-expression</em></code> that
reflects the global namespace, the component names are the same as for
<code class="sourceCode cpp"><span class="op">::</span></code>. The
<code class="sourceCode cpp"><em>constant-expression</em></code> of a
<code class="sourceCode cpp"><em>splice-name-qualifier</em></code> shall
be a reflection of either a
<code class="sourceCode cpp"><em>type-name</em></code>,
<code class="sourceCode cpp"><em>namespace-name</em></code>, or the
global namespace</span>.</p>
</blockquote>
</div>
<p>Extend <span>7.5.4.3 <a href="https://wg21.link/expr.prim.id.qual">[expr.prim.id.qual]</a></span>/3
to also cover splices:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">3</a></span>
The <code class="sourceCode cpp"><em>nested-name-specifier</em></code>
<code class="sourceCode cpp">​<span class="op">::</span></code>​ nominates
the global namespace. A
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> with
a <code class="sourceCode cpp"><em>computed-type-specifier</em></code>
nominates the type denoted by the
<code class="sourceCode cpp"><em>computed-type-specifier</em></code>,
which shall be a class or enumeration type. <span class="addu">A
<code class="sourceCode cpp"><em>nested-name-specifier</em></code> with
a <code class="sourceCode cpp"><em>splice-name-qualifier</em></code>
nominates the entity reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code> of the
<code class="sourceCode cpp"><em>splice-name-qualifier</em></code>.</span>
If a nested-name-specifier N is declarative and has a simple-template-id
with a template argument list A that involves a template parameter, let
T be the template nominated by N without A. T shall be a class
template.</p>
<p>…</p>
</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.7 <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>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">1</a></span>
For a <code class="sourceCode cpp"><em>primary-expression</em></code> of
the form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
or <code class="sourceCode cpp"><span class="kw">template</span><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span>  <span class="op">&lt;</span> <em>template-argument-list</em><sub><em>opt</em></sub> <span class="op">&gt;</span></code>
the <code class="sourceCode cpp"><em>constant-expression</em></code>
shall be a converted constant expression (<span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span>) 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_29" id="pnum_29">2</a></span>
For a <code class="sourceCode cpp"><em>splice-expression</em></code> of
the form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
where the converted
<code class="sourceCode cpp"><em>constant-expression</em></code>
evaluates to a reflection for an object, a function which is not a
constructor or destructor, a non-static data member, or an enumerator,
or a structured binding, the expression is an lvalue denoting the
reflected entity. If the converted
<code class="sourceCode cpp"><em>constant-expression</em></code>
evaluates to a reflection for a variable or a structured binding, the
expression is an lvalue denoting the object designated by the reflected
entity. <span class="note"><span>[ <em>Note 1:</em> </span>Access
checking of class members occurs during name lookup, and therefore does
not pertain to splicing.<span> — <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_30" id="pnum_30">3</a></span>
Otherwise, for a
<code class="sourceCode cpp"><em>splice-expression</em></code> of the
form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
the converted
<code class="sourceCode cpp"><em>constant-expression</em></code> shall
evaluate to a reflection of a value, and the expression shall be a
prvalue whose evaluation computes the reflected value.</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="cb111"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb111-1"><a href="#cb111-1" aria-hidden="true" tabindex="-1"></a>[1]{.pnum} Postfix expressions group left-to-right.</span>
<span id="cb111-2"><a href="#cb111-2" aria-hidden="true" tabindex="-1"></a>  <em>postfix-expression</em>:</span>
<span id="cb111-3"><a href="#cb111-3" aria-hidden="true" tabindex="-1"></a>    ...</span>
<span id="cb111-4"><a href="#cb111-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="cb111-5"><a href="#cb111-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>postfix-expression</em> . <em>template</em><sub><em>opt</em></sub> <em>splice-expression</em></span></span>
<span id="cb111-6"><a href="#cb111-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="cb111-7"><a href="#cb111-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>postfix-expression</em> -&gt; <em>template</em><sub><em>opt</em></sub> <em>splice-expression</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="expr.ref-class-member-access">[expr.ref]
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_31" id="pnum_31">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 template, and then followed by an
<em>id-expression</em> <span class="addu">or a
<em>splice-expression</em></span>, is a postfix expression. <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
<em>id-expression</em> <span class="addu">or
<em>splice-expression</em></span> is a qualified-id.<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_32" id="pnum_32">2</a></span>
For the first option, if the <span class="addu">dot 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>
naming</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></span>
names a non-static data member, the first expression shall be a glvalue.
For the second option (arrow), the first expression shall be a prvalue
having pointer type. The expression E1-&gt;E2 is converted to the
equivalent form (*(E1)).E2; the remainder of [expr.ref] will address
only the first option (dot).</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_33" id="pnum_33">3</a></span>
The postfix expression before the dot is evaluated 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_34" id="pnum_34">4</a></span>
Abbreviating <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>postfix-expression</em></code></span>.<span><code class="sourceCode default"><em>id-expression</em></code></span></del></span>
<span class="addu"><code class="sourceCode cpp"><em>postfix-expression</em><span class="op">.</span>EXPR</code>,
where <code class="sourceCode cpp">EXPR</code> is the
<code class="sourceCode cpp"><em>id-expression</em></code> or
<code class="sourceCode cpp"><em>splice-expression</em></code> following
the dot,</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>. If the
object expression is of scalar type,
<code class="sourceCode cpp">E2</code> shall name the pseudo-destructor
of that same type (ignoring cv-qualifications) and
<code class="sourceCode cpp">E1<span class="op">.</span>E2</code> is a
prvalue of type “function of () returning
<code class="sourceCode cpp"><span class="dt">void</span></code>”.</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>Change <span>7.6.2.1 <a href="https://wg21.link/expr.unary.general">[expr.unary.general]</a></span>
paragraph 1 to add productions for the new operator:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_35" id="pnum_35">1</a></span>
Expressions with unary operators group right-to-left.</p>
<div>
<div class="sourceCode" id="cb112"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb112-1"><a href="#cb112-1" aria-hidden="true" tabindex="-1"></a>  <em>unary-expression</em>:</span>
<span id="cb112-2"><a href="#cb112-2" aria-hidden="true" tabindex="-1"></a>     ...</span>
<span id="cb112-3"><a href="#cb112-3" aria-hidden="true" tabindex="-1"></a>     <em>delete-expression</em></span>
<span id="cb112-4"><a href="#cb112-4" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>reflect-expression</em></span></span>
<span id="cb112-5"><a href="#cb112-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb112-6"><a href="#cb112-6" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>reflect-expression</em>:</span></span>
<span id="cb112-7"><a href="#cb112-7" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ ::</span></span>
<span id="cb112-8"><a href="#cb112-8" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ <em>namespace-name</em></span></span>
<span id="cb112-9"><a href="#cb112-9" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>template-name</em></span></span>
<span id="cb112-10"><a href="#cb112-10" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>concept-name</em></span></span>
<span id="cb112-11"><a href="#cb112-11" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ <em>type-id</em></span></span>
<span id="cb112-12"><a href="#cb112-12" aria-hidden="true" tabindex="-1"></a><span class="va">+    ^ <em>id-expression</em></span></span></code></pre></div>
</div>
</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>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_36" id="pnum_36">1</a></span>
The unary <code class="sourceCode cpp"><span class="op">^</span></code>
operator (called <em>the reflection operator</em>) produces a prvalue —
called a <em>reflection</em> — whose type is the reflection type (i.e.,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>).
That reflection represents its operand.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_37" id="pnum_37">2</a></span>
Every value of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
is either a reflection of some entity (or description thereof) or a
<em>null reflection value</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_38" id="pnum_38">3</a></span>
A <em>reflect-expression</em> is parsed as the longest possible sequence
of tokens that could syntactically form a
<em>reflect-expression</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_39" id="pnum_39">4</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb113"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb113-1"><a href="#cb113-1" aria-hidden="true" tabindex="-1"></a>static_assert(is_type(^int()));    // ^ applies to the type-id &quot;int()&quot;</span>
<span id="cb113-2"><a href="#cb113-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb113-3"><a href="#cb113-3" aria-hidden="true" tabindex="-1"></a>template&lt;bool&gt; struct X {};</span>
<span id="cb113-4"><a href="#cb113-4" aria-hidden="true" tabindex="-1"></a>bool operator&lt;(std::meta::info, X&lt;false&gt;);</span>
<span id="cb113-5"><a href="#cb113-5" aria-hidden="true" tabindex="-1"></a>consteval void g(std::meta::info r, X&lt;false&gt; xv) {</span>
<span id="cb113-6"><a href="#cb113-6" aria-hidden="true" tabindex="-1"></a>  if (r == ^int &amp;&amp; true);    // error: ^ applies to the type-id &quot;int&amp;&amp;&quot;</span>
<span id="cb113-7"><a href="#cb113-7" aria-hidden="true" tabindex="-1"></a>  if (r == ^int &amp; true);     // error: ^ applies to the type-id &quot;int&amp;&quot;</span>
<span id="cb113-8"><a href="#cb113-8" aria-hidden="true" tabindex="-1"></a>  if (r == (^int) &amp;&amp; true);  // OK</span>
<span id="cb113-9"><a href="#cb113-9" aria-hidden="true" tabindex="-1"></a>  if (^X &lt; xv);       // error: &lt; starts template argument list</span>
<span id="cb113-10"><a href="#cb113-10" aria-hidden="true" tabindex="-1"></a>  if ((^X) &lt; xv);     // OK</span>
<span id="cb113-11"><a href="#cb113-11" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb113-12"><a href="#cb113-12" 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_40" id="pnum_40">5</a></span>
When applied to
<code class="sourceCode cpp"><span class="op">::</span></code>, the
reflection operator produces a reflection for the global namespace. When
applied to a
<code class="sourceCode cpp"><em>namespace-name</em></code>, the
reflection operator produces a reflection for the indicated namespace or
namespace alias.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_41" id="pnum_41">6</a></span>
When applied to a
<code class="sourceCode cpp"><em>template-name</em></code>, the
reflection operator produces a reflection for the indicated
template.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_42" id="pnum_42">7</a></span>
When applied to a
<code class="sourceCode cpp"><em>concept-name</em></code>, the
reflection operator produces a reflection for the indicated concept.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_43" id="pnum_43">8</a></span>
When applied to a <code class="sourceCode cpp"><em>type-id</em></code>,
the reflection operator produces a reflection for the indicated type or
type alias.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_44" id="pnum_44">9</a></span>
When applied to an lvalue
<code class="sourceCode cpp"><em>id-expression</em></code> (<span>7.5.4
<a href="https://wg21.link/expr.prim.id">[expr.prim.id]</a></span>), the
reflection operator produces a reflection of the variable, function,
enumerator constant, or non-static member designated by the operand. The
<code class="sourceCode cpp"><em>id-expression</em></code> is not
evaluated.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_45" id="pnum_45">(9.1)</a></span>
If this <code class="sourceCode cpp"><em>id-expression</em></code> names
an overload set <code class="sourceCode cpp">S</code>, and if the
assignment of <code class="sourceCode cpp">S</code> to an invented
variable of type <code class="sourceCode cpp"><span class="kw">const</span> <span class="kw">auto</span></code>
(<span>9.2.9.7.2 <a href="https://wg21.link/dcl.type.auto.deduct">[dcl.type.auto.deduct]</a></span>)
would select a unique candidate function
<code class="sourceCode cpp">F</code> from
<code class="sourceCode cpp">S</code>, the result is a reflection of
<code class="sourceCode cpp">F</code>. Otherwise, the expression
<code class="sourceCode cpp"><span class="op">^</span>S</code> is
ill-formed.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_46" id="pnum_46">10</a></span>
When applied to a prvalue
<code class="sourceCode cpp"><em>id-expression</em></code>, the
reflection operator produces a reflection of the value computed by the
operand <span class="note"><span>[ <em>Note 1:</em> </span>An
<code class="sourceCode cpp"><em>id-expression</em></code> naming a
non-type template parameter of non-class and non-reference type is a
prvalue.<span> — <em>end note</em> ]</span></span></p>
<div class="example">
<span>[ <em>Example 2:</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">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="cb114-2"><a href="#cb114-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="cb114-3"><a href="#cb114-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="cb114-4"><a href="#cb114-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb114-5"><a href="#cb114-5" 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>fn<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span>;     <span class="co">// OK</span></span>
<span id="cb114-6"><a href="#cb114-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> S <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: cannot reflect an overload set</span></span>
<span id="cb114-7"><a href="#cb114-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb114-8"><a href="#cb114-8" 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>std<span class="op">::</span>vector;  <span class="co">// OK</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>Extend <span>7.6.10 <a href="https://wg21.link/expr.eq">[expr.eq]</a></span>/2 to also handle
`std::meta::info:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_47" id="pnum_47">2</a></span>
The converted operands shall have arithmetic, enumeration, pointer, or
pointer-to-member type, or <span class="rm" style="color: #bf0303"><del>type</del></span> <span class="addu">types
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
or</span> <code class="sourceCode cpp">std​<span class="op">::</span>​nullptr_t</code>.
The operators
<code class="sourceCode cpp"><span class="op">==</span></code> and
<code class="sourceCode cpp"><span class="op">!=</span></code> both
yield <code class="sourceCode cpp"><span class="kw">true</span></code>
or <code class="sourceCode cpp"><span class="kw">false</span></code>,
i.e., a result of type
<code class="sourceCode cpp"><span class="dt">bool</span></code>. In
each case below, the operands shall have the same type after the
specified conversions have been applied.</p>
</blockquote>
</div>
<p>Add a new paragraph between <span>7.6.10 <a href="https://wg21.link/expr.eq">[expr.eq]</a></span>/5 and /6:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_48" id="pnum_48">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_49" id="pnum_49">*</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_50" id="pnum_50">(*.1)</a></span>
If both operands are null reflection values, then they compare
equal.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_51" id="pnum_51">(*.2)</a></span>
Otherwise, if one operand is a null reflection value, then they compare
unequal.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_52" id="pnum_52">(*.3)</a></span>
Otherwise, if one operand is a reflection of a namespace alias, alias
template, or type alias and the other operand is not a reflection of the
same kind of alias, they compare unequal. <span class="note"><span>[ <em>Note 1:</em> </span>A reflection of a type and
a reflection of an alias to that same type do not compare equal.<span>
— <em>end note</em> ]</span></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_53" id="pnum_53">(*.4)</a></span>
Otherwise, if both operands are reflections of a namespace alias, alias
template, or type alias, then they compare equal if their reflected
aliases share the same name, are declared within the same enclosing
scope, and alias the same underlying entity.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_54" id="pnum_54">(*.5)</a></span>
Otherwise, if neither operand is a reflection of a value, then they
compare equal if they are reflections of the same entity.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_55" id="pnum_55">(*.6)</a></span>
Otherwise, if one operand is a reflection of a value and the other is
not, then they compare unequal.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_56" id="pnum_56">(*.7)</a></span>
Otherwise, if both operands are reflections of values, then they compare
equal if and only if the reflected values are
<em>template-argument-equivalent</em> (<span>13.6 <a href="https://wg21.link/temp.type">[temp.type]</a></span>).</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_57" id="pnum_57">(*.8)</a></span>
Otherwise the result is unspecified.</li>
</ul>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_58" id="pnum_58">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 new paragraph after the definition of <em>manifestly
constant-evaluated</em> <span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span>/20:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_59" id="pnum_59">21</a></span>
An expression or conversion is <em>plainly constant-evaluated</em> if it
is:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_60" id="pnum_60">(21.1)</a></span>
a <code class="sourceCode cpp"><em>constant-expression</em></code>,
or</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_61" id="pnum_61">(21.2)</a></span>
the condition of a constexpr if statement (<span>8.5.2 <a href="https://wg21.link/stmt.if">[stmt.if]</a></span>),</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_62" id="pnum_62">(21.3)</a></span>
the initializer of a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
(<span>9.2.6 <a href="https://wg21.link/dcl.constexpr">[dcl.constexpr]</a></span>) or
<code class="sourceCode cpp"><span class="kw">constinit</span></code>
(<span>9.2.7 <a href="https://wg21.link/dcl.constinit">[dcl.constinit]</a></span>)
variable, or</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_63" id="pnum_63">(21.4)</a></span>
an immediate invocation, unless it</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_64" id="pnum_64">(21.4.1)</a></span>
results from the substitution of template parameters in a concept-id
(<span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span>), a
<code class="sourceCode cpp"><em>requires-expression</em></code>
(<span>7.5.7 <a href="https://wg21.link/expr.prim.req">[expr.prim.req]</a></span>), or
during template argument deduction (<span>13.10.3 <a href="https://wg21.link/temp.deduct">[temp.deduct]</a></span>), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_65" id="pnum_65">(21.4.2)</a></span>
is a manifestly constant-evaluated initializer of a variable that is
neither
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
(<span>9.2.6 <a href="https://wg21.link/dcl.constexpr">[dcl.constexpr]</a></span>) nor
<code class="sourceCode cpp"><span class="kw">constinit</span></code>
(<span>9.2.7 <a href="https://wg21.link/dcl.constinit">[dcl.constinit]</a></span>).</li>
</ul></li>
</ul>
</div>
</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>Introduce the term “type alias” to <span>9.2.4 <a href="https://wg21.link/dcl.typedef">[dcl.typedef]</a></span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_66" id="pnum_66">1</a></span>
[…] A name declared with the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier becomes a typedef-name. A typedef-name names the type
associated with the identifier ([dcl.decl]) or simple-template-id
([temp.pre]); a typedef-name is thus a synonym for another type. A
typedef-name does not introduce a new type the way a class declaration
([class.name]) or enum declaration ([dcl.enum]) does.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_67" id="pnum_67">2</a></span>
A <em>typedef-name</em> can also be introduced by an alias-declaration.
The identifier following the using keyword is not looked up; it becomes
a typedef-name and the optional attribute-specifier-seq following the
identifier appertains to that typedef-name. Such a typedef-name has the
same semantics as if it were introduced by the typedef specifier. In
particular, it does not define a new type.</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_68" id="pnum_68">*</a></span>
A <em>type alias</em> is either a name declared with the
<code class="sourceCode cpp"><span class="kw">typedef</span></code>
specifier or a name introduced by an <em>alias-declaration</em>.</p>
</div>
</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="cb115"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb115-1"><a href="#cb115-1" aria-hidden="true" tabindex="-1"></a>  <em>computed-type-specifier</em>:</span>
<span id="cb115-2"><a href="#cb115-2" aria-hidden="true" tabindex="-1"></a>     <em>decltype-specifier</em></span>
<span id="cb115-3"><a href="#cb115-3" aria-hidden="true" tabindex="-1"></a>     <em>pack-index-specifier</em></span>
<span id="cb115-4"><a href="#cb115-4" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-type-specifier</em></span></span>
<span id="cb115-5"><a href="#cb115-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb115-6"><a href="#cb115-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb115-7"><a href="#cb115-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-enum-name</em>:</span></span>
<span id="cb115-8"><a href="#cb115-8" aria-hidden="true" tabindex="-1"></a><span class="va">+    [: <em>constant-expression</em> :]</span></span>
<span id="cb115-9"><a href="#cb115-9" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb115-10"><a href="#cb115-10" aria-hidden="true" tabindex="-1"></a>  <em>using-enum-declarator</em>:</span>
<span id="cb115-11"><a href="#cb115-11" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>identifier</em></span>
<span id="cb115-12"><a href="#cb115-12" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>simple-template-id</em></span>
<span id="cb115-13"><a href="#cb115-13" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-enum-name</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.type.splice-type-splicing">9.2.9*
[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">
<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><span class="va">+  <em>splice-type-specifier</em></span></span>
<span id="cb116-2"><a href="#cb116-2" aria-hidden="true" tabindex="-1"></a><span class="va">+      typename [: <em>constant-expression</em> :]</span></span>
<span id="cb116-3"><a href="#cb116-3" aria-hidden="true" tabindex="-1"></a><span class="va">+      [: <em>constant-expression</em> :]</span></span></code></pre></div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_69" id="pnum_69">1</a></span>
The <code class="sourceCode cpp"><em>constant-expression</em></code>
shall be a converted constant expression (<span>7.7 <a href="https://wg21.link/expr.const">[expr.const]</a></span>) 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_70" id="pnum_70">2</a></span>
The form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
shall only be parsed as a
<code class="sourceCode cpp"><em>splice-type-specifier</em></code>
within a <em>type-only context</em> (<span>13.8.1 <a href="https://wg21.link/temp.res.general">[temp.res.general]</a></span>).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_71" id="pnum_71">3</a></span>
The <code class="sourceCode cpp"><em>constant-expression</em></code>
shall evaluate to a reflection of a type, and the type designated by the
<code class="sourceCode cpp"><em>splice-type-specifier</em></code> is
the same as the type reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.init.general-initializers-general"><span>9.4.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-9 of <span>9.4.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_72" id="pnum_72">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_73" id="pnum_73">(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 initialied to a null reflection value;</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_74" id="pnum_74">(6.1)</a></span>
if <code class="sourceCode cpp">T</code> is a scalar type
([basic.types.general]), 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_75" id="pnum_75">(6.2)</a></span>
[…]</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_76" id="pnum_76">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_77" id="pnum_77">(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_78" id="pnum_78">(7.2)</a></span>
If T is an array type, […]</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_79" id="pnum_79">(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_80" id="pnum_80">(7.3)</a></span>
Otherwise, no initialization is performed.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_81" id="pnum_81">8</a></span>
A class type <code class="sourceCode cpp">T</code> is
<em>const-default-constructible</em> if <span class="addu"><code class="sourceCode cpp">T</code> is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,</span>
default-initialization of <code class="sourceCode cpp">T</code> would
invoke a user-provided constructor of T (not inherited from a base
class)<span class="addu">,</span> or if</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_82" id="pnum_82">(8.1)</a></span>
[…]</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_83" id="pnum_83">9</a></span>
To value-initialize an object of type T means: […]</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>Add a bullet to paragraph 9 of <span>9.3.4.6 <a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span> to allow for
reflections of abominable function types:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_84" id="pnum_84">9</a></span>
A function type with a <em>cv-qualifier-seq</em> or a
<em>ref-qualifier</em> (including a type named by <em>typedef-name</em>
([dcl.typedef], [temp.param])) shall appear only as:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_85" id="pnum_85">(9.1)</a></span>
the function type for a non-static member function,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_86" id="pnum_86">(9.2)</a></span>
…</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_87" id="pnum_87">(9.5)</a></span>
the <em>type-id</em> of a <em>template-argument</em> for a
<em>type-parameter</em> ([temp.arg.type])<span class="rm" style="color: #bf0303"><del>.</del></span><span class="addu">,</span></li>
</ul>
<div class="addu">
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_88" id="pnum_88">(9.6)</a></span>
the operand of a <em>reflect-expression</em> ([expr.reflect]).</li>
</ul>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.fct.def.delete-deleted-definitions"><span>9.5.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.5.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_89" id="pnum_89">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
the reflection operator</span>, is ill-formed.</p>
</blockquote>
</div>
<h3 class="unnumbered" id="enum.udecl-the-using-enum-declaration"><span>9.7.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="cb117"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb117-1"><a href="#cb117-1" aria-hidden="true" tabindex="-1"></a>  <em>using-enum-declaration</em>:</span>
<span id="cb117-2"><a href="#cb117-2" aria-hidden="true" tabindex="-1"></a>     using enum <em>using-enum-declarator</em> ;</span>
<span id="cb117-3"><a href="#cb117-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb117-4"><a href="#cb117-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-enum-name</em>:</span></span>
<span id="cb117-5"><a href="#cb117-5" aria-hidden="true" tabindex="-1"></a><span class="va">+    [: <em>constant-expression</em> :]</span></span>
<span id="cb117-6"><a href="#cb117-6" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb117-7"><a href="#cb117-7" aria-hidden="true" tabindex="-1"></a>  <em>using-enum-declarator</em>:</span>
<span id="cb117-8"><a href="#cb117-8" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>identifier</em></span>
<span id="cb117-9"><a href="#cb117-9" aria-hidden="true" tabindex="-1"></a>     <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>simple-template-id</em></span>
<span id="cb117-10"><a href="#cb117-10" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-enum-name</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Modify paragraph 1 of <span>9.7.2 <a href="https://wg21.link/enum.udecl">[enum.udecl]</a></span> as
follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_90" id="pnum_90">1</a></span>
A <code class="sourceCode cpp"><em>using-enum-declarator</em></code>
<span class="addu">not consisting of a
<code class="sourceCode cpp"><em>splice-enum-name</em></code></span>
names the set of declarations found by lookup (<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>)
for the
<code class="sourceCode cpp"><em>using-enum-declarator</em></code>.
<span class="addu">A
<code class="sourceCode cpp"><em>using-enum-declarator</em></code>
containing a
<code class="sourceCode cpp"><em>splice-enum-name</em></code> names the
entity reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code>.</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.udir-using-namespace-directive"><span>9.8.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>Modify the grammar for
<code class="sourceCode cpp"><em>using-directive</em></code> as
follows:</p>
<div class="std">
<blockquote>
<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><span class="va">+ <em>splice-namespace-name</em>:</span></span>
<span id="cb118-2"><a href="#cb118-2" aria-hidden="true" tabindex="-1"></a><span class="va">+    [: <em>constant-expression</em> :]</span></span>
<span id="cb118-3"><a href="#cb118-3" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb118-4"><a href="#cb118-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>namespace-declarator</em>:</span></span>
<span id="cb118-5"><a href="#cb118-5" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>nested-name-specifier</em><sub><em>opt</em></sub> <em>namespace-name</em></span></span>
<span id="cb118-6"><a href="#cb118-6" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>splice-namespace-name</em></span></span>
<span id="cb118-7"><a href="#cb118-7" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb118-8"><a href="#cb118-8" aria-hidden="true" tabindex="-1"></a>  <em>using-directive</em>:</span>
<span id="cb118-9"><a href="#cb118-9" aria-hidden="true" tabindex="-1"></a><span class="st">-    <em>attribute-specifier-seq</em><sub><em>opt</em></sub> using namespace $nested-name-specifier<sub><em>opt</em></sub> <em>namespace-name</em></span></span>
<span id="cb118-10"><a href="#cb118-10" aria-hidden="true" tabindex="-1"></a><span class="va">+    <em>attribute-specifier-seq</em><sub><em>opt</em></sub> using namespace <em>namespace-declarator</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add the following to paragraph 1 of <span>9.8.4 <a href="https://wg21.link/namespace.udir">[namespace.udir]</a></span>,
prior to the note:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_91" id="pnum_91">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. <span class="addu">A
<code class="sourceCode cpp"><em>namespace-declarator</em></code> not
consisting of a
<code class="sourceCode cpp"><em>splice-namespace-name</em></code>
nominates the namespace found by lookup (<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>)
and shall not contain a dependent
<code class="sourceCode cpp"><em>nested-name-specifier</em></code>. A
<code class="sourceCode cpp"><em>namespace-declarator</em></code>
consisting of a
<code class="sourceCode cpp"><em>splice-namespace-name</em></code> shall
contain a non-dependent
<code class="sourceCode cpp"><em>constant-expression</em></code> that
reflects a namespace or namespace alias, and nominates the entity
reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code>.</span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="dcl.attr.grammar-attribute-syntax-and-semantics"><span>9.12.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="cb119"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb119-1"><a href="#cb119-1" aria-hidden="true" tabindex="-1"></a>  <em>attribute-specifier</em>:</span>
<span id="cb119-2"><a href="#cb119-2" aria-hidden="true" tabindex="-1"></a>     [ [ <em>attribute-using-prefix</em><sub><em>opt</em></sub> <em>attribute-list</em> ] ]</span>
<span id="cb119-3"><a href="#cb119-3" aria-hidden="true" tabindex="-1"></a><span class="va">+    [ [ using <em>attribute-namespace</em> :] ]</span></span>
<span id="cb119-4"><a href="#cb119-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="cb120"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb120-1"><a href="#cb120-1" aria-hidden="true" tabindex="-1"></a>  <em>balanced-token</em> :</span>
<span id="cb120-2"><a href="#cb120-2" aria-hidden="true" tabindex="-1"></a>      ( <em>balanced-token-seq</em><sub><em>opt</em></sub> )</span>
<span id="cb120-3"><a href="#cb120-3" aria-hidden="true" tabindex="-1"></a>      [ <em>balanced-token-seq</em><sub><em>opt</em></sub> ]</span>
<span id="cb120-4"><a href="#cb120-4" aria-hidden="true" tabindex="-1"></a>      { <em>balanced-token-seq</em><sub><em>opt</em></sub> }</span>
<span id="cb120-5"><a href="#cb120-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="cb120-6"><a href="#cb120-6" aria-hidden="true" tabindex="-1"></a><span class="va">+     [: <em>balanced-token-seq</em><sub><em>opt</em></sub> :]</span></span>
<span id="cb120-7"><a href="#cb120-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.12.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_92" id="pnum_92">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="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_93" id="pnum_93">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="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">bool</span> <span class="kw">operator</span><span class="op">==(</span>T, T<span class="op">)</span>;</span>
<span id="cb121-2"><a href="#cb121-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 the last sentence of paragraph 4 to disallow splicing concepts
in template parameter declarations.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_94" id="pnum_94">4</a></span>
… The concept designated by a type-constraint shall be a type concept
([temp.concept]) <span class="addu">that does not consist of a
<code class="sourceCode cpp"><em>splice-template-name</em></code></span>.</p>
</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>Modify the grammars for
<code class="sourceCode cpp"><em>template-id</em></code> and
<code class="sourceCode cpp"><em>template-argument</em></code> as
follows:</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><span class="va">+ <em>splice-template-name</em>:</span></span>
<span id="cb122-2"><a href="#cb122-2" aria-hidden="true" tabindex="-1"></a><span class="va">+     template [: constant-expression :]</span></span>
<span id="cb122-3"><a href="#cb122-3" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb122-4"><a href="#cb122-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>splice-template-argument</em>:</span></span>
<span id="cb122-5"><a href="#cb122-5" aria-hidden="true" tabindex="-1"></a><span class="va">+     [: constant-expression :]</span></span>
<span id="cb122-6"><a href="#cb122-6" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb122-7"><a href="#cb122-7" aria-hidden="true" tabindex="-1"></a>  <em>template-name</em>:</span>
<span id="cb122-8"><a href="#cb122-8" aria-hidden="true" tabindex="-1"></a>      identifier</span>
<span id="cb122-9"><a href="#cb122-9" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-template-name</em></span></span>
<span id="cb122-10"><a href="#cb122-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb122-11"><a href="#cb122-11" aria-hidden="true" tabindex="-1"></a>  <em>template-argument</em>:</span>
<span id="cb122-12"><a href="#cb122-12" aria-hidden="true" tabindex="-1"></a>      <em>constant-expression</em></span>
<span id="cb122-13"><a href="#cb122-13" aria-hidden="true" tabindex="-1"></a>      <em>type-id</em></span>
<span id="cb122-14"><a href="#cb122-14" aria-hidden="true" tabindex="-1"></a>      <em>id-expression</em></span>
<span id="cb122-15"><a href="#cb122-15" aria-hidden="true" tabindex="-1"></a>      <em>braced-init-list</em></span>
<span id="cb122-16"><a href="#cb122-16" aria-hidden="true" tabindex="-1"></a><span class="va">+     <em>splice-template-argument</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Extend paragraph 1 to cover template splicers:</p>
<div class="std">
<blockquote>
<p>The component name of a
<code class="sourceCode cpp"><em>simple-template-id</em></code>,
<code class="sourceCode cpp"><em>template-id</em></code>, or
<code class="sourceCode cpp"><em>template-name</em></code> is the first
name in it. <span class="addu">If the
<code class="sourceCode cpp"><em>template-name</em></code> is a
<code class="sourceCode cpp"><em>splice-template-name</em></code>, the
converted
<code class="sourceCode cpp"><em>constant-expression</em></code> shall
evaluate to a reflection for a concept, variable template, class
template, alias template, or function template which is not a
constructor template or destructor template; the
<code class="sourceCode cpp"><em>splice-template-name</em></code> names
the entity reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code>.</span></p>
</blockquote>
</div>
<p>Add a paragraph after paragraph 3 of <span>13.3 <a href="https://wg21.link/temp.names">[temp.names]</a></span>:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_95" id="pnum_95">*</a></span>
A <code class="sourceCode cpp"><span class="op">&lt;</span></code> is
also interpreted as the delimiter of a
<code class="sourceCode cpp"><em>template-argument-list</em></code> if
it follows a <code class="sourceCode cpp"><em>template-name</em></code>
consisting of a
<code class="sourceCode cpp"><em>splice-template-name</em></code>.</p>
</div>
</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>Adjust paragraph 3 of [temp.arg.general] to not apply to splice
template arguments:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_96" id="pnum_96">3</a></span>
In a <code class="sourceCode cpp"><em>template-argument</em></code>
<span class="addu">which does not contain a
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>,
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>. <span class="addu">In a
<code class="sourceCode cpp"><em>template-argument</em></code>
containing a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>,
an ambiguity between a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>
and an expression is resolved to a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>.</span></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_97" id="pnum_97">1</a></span>
A <code class="sourceCode cpp"><em>template-argument</em></code> for a
<code class="sourceCode cpp"><em>template-parameter</em></code> which is
a type 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>. A
<code class="sourceCode cpp"><em>template-argument</em></code> having a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>
for such a
<code class="sourceCode cpp"><em>template-parameter</em></code> is
treated as if it were a
<code class="sourceCode cpp"><em>type-id</em></code> nominating the type
reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code> of the
<code class="sourceCode cpp"><em>splice-template-argument</em></code>.</span></p>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.arg.nontype-template-non-type-arguments"><span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>
Template non-type arguments<a href="#temp.arg.nontype-template-non-type-arguments" class="self-link"></a></h3>
<p>Extend <span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>/2
to cover splice template arguments:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_98" id="pnum_98">2</a></span>
The value of a non-type
<code class="sourceCode cpp"><em>template-parameter</em></code>
<em>P</em> of (possibly deduced) type
<code class="sourceCode cpp">T</code> is determined from its template
argument <em>A</em> as follows. If <code class="sourceCode cpp">T</code>
is not a class type and <em>A</em> is <span class="rm" style="color: #bf0303"><del>not</del></span><span class="addu">neither</span> a
<code class="sourceCode cpp"><em>braced-init-list</em></code> <span class="addu">nor a
<code class="sourceCode cpp"><em>splice-template-argument</em></code></span>,
<em>A</em> shall be a converted constant expression ([expr.const]) of
type <code class="sourceCode cpp">T</code>; the value of <em>P</em> is
<em>A</em> (as converted).</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 <span>13.4.4 <a href="https://wg21.link/temp.arg.template">[temp.arg.template]</a></span>/1
to cover splice template arguments:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_99" id="pnum_99">1</a></span>
A <code class="sourceCode cpp"><em>template-argument</em></code> for a
template <code class="sourceCode cpp"><em>template-parameter</em></code>
shall be the name of a class template or an alias template, expressed as
<code class="sourceCode cpp"><em>id-expression</em></code><span class="addu">, or a
<code class="sourceCode cpp"><em>splice-template-argument</em></code>. A
<code class="sourceCode cpp"><em>template-argument</em></code> for a
template <code class="sourceCode cpp"><em>template-parameter</em></code>
having a
<code class="sourceCode cpp"><em>splice-template-argument</em></code> is
treated as an <code class="sourceCode cpp"><em>id-expression</em></code>
nominating the class template or alias template reflected by the
<code class="sourceCode cpp"><em>constant-expression</em></code> of the
<code class="sourceCode cpp"><em>splice-template-argument</em></code>.</span></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 <em>template-argument-equivalent</em> 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_100" id="pnum_100">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_101" id="pnum_101">(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_102" id="pnum_102">(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_103" id="pnum_103">(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_104" id="pnum_104">(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 they compare equal, or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_105" id="pnum_105">(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_106" id="pnum_106">(2.5)</a></span>
[…]</li>
</ul>
</blockquote>
</div>
<h3 class="unnumbered" id="temp.concept-concept-definitions"><span>13.7.9 <a href="https://wg21.link/temp.concept">[temp.concept]</a></span> Concept
definitions<a href="#temp.concept-concept-definitions" class="self-link"></a></h3>
<p>Extend the grammar of
<code class="sourceCode cpp"><em>concept-name</em></code> to allow for
splicing reflections of concepts:</p>
<div class="std">
<blockquote>
<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>  <em>concept-name</em>:</span>
<span id="cb123-2"><a href="#cb123-2" aria-hidden="true" tabindex="-1"></a>    <em>identifier</em></span>
<span id="cb123-3"><a href="#cb123-3" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>splice-template-name</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Modify paragraph 2 to account for splicing reflections of
concepts:</p>
<div class="std">
<blockquote>
<p>A <code class="sourceCode cpp"><em>concept-definition</em></code>
declares a concept. Its <span class="addu"><code class="sourceCode cpp"><em>concept-name</em></code>
shall consist of an
<code class="sourceCode cpp"><em>identifier</em></code>, and the</span>
<code class="sourceCode cpp"><em>identifier</em></code> becomes a
<em>concept-name</em> referring to that concept within its scope. The
optional <em>attribute-specifier-seq</em> appertains to the concept.</p>
</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
<span>13.8.3.3 <a href="https://wg21.link/temp.dep.expr">[temp.dep.expr]</a></span>/4:</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>literal</em></span>
<span id="cb124-2"><a href="#cb124-2" aria-hidden="true" tabindex="-1"></a>     sizeof <em>unary-expression</em></span>
<span id="cb124-3"><a href="#cb124-3" aria-hidden="true" tabindex="-1"></a>     sizeof ( <em>type-id</em> )</span>
<span id="cb124-4"><a href="#cb124-4" aria-hidden="true" tabindex="-1"></a>     sizeof ... ( <em>identifier</em> )</span>
<span id="cb124-5"><a href="#cb124-5" aria-hidden="true" tabindex="-1"></a>     alignof ( <em>type-id</em> )</span>
<span id="cb124-6"><a href="#cb124-6" aria-hidden="true" tabindex="-1"></a>     typeid ( <em>expression</em> )</span>
<span id="cb124-7"><a href="#cb124-7" aria-hidden="true" tabindex="-1"></a>     typeid ( <em>type-id</em> )</span>
<span id="cb124-8"><a href="#cb124-8" aria-hidden="true" tabindex="-1"></a>     ::<sub><em>opt</em></sub> delete <em>cast-expression</em></span>
<span id="cb124-9"><a href="#cb124-9" aria-hidden="true" tabindex="-1"></a>     ::<sub><em>opt</em></sub> delete [ ] <em>cast-expression</em></span>
<span id="cb124-10"><a href="#cb124-10" aria-hidden="true" tabindex="-1"></a>     throw <em>assignment-expression</em><sub><em>opt</em></sub></span>
<span id="cb124-11"><a href="#cb124-11" aria-hidden="true" tabindex="-1"></a>     noexcept ( <em>expression</em> )</span>
<span id="cb124-12"><a href="#cb124-12" aria-hidden="true" tabindex="-1"></a>     <em>requires-expression</em></span>
<span id="cb124-13"><a href="#cb124-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_107" id="pnum_107">9</a></span>
A <code class="sourceCode cpp"><em>primary-expression</em></code> of the
form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
or <code class="sourceCode cpp"><span class="kw">template</span><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span>  <span class="op">&lt;</span> <em>template-argument-list</em><sub><em>opt</em></sub> <span class="op">&gt;</span></code>
is type-dependent if the
<code class="sourceCode cpp"><em>constant-expression</em></code> is
value-dependent or if the optional
<code class="sourceCode cpp"><em>template-argument-list</em></code>
contains a value-dependent nontype or template argument, or a dependent
type argument.</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_108" id="pnum_108">2</a></span>
An <em>id-expression</em> is value-dependent if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_109" id="pnum_109">(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="cb125"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb125-1"><a href="#cb125-1" aria-hidden="true" tabindex="-1"></a>sizeof unary-expression</span>
<span id="cb125-2"><a href="#cb125-2" aria-hidden="true" tabindex="-1"></a>sizeof ( type-id )</span>
<span id="cb125-3"><a href="#cb125-3" aria-hidden="true" tabindex="-1"></a>typeid ( expression )</span>
<span id="cb125-4"><a href="#cb125-4" aria-hidden="true" tabindex="-1"></a>typeid ( type-id )</span>
<span id="cb125-5"><a href="#cb125-5" aria-hidden="true" tabindex="-1"></a>alignof ( type-id )</span>
<span id="cb125-6"><a href="#cb125-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 the operand of the reflection operator is a type-dependent
or value-dependent expression or if that operand is a dependent
<code class="sourceCode cpp"><em>type-id</em></code>, a dependent
<code class="sourceCode cpp"><em>namespace-name</em></code>, or a
dependent
<code class="sourceCode cpp"><em>template-name</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>/4:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_110" id="pnum_110">6</a></span>
A <code class="sourceCode cpp"><em>primary-expression</em></code> of the
form <code class="sourceCode cpp"><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span></code>
or <code class="sourceCode cpp"><span class="kw">template</span><span class="op">[:</span> <em>constant-expression</em> <span class="op">:]</span>  <span class="op">&lt;</span> <em>template-argument-list</em><sub><em>opt</em></sub> <span class="op">&gt;</span></code>
is value-dependent if the
<code class="sourceCode cpp"><em>constant-expression</em></code> is
value-dependent or if the optional
<code class="sourceCode cpp"><em>template-argument-list</em></code>
contains a value-dependent nontype or template argument, or a dependent
type argument.</p>
</div>
</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 data-number="5.2.1" id="namespace.std-namespace-std"><span class="header-section-number">5.2.1</span> <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_111" id="pnum_111">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_112" id="pnum_112">7pre</a></span>
Let F denote a standard library function, member function, or function
template. If F does not designate 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>E.g., <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>members_of</code>
might not produce reflections of standard functions that an
implementation handles through an extra-linguistic mechanism.<span>
— <em>end note</em> ]</span></span></p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_113" id="pnum_113">7</a></span>
A translation unit shall not declare namespace std to be an inline
namespace ([namespace.def]).</p>
</blockquote>
</div>
<h3 data-number="5.2.2" id="meta.type.synop-header-type_traits-synopsis"><span class="header-section-number">5.2.2</span> <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="cb126"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb126-1"><a href="#cb126-1" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.cat], primary type categories</span>
<span id="cb126-2"><a href="#cb126-2" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_void;</span>
<span id="cb126-3"><a href="#cb126-3" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb126-4"><a href="#cb126-4" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt; struct is_function;</span>
<span id="cb126-5"><a href="#cb126-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt; struct is_reflection;</span></span>
<span id="cb126-6"><a href="#cb126-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb126-7"><a href="#cb126-7" aria-hidden="true" tabindex="-1"></a>    // [meta.unary.cat], primary type categories</span>
<span id="cb126-8"><a href="#cb126-8" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb126-9"><a href="#cb126-9" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_void_v = is_void&lt;T&gt;::value;</span>
<span id="cb126-10"><a href="#cb126-10" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb126-11"><a href="#cb126-11" aria-hidden="true" tabindex="-1"></a>    template&lt;class T&gt;</span>
<span id="cb126-12"><a href="#cb126-12" aria-hidden="true" tabindex="-1"></a>      constexpr bool is_reflection_v = is_function&lt;T&gt;::value;</span>
<span id="cb126-13"><a href="#cb126-13" aria-hidden="true" tabindex="-1"></a><span class="va">+   template&lt;class T&gt;</span></span>
<span id="cb126-14"><a href="#cb126-14" aria-hidden="true" tabindex="-1"></a><span class="va">+     constexpr bool is_reflection_v = is_function&lt;T&gt;::value;</span></span></code></pre></div>
</div>
</blockquote>
</div>
<h3 data-number="5.2.3" id="meta.unary.cat-primary-type-categories"><span class="header-section-number">5.2.3</span> <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>
<table>
<tr style="text-align:center">
<th>
Template
</th>
<th>
Condition
</th>
<th>
Comments
</th>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb127"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb127-1"><a href="#cb127-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb127-2"><a href="#cb127-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="cb128"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb128-1"><a href="#cb128-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb128-2"><a href="#cb128-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>
<h3 class="unnumbered" id="meta.synop-header-meta-synopsis">[meta.synop]
Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis<a href="#meta.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="cb129"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb129-1"><a href="#cb129-1" aria-hidden="true" tabindex="-1"></a>#include &lt;span&gt;</span>
<span id="cb129-2"><a href="#cb129-2" aria-hidden="true" tabindex="-1"></a>#include &lt;string_view&gt;</span>
<span id="cb129-3"><a href="#cb129-3" aria-hidden="true" tabindex="-1"></a>#include &lt;vector&gt;</span>
<span id="cb129-4"><a href="#cb129-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-5"><a href="#cb129-5" aria-hidden="true" tabindex="-1"></a>namespace std::meta {</span>
<span id="cb129-6"><a href="#cb129-6" aria-hidden="true" tabindex="-1"></a>  using info = decltype(^::);</span>
<span id="cb129-7"><a href="#cb129-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-8"><a href="#cb129-8" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.names], reflection names and locations</span>
<span id="cb129-9"><a href="#cb129-9" aria-hidden="true" tabindex="-1"></a>  consteval string_view name_of(info r);</span>
<span id="cb129-10"><a href="#cb129-10" aria-hidden="true" tabindex="-1"></a>  consteval string_view qualified_name_of(info r);</span>
<span id="cb129-11"><a href="#cb129-11" aria-hidden="true" tabindex="-1"></a>  consteval string_view display_name_of(info r);</span>
<span id="cb129-12"><a href="#cb129-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-13"><a href="#cb129-13" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8name_of(info r);</span>
<span id="cb129-14"><a href="#cb129-14" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8qualified_name_of(info r);</span>
<span id="cb129-15"><a href="#cb129-15" aria-hidden="true" tabindex="-1"></a>  consteval u8string_view u8display_name_of(info r);</span>
<span id="cb129-16"><a href="#cb129-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-17"><a href="#cb129-17" aria-hidden="true" tabindex="-1"></a>  consteval source_location source_location_of(info r);</span>
<span id="cb129-18"><a href="#cb129-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-19"><a href="#cb129-19" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.queries], reflection queries</span>
<span id="cb129-20"><a href="#cb129-20" aria-hidden="true" tabindex="-1"></a>  consteval bool is_public(info r);</span>
<span id="cb129-21"><a href="#cb129-21" aria-hidden="true" tabindex="-1"></a>  consteval bool is_protected(info r);</span>
<span id="cb129-22"><a href="#cb129-22" aria-hidden="true" tabindex="-1"></a>  consteval bool is_private(info r);</span>
<span id="cb129-23"><a href="#cb129-23" aria-hidden="true" tabindex="-1"></a>  consteval bool is_virtual(info r);</span>
<span id="cb129-24"><a href="#cb129-24" aria-hidden="true" tabindex="-1"></a>  consteval bool is_pure_virtual(info r);</span>
<span id="cb129-25"><a href="#cb129-25" aria-hidden="true" tabindex="-1"></a>  consteval bool is_override(info r);</span>
<span id="cb129-26"><a href="#cb129-26" aria-hidden="true" tabindex="-1"></a>  consteval bool is_deleted(info r);</span>
<span id="cb129-27"><a href="#cb129-27" aria-hidden="true" tabindex="-1"></a>  consteval bool is_defaulted(info r);</span>
<span id="cb129-28"><a href="#cb129-28" aria-hidden="true" tabindex="-1"></a>  consteval bool is_explicit(info r);</span>
<span id="cb129-29"><a href="#cb129-29" aria-hidden="true" tabindex="-1"></a>  consteval bool is_noexcept(info r);</span>
<span id="cb129-30"><a href="#cb129-30" aria-hidden="true" tabindex="-1"></a>  consteval bool is_bit_field(info r);</span>
<span id="cb129-31"><a href="#cb129-31" aria-hidden="true" tabindex="-1"></a>  consteval bool is_const(info r);</span>
<span id="cb129-32"><a href="#cb129-32" aria-hidden="true" tabindex="-1"></a>  consteval bool is_volatile(info r);</span>
<span id="cb129-33"><a href="#cb129-33" aria-hidden="true" tabindex="-1"></a>  consteval bool is_final(info r);</span>
<span id="cb129-34"><a href="#cb129-34" aria-hidden="true" tabindex="-1"></a>  consteval bool has_static_storage_duration(info r);</span>
<span id="cb129-35"><a href="#cb129-35" aria-hidden="true" tabindex="-1"></a>  consteval bool has_internal_linkage(info r);</span>
<span id="cb129-36"><a href="#cb129-36" aria-hidden="true" tabindex="-1"></a>  consteval bool has_module_linkage(info r);</span>
<span id="cb129-37"><a href="#cb129-37" aria-hidden="true" tabindex="-1"></a>  consteval bool has_external_linkage(info r);</span>
<span id="cb129-38"><a href="#cb129-38" aria-hidden="true" tabindex="-1"></a>  consteval bool has_linkage(info r);</span>
<span id="cb129-39"><a href="#cb129-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-40"><a href="#cb129-40" aria-hidden="true" tabindex="-1"></a>  consteval bool is_namespace(info r);</span>
<span id="cb129-41"><a href="#cb129-41" aria-hidden="true" tabindex="-1"></a>  consteval bool is_function(info r);</span>
<span id="cb129-42"><a href="#cb129-42" aria-hidden="true" tabindex="-1"></a>  consteval bool is_variable(info r);</span>
<span id="cb129-43"><a href="#cb129-43" aria-hidden="true" tabindex="-1"></a>  consteval bool is_type(info r);</span>
<span id="cb129-44"><a href="#cb129-44" aria-hidden="true" tabindex="-1"></a>  consteval bool is_alias(info r);</span>
<span id="cb129-45"><a href="#cb129-45" aria-hidden="true" tabindex="-1"></a>  consteval bool is_incomplete_type(info r);</span>
<span id="cb129-46"><a href="#cb129-46" aria-hidden="true" tabindex="-1"></a>  consteval bool is_template(info r);</span>
<span id="cb129-47"><a href="#cb129-47" aria-hidden="true" tabindex="-1"></a>  consteval bool is_function_template(info r);</span>
<span id="cb129-48"><a href="#cb129-48" aria-hidden="true" tabindex="-1"></a>  consteval bool is_variable_template(info r);</span>
<span id="cb129-49"><a href="#cb129-49" aria-hidden="true" tabindex="-1"></a>  consteval bool is_class_template(info r);</span>
<span id="cb129-50"><a href="#cb129-50" aria-hidden="true" tabindex="-1"></a>  consteval bool is_alias_template(info r);</span>
<span id="cb129-51"><a href="#cb129-51" aria-hidden="true" tabindex="-1"></a>  consteval bool is_concept(info r);</span>
<span id="cb129-52"><a href="#cb129-52" aria-hidden="true" tabindex="-1"></a>  consteval bool is_value(info r);</span>
<span id="cb129-53"><a href="#cb129-53" aria-hidden="true" tabindex="-1"></a>  consteval bool is_object(info r);</span>
<span id="cb129-54"><a href="#cb129-54" aria-hidden="true" tabindex="-1"></a>  consteval bool is_structured_binding(info r);</span>
<span id="cb129-55"><a href="#cb129-55" aria-hidden="true" tabindex="-1"></a>  consteval bool has_template_arguments(info r);</span>
<span id="cb129-56"><a href="#cb129-56" aria-hidden="true" tabindex="-1"></a>  consteval bool is_class_member(info entity);</span>
<span id="cb129-57"><a href="#cb129-57" aria-hidden="true" tabindex="-1"></a>  consteval bool is_namespace_member(info entity);</span>
<span id="cb129-58"><a href="#cb129-58" aria-hidden="true" tabindex="-1"></a>  consteval bool is_nonstatic_data_member(info r);</span>
<span id="cb129-59"><a href="#cb129-59" aria-hidden="true" tabindex="-1"></a>  consteval bool is_static_member(info r);</span>
<span id="cb129-60"><a href="#cb129-60" aria-hidden="true" tabindex="-1"></a>  consteval bool is_base(info r);</span>
<span id="cb129-61"><a href="#cb129-61" aria-hidden="true" tabindex="-1"></a>  consteval bool is_constructor(info r);</span>
<span id="cb129-62"><a href="#cb129-62" aria-hidden="true" tabindex="-1"></a>  consteval bool is_destructor(info r);</span>
<span id="cb129-63"><a href="#cb129-63" aria-hidden="true" tabindex="-1"></a>  consteval bool is_special_member(info r);</span>
<span id="cb129-64"><a href="#cb129-64" aria-hidden="true" tabindex="-1"></a>  consteval bool is_user_provided(info r);</span>
<span id="cb129-65"><a href="#cb129-65" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-66"><a href="#cb129-66" aria-hidden="true" tabindex="-1"></a>  consteval info type_of(info r);</span>
<span id="cb129-67"><a href="#cb129-67" aria-hidden="true" tabindex="-1"></a>  consteval info object_of(info r);</span>
<span id="cb129-68"><a href="#cb129-68" aria-hidden="true" tabindex="-1"></a>  consteval info value_of(info r);</span>
<span id="cb129-69"><a href="#cb129-69" aria-hidden="true" tabindex="-1"></a>  consteval info parent_of(info r);</span>
<span id="cb129-70"><a href="#cb129-70" aria-hidden="true" tabindex="-1"></a>  consteval info dealias(info r);</span>
<span id="cb129-71"><a href="#cb129-71" aria-hidden="true" tabindex="-1"></a>  consteval info template_of(info r);</span>
<span id="cb129-72"><a href="#cb129-72" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; template_arguments_of(info r);</span>
<span id="cb129-73"><a href="#cb129-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-74"><a href="#cb129-74" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.member.queries], reflection member queries</span>
<span id="cb129-75"><a href="#cb129-75" aria-hidden="true" tabindex="-1"></a>  template&lt;class... Fs&gt;</span>
<span id="cb129-76"><a href="#cb129-76" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; members_of(info type, Fs... filters);</span>
<span id="cb129-77"><a href="#cb129-77" aria-hidden="true" tabindex="-1"></a>  template&lt;class... Fs&gt;</span>
<span id="cb129-78"><a href="#cb129-78" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; bases_of(info type, Fs... filters);</span>
<span id="cb129-79"><a href="#cb129-79" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; static_data_members_of(info type);</span>
<span id="cb129-80"><a href="#cb129-80" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; nonstatic_data_members_of(info type);</span>
<span id="cb129-81"><a href="#cb129-81" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; subobjects_of(info type);</span>
<span id="cb129-82"><a href="#cb129-82" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; enumerators_of(info type_enum);</span>
<span id="cb129-83"><a href="#cb129-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-84"><a href="#cb129-84" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.member.access], reflection member access queries</span>
<span id="cb129-85"><a href="#cb129-85" aria-hidden="true" tabindex="-1"></a>  consteval info access_context();</span>
<span id="cb129-86"><a href="#cb129-86" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-87"><a href="#cb129-87" aria-hidden="true" tabindex="-1"></a>  struct access_pair {</span>
<span id="cb129-88"><a href="#cb129-88" aria-hidden="true" tabindex="-1"></a>    consteval access_pair(info target, info from = access_context());</span>
<span id="cb129-89"><a href="#cb129-89" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb129-90"><a href="#cb129-90" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-91"><a href="#cb129-91" aria-hidden="true" tabindex="-1"></a>  consteval bool is_accessible(access_pair p);</span>
<span id="cb129-92"><a href="#cb129-92" aria-hidden="true" tabindex="-1"></a>  consteval bool is_accessible(info r, info from);</span>
<span id="cb129-93"><a href="#cb129-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-94"><a href="#cb129-94" aria-hidden="true" tabindex="-1"></a>  template &lt;typename... Preds&gt;</span>
<span id="cb129-95"><a href="#cb129-95" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; accessible_members_of(access_pair p, Preds... preds);</span>
<span id="cb129-96"><a href="#cb129-96" aria-hidden="true" tabindex="-1"></a>  template &lt;typename... Preds&gt;</span>
<span id="cb129-97"><a href="#cb129-97" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; accessible_members_of(info target, info from, Preds... preds);</span>
<span id="cb129-98"><a href="#cb129-98" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-99"><a href="#cb129-99" aria-hidden="true" tabindex="-1"></a>  template &lt;typename... Preds&gt;</span>
<span id="cb129-100"><a href="#cb129-100" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; accessible_bases_of(access_pair p, Preds... preds);</span>
<span id="cb129-101"><a href="#cb129-101" aria-hidden="true" tabindex="-1"></a>  template &lt;typename... Preds&gt;</span>
<span id="cb129-102"><a href="#cb129-102" aria-hidden="true" tabindex="-1"></a>    consteval vector&lt;info&gt; accessible_bases_of(info target, info from, Preds... preds);</span>
<span id="cb129-103"><a href="#cb129-103" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-104"><a href="#cb129-104" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_nonstatic_data_members_of(access_pair p);</span>
<span id="cb129-105"><a href="#cb129-105" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_nonstatic_data_members_of(info target, info from);</span>
<span id="cb129-106"><a href="#cb129-106" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_static_data_members_of(access_pair p);</span>
<span id="cb129-107"><a href="#cb129-107" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_static_data_members_of(info target, info from);</span>
<span id="cb129-108"><a href="#cb129-108" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_subobjects_of(access_pair p);</span>
<span id="cb129-109"><a href="#cb129-109" aria-hidden="true" tabindex="-1"></a>  consteval vector&lt;info&gt; accessible_subobjects_of(info target, info from);</span>
<span id="cb129-110"><a href="#cb129-110" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-111"><a href="#cb129-111" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.layout], reflection layout queries</span>
<span id="cb129-112"><a href="#cb129-112" aria-hidden="true" tabindex="-1"></a>  consteval size_t offset_of(info entity);</span>
<span id="cb129-113"><a href="#cb129-113" aria-hidden="true" tabindex="-1"></a>  consteval size_t size_of(info entity);</span>
<span id="cb129-114"><a href="#cb129-114" aria-hidden="true" tabindex="-1"></a>  consteval size_t alignment_of(info entity);</span>
<span id="cb129-115"><a href="#cb129-115" aria-hidden="true" tabindex="-1"></a>  consteval size_t bit_offset_of(info entity);</span>
<span id="cb129-116"><a href="#cb129-116" aria-hidden="true" tabindex="-1"></a>  consteval size_t bit_size_of(info entity);</span>
<span id="cb129-117"><a href="#cb129-117" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-118"><a href="#cb129-118" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.extract], value extraction</span>
<span id="cb129-119"><a href="#cb129-119" aria-hidden="true" tabindex="-1"></a>  template &lt;typename T&gt;</span>
<span id="cb129-120"><a href="#cb129-120" aria-hidden="true" tabindex="-1"></a>    consteval T extract(info);</span>
<span id="cb129-121"><a href="#cb129-121" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-122"><a href="#cb129-122" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.substitute], reflection substitution</span>
<span id="cb129-123"><a href="#cb129-123" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-124"><a href="#cb129-124" aria-hidden="true" tabindex="-1"></a>    consteval bool can_substitute(info templ, R&amp;&amp; arguments);</span>
<span id="cb129-125"><a href="#cb129-125" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-126"><a href="#cb129-126" aria-hidden="true" tabindex="-1"></a>    consteval info substitute(info templ, R&amp;&amp; arguments);</span>
<span id="cb129-127"><a href="#cb129-127" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-128"><a href="#cb129-128" aria-hidden="true" tabindex="-1"></a>  consteval bool test_trait(info templ, info type);</span>
<span id="cb129-129"><a href="#cb129-129" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-130"><a href="#cb129-130" aria-hidden="true" tabindex="-1"></a>    consteval bool test_trait(info templ, R&amp;&amp; arguments);</span>
<span id="cb129-131"><a href="#cb129-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-132"><a href="#cb129-132" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.result], expression result reflection</span>
<span id="cb129-133"><a href="#cb129-133" aria-hidden="true" tabindex="-1"></a>  template &lt;class R&gt;</span>
<span id="cb129-134"><a href="#cb129-134" aria-hidden="true" tabindex="-1"></a>    concept reflection_range = <em>see below</em>;</span>
<span id="cb129-135"><a href="#cb129-135" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-136"><a href="#cb129-136" aria-hidden="true" tabindex="-1"></a>  template &lt;typename T&gt;</span>
<span id="cb129-137"><a href="#cb129-137" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_value(T value);</span>
<span id="cb129-138"><a href="#cb129-138" aria-hidden="true" tabindex="-1"></a>  template &lt;typename T&gt;</span>
<span id="cb129-139"><a href="#cb129-139" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_object(T&amp; object);</span>
<span id="cb129-140"><a href="#cb129-140" aria-hidden="true" tabindex="-1"></a>  template &lt;typename T&gt;</span>
<span id="cb129-141"><a href="#cb129-141" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_function(T&amp; fn);</span>
<span id="cb129-142"><a href="#cb129-142" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-143"><a href="#cb129-143" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-144"><a href="#cb129-144" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_invoke(info target, R&amp;&amp; args);</span>
<span id="cb129-145"><a href="#cb129-145" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R1 = span&lt;info const&gt;, reflection_range R2 = span&lt;info const&gt;&gt;</span>
<span id="cb129-146"><a href="#cb129-146" aria-hidden="true" tabindex="-1"></a>    consteval info reflect_invoke(info target, R1&amp;&amp; tmpl_args, R2&amp;&amp; args);</span>
<span id="cb129-147"><a href="#cb129-147" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-148"><a href="#cb129-148" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.define_class], class definition generation</span>
<span id="cb129-149"><a href="#cb129-149" aria-hidden="true" tabindex="-1"></a>  struct data_member_options_t {</span>
<span id="cb129-150"><a href="#cb129-150" aria-hidden="true" tabindex="-1"></a>    struct name_type {</span>
<span id="cb129-151"><a href="#cb129-151" aria-hidden="true" tabindex="-1"></a>      template &lt;typename T&gt; requires constructible_from&lt;u8string, T&gt;</span>
<span id="cb129-152"><a href="#cb129-152" aria-hidden="true" tabindex="-1"></a>        consteval name_type(T &amp;&amp;);</span>
<span id="cb129-153"><a href="#cb129-153" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-154"><a href="#cb129-154" aria-hidden="true" tabindex="-1"></a>      template &lt;typename T&gt; requires constructible_from&lt;string, T&gt;</span>
<span id="cb129-155"><a href="#cb129-155" aria-hidden="true" tabindex="-1"></a>        consteval name_type(T &amp;&amp;);</span>
<span id="cb129-156"><a href="#cb129-156" aria-hidden="true" tabindex="-1"></a>    };</span>
<span id="cb129-157"><a href="#cb129-157" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-158"><a href="#cb129-158" aria-hidden="true" tabindex="-1"></a>    optional&lt;name_type&gt; name;</span>
<span id="cb129-159"><a href="#cb129-159" aria-hidden="true" tabindex="-1"></a>    optional&lt;int&gt; alignment;</span>
<span id="cb129-160"><a href="#cb129-160" aria-hidden="true" tabindex="-1"></a>    optional&lt;int&gt; width;</span>
<span id="cb129-161"><a href="#cb129-161" aria-hidden="true" tabindex="-1"></a>    bool no_unique_address = false;</span>
<span id="cb129-162"><a href="#cb129-162" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb129-163"><a href="#cb129-163" aria-hidden="true" tabindex="-1"></a>  consteval info data_member_spec(info type,</span>
<span id="cb129-164"><a href="#cb129-164" aria-hidden="true" tabindex="-1"></a>                                  data_member_options_t options = {});</span>
<span id="cb129-165"><a href="#cb129-165" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-166"><a href="#cb129-166" aria-hidden="true" tabindex="-1"></a>  consteval info define_class(info type_class, R&amp;&amp;);</span>
<span id="cb129-167"><a href="#cb129-167" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-168"><a href="#cb129-168" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.unary.cat], primary type categories</span>
<span id="cb129-169"><a href="#cb129-169" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_void(info type);</span>
<span id="cb129-170"><a href="#cb129-170" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_null_pointer(info type);</span>
<span id="cb129-171"><a href="#cb129-171" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_integral(info type);</span>
<span id="cb129-172"><a href="#cb129-172" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_floating_point(info type);</span>
<span id="cb129-173"><a href="#cb129-173" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_array(info type);</span>
<span id="cb129-174"><a href="#cb129-174" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_pointer(info type);</span>
<span id="cb129-175"><a href="#cb129-175" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_lvalue_reference(info type);</span>
<span id="cb129-176"><a href="#cb129-176" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_rvalue_reference(info type);</span>
<span id="cb129-177"><a href="#cb129-177" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_member_object_pointer(info type);</span>
<span id="cb129-178"><a href="#cb129-178" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_member_function_pointer(info type);</span>
<span id="cb129-179"><a href="#cb129-179" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_enum(info type);</span>
<span id="cb129-180"><a href="#cb129-180" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_union(info type);</span>
<span id="cb129-181"><a href="#cb129-181" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_class(info type);</span>
<span id="cb129-182"><a href="#cb129-182" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_function(info type);</span>
<span id="cb129-183"><a href="#cb129-183" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_reflection(info type);</span>
<span id="cb129-184"><a href="#cb129-184" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-185"><a href="#cb129-185" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.unary.comp], composite type categories</span>
<span id="cb129-186"><a href="#cb129-186" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_reference(info type);</span>
<span id="cb129-187"><a href="#cb129-187" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_arithmetic(info type);</span>
<span id="cb129-188"><a href="#cb129-188" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_fundamental(info type);</span>
<span id="cb129-189"><a href="#cb129-189" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_object(info type);</span>
<span id="cb129-190"><a href="#cb129-190" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_scalar(info type);</span>
<span id="cb129-191"><a href="#cb129-191" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_compound(info type);</span>
<span id="cb129-192"><a href="#cb129-192" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_member_pointer(info type);</span>
<span id="cb129-193"><a href="#cb129-193" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-194"><a href="#cb129-194" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection unary.prop], type properties</span>
<span id="cb129-195"><a href="#cb129-195" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_const(info type);</span>
<span id="cb129-196"><a href="#cb129-196" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_volatile(info type);</span>
<span id="cb129-197"><a href="#cb129-197" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivial(info type);</span>
<span id="cb129-198"><a href="#cb129-198" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_copyable(info type);</span>
<span id="cb129-199"><a href="#cb129-199" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_standard_layout(info type);</span>
<span id="cb129-200"><a href="#cb129-200" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_empty(info type);</span>
<span id="cb129-201"><a href="#cb129-201" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_polymorphic(info type);</span>
<span id="cb129-202"><a href="#cb129-202" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_abstract(info type);</span>
<span id="cb129-203"><a href="#cb129-203" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_final(info type);</span>
<span id="cb129-204"><a href="#cb129-204" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_aggregate(info type);</span>
<span id="cb129-205"><a href="#cb129-205" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_signed(info type);</span>
<span id="cb129-206"><a href="#cb129-206" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_unsigned(info type);</span>
<span id="cb129-207"><a href="#cb129-207" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_bounded_array(info type);</span>
<span id="cb129-208"><a href="#cb129-208" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_unbounded_array(info type);</span>
<span id="cb129-209"><a href="#cb129-209" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_scoped_enum(info type);</span>
<span id="cb129-210"><a href="#cb129-210" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-211"><a href="#cb129-211" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-212"><a href="#cb129-212" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_constructible(info type, R&amp;&amp; type_args);</span>
<span id="cb129-213"><a href="#cb129-213" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_default_constructible(info type);</span>
<span id="cb129-214"><a href="#cb129-214" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_copy_constructible(info type);</span>
<span id="cb129-215"><a href="#cb129-215" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_move_constructible(info type);</span>
<span id="cb129-216"><a href="#cb129-216" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-217"><a href="#cb129-217" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_assignable(info type_dst, info type_src);</span>
<span id="cb129-218"><a href="#cb129-218" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_copy_assignable(info type);</span>
<span id="cb129-219"><a href="#cb129-219" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_move_assignable(info type);</span>
<span id="cb129-220"><a href="#cb129-220" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-221"><a href="#cb129-221" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_swappable_with(info type_dst, info type_src);</span>
<span id="cb129-222"><a href="#cb129-222" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_swappable(info type);</span>
<span id="cb129-223"><a href="#cb129-223" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-224"><a href="#cb129-224" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_destructible(info type);</span>
<span id="cb129-225"><a href="#cb129-225" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-226"><a href="#cb129-226" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-227"><a href="#cb129-227" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_trivially_constructible(info type, R&amp;&amp; type_args);</span>
<span id="cb129-228"><a href="#cb129-228" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_default_constructible(info type);</span>
<span id="cb129-229"><a href="#cb129-229" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_copy_constructible(info type);</span>
<span id="cb129-230"><a href="#cb129-230" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_move_constructible(info type);</span>
<span id="cb129-231"><a href="#cb129-231" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-232"><a href="#cb129-232" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_assignable(info type_dst, info type_src);</span>
<span id="cb129-233"><a href="#cb129-233" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_copy_assignable(info type);</span>
<span id="cb129-234"><a href="#cb129-234" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_move_assignable(info type);</span>
<span id="cb129-235"><a href="#cb129-235" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_trivially_destructible(info type);</span>
<span id="cb129-236"><a href="#cb129-236" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-237"><a href="#cb129-237" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-238"><a href="#cb129-238" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_nothrow_constructible(info type, R&amp;&amp; type_args);</span>
<span id="cb129-239"><a href="#cb129-239" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_default_constructible(info type);</span>
<span id="cb129-240"><a href="#cb129-240" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_copy_constructible(info type);</span>
<span id="cb129-241"><a href="#cb129-241" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_move_constructible(info type);</span>
<span id="cb129-242"><a href="#cb129-242" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-243"><a href="#cb129-243" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_assignable(info type_dst, info type_src);</span>
<span id="cb129-244"><a href="#cb129-244" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_copy_assignable(info type);</span>
<span id="cb129-245"><a href="#cb129-245" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_move_assignable(info type);</span>
<span id="cb129-246"><a href="#cb129-246" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-247"><a href="#cb129-247" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_swappable_with(info type_dst, info type_src);</span>
<span id="cb129-248"><a href="#cb129-248" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_swappable(info type);</span>
<span id="cb129-249"><a href="#cb129-249" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-250"><a href="#cb129-250" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_destructible(info type);</span>
<span id="cb129-251"><a href="#cb129-251" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-252"><a href="#cb129-252" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_implicit_lifetime(info type);</span>
<span id="cb129-253"><a href="#cb129-253" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-254"><a href="#cb129-254" aria-hidden="true" tabindex="-1"></a>  consteval bool type_has_virtual_destructor(info type);</span>
<span id="cb129-255"><a href="#cb129-255" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-256"><a href="#cb129-256" aria-hidden="true" tabindex="-1"></a>  consteval bool type_has_unique_object_representations(info type);</span>
<span id="cb129-257"><a href="#cb129-257" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-258"><a href="#cb129-258" aria-hidden="true" tabindex="-1"></a>  consteval bool type_reference_constructs_from_temporary(info type_dst, info type_src);</span>
<span id="cb129-259"><a href="#cb129-259" aria-hidden="true" tabindex="-1"></a>  consteval bool type_reference_converts_from_temporary(info type_dst, info type_src);</span>
<span id="cb129-260"><a href="#cb129-260" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-261"><a href="#cb129-261" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.unary.prop.query], type property queries</span>
<span id="cb129-262"><a href="#cb129-262" aria-hidden="true" tabindex="-1"></a>  consteval size_t type_alignment_of(info type);</span>
<span id="cb129-263"><a href="#cb129-263" aria-hidden="true" tabindex="-1"></a>  consteval size_t type_rank(info type);</span>
<span id="cb129-264"><a href="#cb129-264" aria-hidden="true" tabindex="-1"></a>  consteval size_t type_extent(info type, unsigned i = 0);</span>
<span id="cb129-265"><a href="#cb129-265" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-266"><a href="#cb129-266" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.rel], type relations</span>
<span id="cb129-267"><a href="#cb129-267" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_same(info type1, info type2);</span>
<span id="cb129-268"><a href="#cb129-268" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_base_of(info type_base, info type_derived);</span>
<span id="cb129-269"><a href="#cb129-269" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_convertible(info type_src, info type_dst);</span>
<span id="cb129-270"><a href="#cb129-270" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_nothrow_convertible(info type_src, info type_dst);</span>
<span id="cb129-271"><a href="#cb129-271" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_layout_compatible(info type1, info type2);</span>
<span id="cb129-272"><a href="#cb129-272" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_pointer_interconvertible_base_of(info type_base, info type_derived);</span>
<span id="cb129-273"><a href="#cb129-273" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-274"><a href="#cb129-274" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-275"><a href="#cb129-275" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_invocable(info type, R&amp;&amp; type_args);</span>
<span id="cb129-276"><a href="#cb129-276" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-277"><a href="#cb129-277" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_invocable_r(info type_result, info type, R&amp;&amp; type_args);</span>
<span id="cb129-278"><a href="#cb129-278" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-279"><a href="#cb129-279" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-280"><a href="#cb129-280" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_nothrow_invocable(info type, R&amp;&amp; type_args);</span>
<span id="cb129-281"><a href="#cb129-281" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-282"><a href="#cb129-282" aria-hidden="true" tabindex="-1"></a>    consteval bool type_is_nothrow_invocable_r(info type_result, info type, R&amp;&amp; type_args);</span>
<span id="cb129-283"><a href="#cb129-283" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-284"><a href="#cb129-284" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.cv], const-volatile modifications</span>
<span id="cb129-285"><a href="#cb129-285" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_const(info type);</span>
<span id="cb129-286"><a href="#cb129-286" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_volatile(info type);</span>
<span id="cb129-287"><a href="#cb129-287" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_cv(info type);</span>
<span id="cb129-288"><a href="#cb129-288" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_const(info type);</span>
<span id="cb129-289"><a href="#cb129-289" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_volatile(info type);</span>
<span id="cb129-290"><a href="#cb129-290" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_cv(info type);</span>
<span id="cb129-291"><a href="#cb129-291" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-292"><a href="#cb129-292" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.ref], reference modifications</span>
<span id="cb129-293"><a href="#cb129-293" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_reference(info type);</span>
<span id="cb129-294"><a href="#cb129-294" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_lvalue_reference(info type);</span>
<span id="cb129-295"><a href="#cb129-295" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_rvalue_reference(info type);</span>
<span id="cb129-296"><a href="#cb129-296" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-297"><a href="#cb129-297" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.sign], sign modifications</span>
<span id="cb129-298"><a href="#cb129-298" aria-hidden="true" tabindex="-1"></a>  consteval info type_make_signed(info type);</span>
<span id="cb129-299"><a href="#cb129-299" aria-hidden="true" tabindex="-1"></a>  consteval info type_make_unsigned(info type);</span>
<span id="cb129-300"><a href="#cb129-300" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-301"><a href="#cb129-301" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.arr], array modifications</span>
<span id="cb129-302"><a href="#cb129-302" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_extent(info type);</span>
<span id="cb129-303"><a href="#cb129-303" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_all_extents(info type);</span>
<span id="cb129-304"><a href="#cb129-304" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-305"><a href="#cb129-305" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.ptr], pointer modifications</span>
<span id="cb129-306"><a href="#cb129-306" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_pointer(info type);</span>
<span id="cb129-307"><a href="#cb129-307" aria-hidden="true" tabindex="-1"></a>  consteval info type_add_pointer(info type);</span>
<span id="cb129-308"><a href="#cb129-308" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb129-309"><a href="#cb129-309" aria-hidden="true" tabindex="-1"></a>  // [meta.reflection.trans.other], other transformations</span>
<span id="cb129-310"><a href="#cb129-310" aria-hidden="true" tabindex="-1"></a>  consteval info type_remove_cvref(info type);</span>
<span id="cb129-311"><a href="#cb129-311" aria-hidden="true" tabindex="-1"></a>  consteval info type_decay(info type);</span>
<span id="cb129-312"><a href="#cb129-312" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-313"><a href="#cb129-313" aria-hidden="true" tabindex="-1"></a>    consteval info type_common_type(R&amp;&amp; type_args);</span>
<span id="cb129-314"><a href="#cb129-314" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-315"><a href="#cb129-315" aria-hidden="true" tabindex="-1"></a>    consteval info type_common_reference(R&amp;&amp; type_args);</span>
<span id="cb129-316"><a href="#cb129-316" aria-hidden="true" tabindex="-1"></a>  consteval info type_underlying_type(info type);</span>
<span id="cb129-317"><a href="#cb129-317" aria-hidden="true" tabindex="-1"></a>  template &lt;reflection_range R = span&lt;info const&gt;&gt;</span>
<span id="cb129-318"><a href="#cb129-318" aria-hidden="true" tabindex="-1"></a>    `consteval info type_invoke_result(info type, R&amp;&amp; type_args);</span>
<span id="cb129-319"><a href="#cb129-319" aria-hidden="true" tabindex="-1"></a>  consteval info type_unwrap_reference(info type);</span>
<span id="cb129-320"><a href="#cb129-320" aria-hidden="true" tabindex="-1"></a>  consteval info type_unwrap_ref_decay(info type);</span>
<span id="cb129-321"><a href="#cb129-321" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</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="cb130"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb130-1"><a href="#cb130-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view name_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb130-2"><a href="#cb130-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8name_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_114" id="pnum_114">1</a></span>
<em>Mandates</em>: If returning
<code class="sourceCode cpp">string_view</code>, the unqualified name is
representable using the ordinary string literal encoding.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_115" id="pnum_115">2</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> designates a
declared entity <code class="sourceCode cpp">X</code>, then the
unqualified name of <code class="sourceCode cpp">X</code>. Otherwise, an
empty <code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code>, respectively.</p>
<div class="sourceCode" id="cb131"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb131-1"><a href="#cb131-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view qualified_name_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb131-2"><a href="#cb131-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8qualified_name_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_116" id="pnum_116">3</a></span>
<em>Mandates</em>: If returning
<code class="sourceCode cpp">string_view</code>, the qualified name is
representable using the ordinary string literal encoding.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_117" id="pnum_117">4</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> designates a
declared entity <code class="sourceCode cpp">X</code>, then the
qualified name of <code class="sourceCode cpp">X</code>. Otherwise, an
empty <code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code>, respectively.</p>
<div class="sourceCode" id="cb132"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb132-1"><a href="#cb132-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> string_view display_name_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb132-2"><a href="#cb132-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> u8string_view u8display_name_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_118" id="pnum_118">5</a></span>
<em>Mandates</em>: If returning
<code class="sourceCode cpp">string_view</code>, the
implementation-defined name is representable using the ordinary string
literal encoding.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_119" id="pnum_119">6</a></span>
<em>Returns</em>: An implementation-defined
<code class="sourceCode cpp">string_view</code> or
<code class="sourceCode cpp">u8string_view</code>, respectively,
suitable for identifying the reflected construct.</p>
<div class="sourceCode" id="cb133"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb133-1"><a href="#cb133-1" aria-hidden="true" tabindex="-1"></a><span class="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_120" id="pnum_120">7</a></span>
<em>Returns</em>: An implementation-defined
<code class="sourceCode cpp">source_location</code> corresponding to the
reflected construct.</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="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">consteval</span> <span class="dt">bool</span> is_public<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb134-2"><a href="#cb134-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="cb134-3"><a href="#cb134-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_121" id="pnum_121">1</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a class member or base
class that is public, protected, or private, respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<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">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_122" id="pnum_122">2</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a either a virtual
member function or a virtual base class. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<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">consteval</span> <span class="dt">bool</span> is_pure_virtual<span class="op">(</span>info r<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="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_123" id="pnum_123">3</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates 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="cb137"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb137-1"><a href="#cb137-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></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_124" id="pnum_124">4</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a function that is
defined as deleted. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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="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_125" id="pnum_125">5</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a function that is
defined as defaulted. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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">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_126" id="pnum_126">6</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a member function that
is declared explicit. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<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">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_127" id="pnum_127">7</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
function type, a pointer to
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
function or member function type, a closure type of a non-generic lambda
whose call operator is declared
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>, a
value of any of the previously mentioned types, or a function that is
declared
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb141"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb141-1"><a href="#cb141-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_128" id="pnum_128">8</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a bit-field. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb142"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb142-1"><a href="#cb142-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_const<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb142-2"><a href="#cb142-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_129" id="pnum_129">9</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a const or volatile
type (respectively), a const- or volatile-qualified function type
(respectively), or an object, variable, non-static data member, or
function with such a type. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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><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_130" id="pnum_130">10</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a final class or a
final member function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb144"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb144-1"><a href="#cb144-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_static_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_131" id="pnum_131">11</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates an object or variable
that has static storage duration. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb145"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb145-1"><a href="#cb145-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_internal_linkage<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb145-2"><a href="#cb145-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="cb145-3"><a href="#cb145-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="cb145-4"><a href="#cb145-4" 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_132" id="pnum_132">12</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates an entity that has
internal linkage, module linkage, external linkage, or any linkage,
respectively ([basic.link]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb146"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb146-1"><a href="#cb146-1" aria-hidden="true" tabindex="-1"></a><span class="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_133" id="pnum_133">13</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a namespace or
namespace alias. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb147"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb147-1"><a href="#cb147-1" aria-hidden="true" tabindex="-1"></a><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_134" id="pnum_134">14</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a function or member
function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb148"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb148-1"><a href="#cb148-1" aria-hidden="true" tabindex="-1"></a><span class="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_135" id="pnum_135">15</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a variable. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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="kw">consteval</span> <span class="dt">bool</span> is_type<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_136" id="pnum_136">16</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a type or a type alias.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb150"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb150-1"><a href="#cb150-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_alias<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_137" id="pnum_137">17</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a type alias, alias
template, or namespace alias. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb151"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb151-1"><a href="#cb151-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_incomplete_type<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_138" id="pnum_138">18</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating a type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_139" id="pnum_139">19</a></span>
<em>Effects</em>: If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
designates a class template specialization with a reachable definition,
the specialization is instantiated.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_140" id="pnum_140">20</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if the
type designated by <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
is an incomplete type ([basic.types]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb152"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb152-1"><a href="#cb152-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_141" id="pnum_141">21</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a function template,
class template, variable template, or alias template. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_142" id="pnum_142">22</a></span>
<span class="note"><span>[ <em>Note 1:</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="cb153"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb153-1"><a href="#cb153-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="cb153-2"><a href="#cb153-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="cb153-3"><a href="#cb153-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="cb153-4"><a href="#cb153-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="cb153-5"><a href="#cb153-5" 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>
<span id="cb153-6"><a href="#cb153-6" 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>
<span id="cb153-7"><a href="#cb153-7" 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></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_143" id="pnum_143">23</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a function template,
class template, variable template, alias template, concept, structured
binding, or value respectively. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb154"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb154-1"><a href="#cb154-1" 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_144" id="pnum_144">24</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates an object. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<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">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_145" id="pnum_145">25</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates an instantiation 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="cb156"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb156-1"><a href="#cb156-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="cb156-2"><a href="#cb156-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="cb156-3"><a href="#cb156-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="cb156-4"><a href="#cb156-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="cb156-5"><a href="#cb156-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>
<span id="cb156-6"><a href="#cb156-6" 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="cb156-7"><a href="#cb156-7" 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>
<span id="cb156-8"><a href="#cb156-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_special_member<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_146" id="pnum_146">26</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a class member,
namespace member, non-static data member, static member, base class
member, constructor, destructor, or special member, respectively.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb157"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb157-1"><a href="#cb157-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></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_147" id="pnum_147">27</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> designates a
function.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_148" id="pnum_148">28</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">r</code> designates a user-provided
(<span>9.5.2 <a href="https://wg21.link/dcl.fct.def.default">[dcl.fct.def.default]</a></span>)
function. Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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><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_149" id="pnum_149">29</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> designates a
typed entity. <code class="sourceCode cpp">r</code> does not designate a
constructor, destructor, or structured binding.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_150" id="pnum_150">30</a></span>
<em>Returns</em>: A reflection of the type of that entity. If every
declaration of that entity was declared with the same type alias (but
not a template parameter substituted by a type alias), the reflection
returned is for that alias. Otherwise, if some declaration of that
entity was declared with an alias it is unspecified whether the
reflection returned is for that alias or for the type underlying that
alias. Otherwise, the reflection returned shall not be a type alias
reflection.</p>
<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">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_151" id="pnum_151">31</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating either an object or a variable denoting an object with
static storage duration ([expr.const]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_152" id="pnum_152">32</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> is a
reflection of a variable, then a reflection of the object denoted by the
variable. Otherwise, <code class="sourceCode cpp">r</code>.</p>
<div class="sourceCode" id="cb160"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb160-1"><a href="#cb160-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info value_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_153" id="pnum_153">33</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating either an object or variable usable in constant expressions
([expr.const]), an enumerator, or a value.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_154" id="pnum_154">34</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> is a
reflection of an object <code class="sourceCode cpp">o</code>, or a
reflection of a variable which designates an object
<code class="sourceCode cpp">o</code>, then a reflection of the value
held by <code class="sourceCode cpp">o</code>. The reflected value has
type <code class="sourceCode cpp">dealias<span class="op">(</span>type_of<span class="op">(</span>o<span class="op">))</span></code>,
with the cv-qualifiers removed if this is a scalar type. Otherwise, if
<code class="sourceCode cpp">r</code> is a reflection of an enumerator,
then a reflection of the value of the enumerator. Otherwise,
<code class="sourceCode cpp">r</code>.</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="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_155" id="pnum_155">35</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> designates a
member of either a class or a namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_156" id="pnum_156">36</a></span>
<em>Returns</em>: A reflection of that entity’s immediately enclosing
class or namespace.</p>
<div class="sourceCode" id="cb162"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb162-1"><a href="#cb162-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_157" id="pnum_157">37</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> designates a
type alias or a namespace alias, a reflection designating the underlying
entity. Otherwise, <code class="sourceCode cpp">r</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_158" id="pnum_158">38</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb163"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb163-1"><a href="#cb163-1" aria-hidden="true" tabindex="-1"></a>using X = int;</span>
<span id="cb163-2"><a href="#cb163-2" aria-hidden="true" tabindex="-1"></a>using Y = X;</span>
<span id="cb163-3"><a href="#cb163-3" aria-hidden="true" tabindex="-1"></a>static_assert(dealias(^int) == ^int);</span>
<span id="cb163-4"><a href="#cb163-4" aria-hidden="true" tabindex="-1"></a>static_assert(dealias(^X) == ^int);</span>
<span id="cb163-5"><a href="#cb163-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="cb164"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb164-1"><a href="#cb164-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>
<span id="cb164-2"><a href="#cb164-2" 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_159" id="pnum_159">39</a></span>
<em>Mandates</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_160" id="pnum_160">40</a></span>
<em>Returns</em>: A reflection of the template of
<code class="sourceCode cpp">r</code>, and the reflections of the
template arguments of the specialization designated by
<code class="sourceCode cpp">r</code>, respectively.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_161" id="pnum_161">41</a></span></p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<div class="sourceCode" id="cb165"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb165-1"><a href="#cb165-1" aria-hidden="true" tabindex="-1"></a>template &lt;class T, class U=T&gt; struct Pair { };</span>
<span id="cb165-2"><a href="#cb165-2" aria-hidden="true" tabindex="-1"></a>template &lt;class T&gt; using PairPtr = Pair&lt;T*&gt;;</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>static_assert(template_of(^Pair&lt;int&gt;) == ^Pair);</span>
<span id="cb165-5"><a href="#cb165-5" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(^Pair&lt;int&gt;).size() == 2);</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>static_assert(template_of(^PairPtr&lt;int&gt;) == ^PairPtr);</span>
<span id="cb165-8"><a href="#cb165-8" aria-hidden="true" tabindex="-1"></a>static_assert(template_arguments_of(^PairPtr&lt;int&gt;).size() == 1);</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</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="cb166"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb166-1"><a href="#cb166-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> Fs<span class="op">&gt;</span></span>
<span id="cb166-2"><a href="#cb166-2" 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, Fs<span class="op">...</span> filters<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_162" id="pnum_162">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating either a complete class type or a namespace and <code class="sourceCode cpp"><span class="op">(</span>std<span class="op">::</span>predicate<span class="op">&lt;</span>Fs, info<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <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_163" id="pnum_163">2</a></span>
<em>Effects</em>: If <code class="sourceCode cpp">dealias<span class="op">(</span>r<span class="op">)</span></code>
designates a class template specialization with a reachable definition,
the specialization is instantiated.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_164" id="pnum_164">3</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing the reflections of all the direct members
<code class="sourceCode cpp">m</code> of the entity, excluding any
structured bindings, designated by <code class="sourceCode cpp">r</code>
such that <code class="sourceCode cpp"><span class="op">(</span>filters<span class="op">(</span>m<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
Non-static data members are indexed in the order in which they are
declared, but the order of other kinds of members is unspecified. <span class="note"><span>[ <em>Note 1:</em> </span>Base classes are not
members.<span> — <em>end note</em> ]</span></span></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">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Fs<span class="op">&gt;</span></span>
<span id="cb167-2"><a href="#cb167-2" 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, Fs<span class="op">...</span> filters<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_165" id="pnum_165">4</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">type</code> is a
reflection designating a complete class type and <code class="sourceCode cpp"><span class="op">(</span>std<span class="op">::</span>predicate<span class="op">&lt;</span>Fs, info<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <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_166" id="pnum_166">5</a></span>
<em>Effects</em>: If <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
designates a class template specialization with a reachable definition,
the specialization is instantiated.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_167" id="pnum_167">6</a></span>
<em>Returns</em>: Let <code class="sourceCode cpp">C</code> be the type
designated by <code class="sourceCode cpp">type</code>. A
<code class="sourceCode cpp">vector</code> containing the reflections of
all the direct base classes <code class="sourceCode cpp">b</code>, if
any, of <code class="sourceCode cpp">C</code> such that <code class="sourceCode cpp"><span class="op">(</span>filters<span class="op">(</span>b<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>. The
base classes are indexed in the order in which they appear in the
<em>base-specifier-list</em> of
<code class="sourceCode cpp">C</code>.</p>
<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">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> static_data_members_of<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_168" id="pnum_168">7</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> members_of<span class="op">(</span>type, is_variable<span class="op">)</span>;</code></p>
<div class="sourceCode" id="cb169"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb169-1"><a href="#cb169-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<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_169" id="pnum_169">8</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> members_of<span class="op">(</span>type, is_nonstatic_data_member<span class="op">)</span>;</code></p>
<div class="sourceCode" id="cb170"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb170-1"><a href="#cb170-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> subobjects_of<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_170" id="pnum_170">9</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">type</code> is a
reflection designating a complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_171" id="pnum_171">10</a></span>
<em>Effects</em>: If <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>
designates a class template specialization with a reachable definition,
the specialization is instantiated.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_172" id="pnum_172">11</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing all the reflections in <code class="sourceCode cpp">bases_of<span class="op">(</span>type<span class="op">)</span></code>
followed by all the reflections in <code class="sourceCode cpp">nonstatic_data_members_of<span class="op">(</span>type<span class="op">)</span></code>.</p>
<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">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_173" id="pnum_173">12</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">type_enum</code> is a
reflection designating an enumeration.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_174" id="pnum_174">13</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing the reflections of each enumerator of the enumeration
designated by <code class="sourceCode cpp">type_enum</code>, in the
order in which they are declared.</p>
</div>
</blockquote>
</div>
<h3 data-number="5.2.4" id="meta.reflection.member.access-reflection-member-access-queries"><span class="header-section-number">5.2.4</span>
[meta.reflection.member.access], Reflection member access queries<a href="#meta.reflection.member.access-reflection-member-access-queries" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<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">consteval</span> info access_context<span class="op">()</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_175" id="pnum_175">1</a></span>
<em>Returns</em>: A reflection of the function, class, or namespace
scope most nearly enclosing the function call.</p>
<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">consteval</span> <span class="dt">bool</span> is_accessible<span class="op">(</span>access_pair p<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_176" id="pnum_176">2</a></span>
<em>Mandates</em>:
<code class="sourceCode cpp">p<span class="op">.</span>target</code> is
a reflection designating a member of a class.
<code class="sourceCode cpp">p<span class="op">.</span>from</code>
designates a function, class, or namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_177" id="pnum_177">3</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if the
class member designated by
<code class="sourceCode cpp">p<span class="op">.</span>target</code> can
be named within the scope of
<code class="sourceCode cpp">p<span class="op">.</span>from</code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</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="kw">consteval</span> <span class="dt">bool</span> is_accessible<span class="op">(</span>info target, info from<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_178" id="pnum_178">4</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> is_accessible<span class="op">({</span>target, from<span class="op">})</span>;</code></p>
<div class="sourceCode" id="cb175"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb175-1"><a href="#cb175-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> Preds<span class="op">&gt;</span></span>
<span id="cb175-2"><a href="#cb175-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_members_of<span class="op">(</span>access_pair p,</span>
<span id="cb175-3"><a href="#cb175-3" aria-hidden="true" tabindex="-1"></a>                                               Preds<span class="op">...</span> preds<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_179" id="pnum_179">5</a></span>
<em>Mandates</em>:
<code class="sourceCode cpp">p<span class="op">.</span>target</code> is
a reflection designating a complete class type.
<code class="sourceCode cpp">p<span class="op">.</span>from</code>
designates a function, class, or namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_180" id="pnum_180">6</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> members_of<span class="op">(</span>p<span class="op">.</span>target,</span>
<span id="cb176-2"><a href="#cb176-2" aria-hidden="true" tabindex="-1"></a>                      <span class="op">[&amp;](</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> is_accessible<span class="op">({</span>r, p<span class="op">.</span>from<span class="op">})</span>; <span class="op">}</span>,</span>
<span id="cb176-3"><a href="#cb176-3" aria-hidden="true" tabindex="-1"></a>                      preds<span class="op">...)</span>;</span></code></pre></div>
<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">typename</span><span class="op">...</span> Preds<span class="op">&gt;</span></span>
<span id="cb177-2"><a href="#cb177-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_members_of<span class="op">(</span>info target,</span>
<span id="cb177-3"><a href="#cb177-3" aria-hidden="true" tabindex="-1"></a>                                               info from,</span>
<span id="cb177-4"><a href="#cb177-4" aria-hidden="true" tabindex="-1"></a>                                               Preds<span class="op">...</span> preds<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_181" id="pnum_181">7</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> accessible_members_of<span class="op">({</span>target, from<span class="op">}</span>, preds<span class="op">...)</span>;</code></p>
<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">typename</span><span class="op">...</span> Preds<span class="op">&gt;</span></span>
<span id="cb178-2"><a href="#cb178-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_bases_of<span class="op">(</span>access_pair p,</span>
<span id="cb178-3"><a href="#cb178-3" aria-hidden="true" tabindex="-1"></a>                                             Preds<span class="op">...</span> preds<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_182" id="pnum_182">8</a></span>
<em>Mandates</em>:
<code class="sourceCode cpp">p<span class="op">.</span>target</code> is
a reflection designating a complete class type.
<code class="sourceCode cpp">p<span class="op">.</span>from</code>
designates a function, class, or namespace.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_183" id="pnum_183">9</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> bases_of<span class="op">(</span>p<span class="op">.</span>target,</span>
<span id="cb179-2"><a href="#cb179-2" aria-hidden="true" tabindex="-1"></a>                      <span class="op">[&amp;](</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> is_accessible<span class="op">({</span>r, p<span class="op">.</span>from<span class="op">})</span>; <span class="op">}</span>,</span>
<span id="cb179-3"><a href="#cb179-3" aria-hidden="true" tabindex="-1"></a>                      preds<span class="op">...)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb180"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb180-1"><a href="#cb180-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> Preds<span class="op">&gt;</span></span>
<span id="cb180-2"><a href="#cb180-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_bases_of<span class="op">(</span>info target,</span>
<span id="cb180-3"><a href="#cb180-3" aria-hidden="true" tabindex="-1"></a>                                             info from,</span>
<span id="cb180-4"><a href="#cb180-4" aria-hidden="true" tabindex="-1"></a>                                             Preds<span class="op">...</span> preds<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_184" id="pnum_184">10</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> accessible_bases_of<span class="op">({</span>target, from<span class="op">}</span>, preds<span class="op">...)</span>;</code></p>
<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">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_nonstatic_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_185" id="pnum_185">11</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> accessible_members_of<span class="op">(</span>p<span class="op">.</span>target,</span>
<span id="cb182-2"><a href="#cb182-2" aria-hidden="true" tabindex="-1"></a>                                 std<span class="op">::</span>meta<span class="op">::</span>is_nonstatic_data_member,</span>
<span id="cb182-3"><a href="#cb182-3" aria-hidden="true" tabindex="-1"></a>                                 preds<span class="op">...)</span>;</span></code></pre></div>
<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">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_nonstatic_data_members_of<span class="op">(</span>info target,</span>
<span id="cb183-2"><a href="#cb183-2" aria-hidden="true" tabindex="-1"></a>                                                            info from<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_186" id="pnum_186">12</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> accessible_nonstatic_data_members_of<span class="op">({</span>target, from<span class="op">})</span>;</code></p>
<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> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_static_data_members_of<span class="op">(</span>access_pair p<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_187" id="pnum_187">13</a></span>
<em>Effects</em>: Equivalent to:</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="cf">return</span> accessible_members_of<span class="op">(</span>p<span class="op">.</span>target,</span>
<span id="cb185-2"><a href="#cb185-2" aria-hidden="true" tabindex="-1"></a>                                 std<span class="op">::</span>meta<span class="op">::</span>is_static_data_member<span class="op">)</span>;</span></code></pre></div>
<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> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_static_data_members_of<span class="op">(</span>info target,</span>
<span id="cb186-2"><a href="#cb186-2" aria-hidden="true" tabindex="-1"></a>                                                         info from<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_188" id="pnum_188">14</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> accessible_static_data_members_of<span class="op">({</span>target, from<span class="op">})</span>;</code></p>
<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> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_subobjects_of<span class="op">(</span>access_pair p<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_189" id="pnum_189">15</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing all the reflections in <code class="sourceCode cpp">accessible_bases_of<span class="op">(</span>p<span class="op">)</span></code>
followed by all the reflections in <code class="sourceCode cpp">accessible_nonstatic_data_members_of<span class="op">(</span>p<span class="op">)</span></code>.</p>
<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> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> accessible_subobjects_of<span class="op">(</span>info target, info from<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_190" id="pnum_190">16</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> accessible_subobjects_data_members_of<span class="op">({</span>target, from<span class="op">})</span>;</code></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="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> <span class="dt">size_t</span> 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_191" id="pnum_191">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating a non-static data member or non-virtual base class.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_192" id="pnum_192">2</a></span>
<em>Returns</em>: The offset in bytes from the beginning of an 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 reflected by
<code class="sourceCode cpp">r</code>.</p>
<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">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_193" id="pnum_193">3</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
of a type, non-static data member, base class, object, value, or
variable.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_194" id="pnum_194">4</a></span>
<em>Returns</em> If <code class="sourceCode cpp">r</code> designates a
type <code class="sourceCode cpp">T</code>, then <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span></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>
<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> <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_195" id="pnum_195">5</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating an object, variable, type, non-static data member, or base
class.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_196" id="pnum_196">6</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> designates a
type, object, or variable, then the alignment requirement of the entity.
Otherwise, if <code class="sourceCode cpp">r</code> designates a base
class, then <code class="sourceCode cpp">alignment_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>.
Otherwise, the alignment requirement of the subobject associated with
the reflected non-static data member within any object of type <code class="sourceCode cpp">parent_of<span class="op">(</span>r<span class="op">)</span></code>.</p>
<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> <span class="dt">size_t</span> bit_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_197" id="pnum_197">7</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating a non-static data member or a non-virtual base class.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_198" id="pnum_198">8</a></span>
Let <code class="sourceCode cpp">V</code> be the offset in bits from the
beginning of an 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 reflected by
<code class="sourceCode cpp">r</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_199" id="pnum_199">9</a></span>
<em>Returns</em>: <code class="sourceCode cpp">V <span class="op">-</span> offset_of<span class="op">(</span>r<span class="op">)</span></code>.</p>
<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="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_200" id="pnum_200">10</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
of a type, non-static data member, base class, object, value, or
variable.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_201" id="pnum_201">11</a></span>
<em>Returns</em> If <code class="sourceCode cpp">r</code> designates a
type, then the size in bits of any object having the reflected type.
Otherwise, if <code class="sourceCode cpp">r</code> reflects a
non-static data member that is a bit-field, then the width of the
reflected bit-field. Otherwise, <code class="sourceCode cpp">bit_size_of<span class="op">(</span>type_of<span class="op">(</span>r<span class="op">))</span></code>.</p>
</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">
<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">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb194-2"><a href="#cb194-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_202" id="pnum_202">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">r</code> is a reflection
designating a value, object, variable, function, enumerator, or
non-static data member that is not a bit-field. If
<code class="sourceCode cpp">r</code> reflects a value or enumerator,
then <code class="sourceCode cpp">T</code> is not a reference type. If
<code class="sourceCode cpp">r</code> reflects a value or enumerator of
type <code class="sourceCode cpp">U</code>, or if
<code class="sourceCode cpp">r</code> reflects a variable or object of
non-reference type <code class="sourceCode cpp">U</code>, then the
cv-unqualified types of <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code> are the same. If
<code class="sourceCode cpp">r</code> reflects a variable, object, or
function with type <code class="sourceCode cpp">U</code>, and
<code class="sourceCode cpp">T</code> is a reference type, then the
cv-unqualified types of <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code> are the same, and
<code class="sourceCode cpp">T</code> is either
<code class="sourceCode cpp">U</code> or more cv-qualified than
<code class="sourceCode cpp">U</code>. If
<code class="sourceCode cpp">r</code> reflects a non-static data member,
or if <code class="sourceCode cpp">r</code> reflects a function and
<code class="sourceCode cpp">T</code> is a reference type, then the
statement <code class="sourceCode cpp">T v <span class="op">=</span> <span class="op">&amp;</span>expr</code>,
where <code class="sourceCode cpp">expr</code> is an lvalue naming the
entity designated by <code class="sourceCode cpp">r</code>, is
well-formed.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_203" id="pnum_203">2</a></span>
<em>Returns</em>: If <code class="sourceCode cpp">r</code> designates a
value or enumerator, then the entity reflected by
<code class="sourceCode cpp">r</code>. Otherwise, if
<code class="sourceCode cpp">r</code> reflects an object, variable, or
enumerator and <code class="sourceCode cpp">T</code> is not a reference
type, then the result of an lvalue-to-rvalue conversion applied to an
expression naming the entity reflected by
<code class="sourceCode cpp">r</code>. Otherwise, if
<code class="sourceCode cpp">r</code> reflects an object, variable, or
function and <code class="sourceCode cpp">T</code> is a reference type,
then the result of an lvalue naming the entity reflected by
<code class="sourceCode cpp">r</code>. Otherwise, if
<code class="sourceCode cpp">r</code> reflects a function or non-static
data member, then a pointer value designating the entity reflected by
<code class="sourceCode cpp">r</code>.</p>
</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="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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> R<span class="op">&gt;</span></span>
<span id="cb195-2"><a href="#cb195-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> reflection_range <span class="op">=</span></span>
<span id="cb195-3"><a href="#cb195-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="cb195-4"><a href="#cb195-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="cb195-5"><a href="#cb195-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="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">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb196-2"><a href="#cb196-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_204" id="pnum_204">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">templ</code> designates
a template.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_205" id="pnum_205">2</a></span>
Let <code class="sourceCode cpp">Z</code> be the template designated by
<code class="sourceCode cpp">templ</code> and let
<code class="sourceCode cpp">Args<span class="op">...</span></code> be
the sequence of entities or aliases designated by the elements of
<code class="sourceCode cpp">arguments</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_206" id="pnum_206">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 <em>template-id</em> ([temp.names]). Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_207" id="pnum_207">4</a></span>
<em>Remarks</em>: If attempting to substitute leads to a failure outside
of the immediate context, the program is ill-formed.</p>
<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">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb197-2"><a href="#cb197-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_208" id="pnum_208">5</a></span>
<em>Mandates</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_209" id="pnum_209">6</a></span>
Let <code class="sourceCode cpp">Z</code> be the template designated by
<code class="sourceCode cpp">templ</code> and let
<code class="sourceCode cpp">Args<span class="op">...</span></code> be
the sequence of entities or aliases designated by the elements of
<code class="sourceCode cpp">arguments</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_210" id="pnum_210">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>
<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> test_trait<span class="op">(</span>info templ, info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_211" id="pnum_211">8</a></span>
<em>Effects</em>: Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>substitute<span class="op">(</span>templ, <span class="op">{</span>type<span class="op">}))</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">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</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> test_trait<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_212" id="pnum_212">9</a></span>
<em>Effects</em>: Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> extract<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;(</span>substitute<span class="op">(</span>templ, arguments<span class="op">))</span>;</code></p>
</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">
<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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb200-2"><a href="#cb200-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_value<span class="op">(</span>T expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_213" id="pnum_213">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">T</code> is a structural
type that is not a reference type. Any subobject of the value computed
by <code class="sourceCode cpp">expr</code> having reference or pointer
type designates an entity that is a permitted result of a constant
expression ([expr.const]).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_214" id="pnum_214">2</a></span>
<em>Returns</em>: A reflection of the value computed by an
lvalue-to-rvalue conversion applied to
<code class="sourceCode cpp">expr</code>. The type of the reflected
value is the cv-unqualified version of
<code class="sourceCode cpp">T</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb201-2"><a href="#cb201-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_215" id="pnum_215">3</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">T</code> is not a
function type. <code class="sourceCode cpp">expr</code> designates an
entity that is a permitted result of a constant expression.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_216" id="pnum_216">4</a></span>
<em>Returns</em>: A reflection of the object referenced by
<code class="sourceCode cpp">expr</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb202-2"><a href="#cb202-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> expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_217" id="pnum_217">5</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_218" id="pnum_218">6</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="op">^</span>fn</code>, where
<code class="sourceCode cpp">fn</code> is the function referenced by
<code class="sourceCode cpp">expr</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">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb203-2"><a href="#cb203-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_invoke<span class="op">(</span>info target, R<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span>
<span id="cb203-3"><a href="#cb203-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R1 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;</span>, reflection_range R2 <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb203-4"><a href="#cb203-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_invoke<span class="op">(</span>info target, R1<span class="op">&amp;&amp;</span> tmpl_args, R2<span class="op">&amp;&amp;</span> args<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_219" id="pnum_219">7</a></span>
Let <code class="sourceCode cpp">F</code> be the entity reflected by
<code class="sourceCode cpp">target</code>, let
<code class="sourceCode cpp">Arg0</code> be the entity reflected by the
first element of <code class="sourceCode cpp">args</code> (if any), let
<code class="sourceCode cpp">Args<span class="op">...</span></code> be
the sequence of entities reflected by the elements of
<code class="sourceCode cpp">args</code> excluding the first, and let
<code class="sourceCode cpp">TArgs<span class="op">...</span></code> be
the sequence of entities or aliases designated by the elements of
<code class="sourceCode cpp">tmpl_args</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_220" id="pnum_220">8</a></span>
If <code class="sourceCode cpp">F</code> is a non-member function, a
value of pointer to function type, a value of pointer to member type, or
a value of closure type, then let
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
be the expression <code class="sourceCode cpp">INVOKE<span class="op">(</span>F, Arg0, Args<span class="op">...)</span></code>.
Otherwise, if <code class="sourceCode cpp">F</code> is a member
function, then let
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
be the expression <code class="sourceCode cpp">Arg0<span class="op">.</span>F<span class="op">(</span>Args<span class="op">...)</span></code>.
Otherwise, if <code class="sourceCode cpp">F</code> is a constructor for
a class <code class="sourceCode cpp">C</code>, then let
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
be the expression <code class="sourceCode cpp">C<span class="op">(</span>Arg0, Args<span class="op">...)</span></code>
for which only the constructor <code class="sourceCode cpp">F</code> is
considered by overload resolution. Otherwise, if
<code class="sourceCode cpp">F</code> is a non-member function template
or a member function template, then let
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
be the expression <code class="sourceCode cpp">F<span class="op">&lt;</span>TArgs<span class="op">...&gt;(</span>Arg0, Args<span class="op">...)</span></code>
or <code class="sourceCode cpp">Arg0<span class="op">.</span><span class="kw">template</span> F<span class="op">&lt;</span>TArgs<span class="op">...&gt;(</span>Args<span class="op">...)</span></code>
respectively. Otherwise, if <code class="sourceCode cpp">F</code> is a
constructor template, then let
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
be the expression <code class="sourceCode cpp">C<span class="op">(</span>Arg0, Args<span class="op">...)</span></code>
for which only the constructor <code class="sourceCode cpp">F</code> is
considered by overload resolution, and
<code class="sourceCode cpp">TArgs<span class="op">...</span></code> are
inferred as explicit template arguments for
<code class="sourceCode cpp">F</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_221" id="pnum_221">9</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">target</code> designates
a reflection of a function, a constructor, a constructor template, a
value, or a function template. If
<code class="sourceCode cpp">target</code> reflects a value of type
<code class="sourceCode cpp">T</code>, then
<code class="sourceCode cpp">T</code> is a pointer to function type,
pointer to member type, or closure type. The expression
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>
is a well-formed constant expression of structural type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_222" id="pnum_222">10</a></span>
<em>Returns</em>: A reflection of the result of the expression
<code class="sourceCode cpp">INVOKE<span class="op">-</span>EXPR</code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.define_class-reflection-class-definition-generation">[meta.reflection.define_class]
Reflection class definition generation<a href="#meta.reflection.define_class-reflection-class-definition-generation" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<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> info data_member_spec<span class="op">(</span>info type,</span>
<span id="cb204-2"><a href="#cb204-2" aria-hidden="true" tabindex="-1"></a>                                data_member_options_t options <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_223" id="pnum_223">1</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">type</code> designates a
type. If
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
contains a value, the <code class="sourceCode cpp">string</code> or
<code class="sourceCode cpp">u8string</code> value that was used to
initialize
<code class="sourceCode cpp">options<span class="op">.</span>name</code>
contains a valid identifier (<span>5.10 <a href="https://wg21.link/lex.name">[lex.name]</a></span>).</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_224" id="pnum_224">2</a></span>
<em>Returns</em>: A reflection of a description of the declaration of
non-static data member with a type designated by
<code class="sourceCode cpp">type</code> and optional characteristics
designated by <code class="sourceCode cpp">options</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_225" id="pnum_225">3</a></span>
<em>Remarks</em>: The reflection value being returned is only useful for
consumption by <code class="sourceCode cpp">define_class</code>. No
other function in
<code class="sourceCode cpp">std<span class="op">::</span>meta</code>
recognizes such a value.</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">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb205-2"><a href="#cb205-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info define_class<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_226" id="pnum_226">4</a></span>
Let <code class="sourceCode cpp"><em>d</em><sub>1</sub></code>,
<code class="sourceCode cpp"><em>d</em><sub>2</sub></code>, …,
<code class="sourceCode cpp"><em>d</em><sub>N</sub></code> denote the
reflection values of the range
<code class="sourceCode cpp">mdescrs</code> obtained by calling
<code class="sourceCode cpp">data_member_spec</code> with
<code class="sourceCode cpp">type</code> values
<code class="sourceCode cpp"><em>t</em><sub>1</sub></code>,
<code class="sourceCode cpp"><em>t</em><sub>2</sub></code>, …
<code class="sourceCode cpp"><em>t</em><sub>N</sub></code> and
<code class="sourceCode cpp">option</code> values
<code class="sourceCode cpp"><em>o</em><sub>1</sub></code>,
<code class="sourceCode cpp"><em>o</em><sub>2</sub></code>, …
<code class="sourceCode cpp"><em>o</em><sub>N</sub></code>
respectively.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_227" id="pnum_227">5</a></span>
<em>Mandates</em>: <code class="sourceCode cpp">class_type</code>
designates an incomplete class type.
<code class="sourceCode cpp">mdescrs</code> is a (possibly empty) range
of reflection values obtained by calls to
<code class="sourceCode cpp">data_member_spec</code>. <span class="note"><span>[ <em>Note 1:</em> </span>For example,
<code class="sourceCode cpp">class_type</code> could be a specialization
of a class template that has not been instantiated or explicitly
specialized.<span> — <em>end note</em> ]</span></span> Each
<code class="sourceCode cpp"><em>t</em><sub>i</sub></code> designates a
type that is valid types for data members. If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>width</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) contains a
value <code class="sourceCode cpp"><em>w</em></code>, the corresponding
type <code class="sourceCode cpp"><em>t</em><sub>K</sub></code> is a
valid type for bit field of width
<code class="sourceCode cpp"><em>w</em></code>. If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>alignment</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) contains a
value <code class="sourceCode cpp"><em>a</em></code>, <code class="sourceCode cpp"><span class="kw">alignas</span><span class="op">(</span><em>a</em><span class="op">)</span></code>
is a valid
<code class="sourceCode cpp"><em>alignment-specifier</em></code> for a
non-static data member of type
<code class="sourceCode cpp"><em>t</em><sub>K</sub></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_228" id="pnum_228">6</a></span>
<em>Effects</em>: Defines <code class="sourceCode cpp">class_type</code>
with properties as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_229" id="pnum_229">(6.1)</a></span>
If <code class="sourceCode cpp">class_type</code> designates a
specialization of a class template, the specialization is explicitly
specialized.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_230" id="pnum_230">(6.2)</a></span>
Non-static data members are declared in the definition of
<code class="sourceCode cpp">class_type</code> according to
<code class="sourceCode cpp"><em>d</em><sub>1</sub></code>,
<code class="sourceCode cpp"><em>d</em><sub>2</sub></code>, …,
<code class="sourceCode cpp"><em>d</em><sub>N</sub></code>, in that
order.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_231" id="pnum_231">(6.3)</a></span>
The type of the respective members are the types denoted by the
reflection values
<code class="sourceCode cpp"><em>t</em><sub>1</sub></code>,
<code class="sourceCode cpp"><em>t</em><sub>2</sub></code>, …
<code class="sourceCode cpp"><em>t</em><sub>N</sub></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_232" id="pnum_232">(6.4)</a></span>
If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>no_unique_address</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) is
<code class="sourceCode cpp"><span class="kw">true</span></code>, the
corresponding member is declared with attribute <code class="sourceCode cpp"><span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_233" id="pnum_233">(6.5)</a></span>
If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>width</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) contains a
value, the corresponding member is declared as a bit field with that
value as its width.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_234" id="pnum_234">(6.6)</a></span>
If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>alignment</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) contains a
value <code class="sourceCode cpp"><em>a</em></code>, the corresponding
member is aligned as if declared with <code class="sourceCode cpp"><span class="kw">alignas</span><span class="op">(</span><em>a</em><span class="op">)</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_235" id="pnum_235">(6.7)</a></span>
If <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>name</code>
(for some <code class="sourceCode cpp"><em>K</em></code>) does not
contain a value, the corresponding member is declared with an
implementation-defined name. Otherwise, the corresponding member is
declared with a name corresponding to the
<code class="sourceCode cpp">string</code> or
<code class="sourceCode cpp">u8string</code> value that was used to
initialize <code class="sourceCode cpp"><em>o</em><sub>K</sub><span class="op">.</span>name</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_236" id="pnum_236">(6.8)</a></span>
If <code class="sourceCode cpp">class_type</code> is a union type and
any of its members is not trivially default constructible, then it has a
default constructor that is user-provided and has no effect. If
<code class="sourceCode cpp">class_type</code> is a union type and any
of its members is not trivially default destructible, then it has a
default destructor that is user-provided and has no effect.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_237" id="pnum_237">7</a></span>
<em>Returns</em>: <code class="sourceCode cpp">class_type</code>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.unary-unary-type-traits">[meta.reflection.unary]
Unary type traits<a href="#meta.reflection.unary-unary-type-traits" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_238" id="pnum_238">1</a></span>
Subclause [meta.reflection.unary] contains consteval functions that may
be used to query the properties of a type at compile time.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_239" id="pnum_239">2</a></span>
For each function taking an argument of type
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>
whose name contains <code class="sourceCode cpp">type</code>, a call to
the function is a non-constant library call (<span>3.34 <a href="https://wg21.link/defns.nonconst.libcall">[defns.nonconst.libcall]</a></span>)
if that argument is not a reflection of a type or type alias. For each
function taking an argument named
<code class="sourceCode cpp">type_args</code>, a call to the function is
a non-constant library call if any
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>
in that range is not a reflection of a type or a type alias.</p>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.unary.cat-primary-type-categories">[meta.reflection.unary.cat]
Primary type categories<a href="#meta.reflection.unary.cat-primary-type-categories" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_240" id="pnum_240">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>TRAIT</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>TRAIT</em><span class="op">(^</span>T<span class="op">)</span></code>
equals the value of the corresponding unary type trait <code class="sourceCode cpp">std<span class="op">::</span><em>TRAIT</em>_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.5.2 <a href="https://wg21.link/meta.unary.cat">[meta.unary.cat]</a></span>.</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> type_is_void<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-2"><a href="#cb206-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_null_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-3"><a href="#cb206-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_integral<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-4"><a href="#cb206-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_floating_point<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-5"><a href="#cb206-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_array<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-6"><a href="#cb206-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-7"><a href="#cb206-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_lvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-8"><a href="#cb206-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_rvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-9"><a href="#cb206-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_member_object_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-10"><a href="#cb206-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_member_function_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-11"><a href="#cb206-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_enum<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-12"><a href="#cb206-12" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_union<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-13"><a href="#cb206-13" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_class<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-14"><a href="#cb206-14" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_function<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb206-15"><a href="#cb206-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_reflection<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_241" id="pnum_241">2</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb207"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb207-1"><a href="#cb207-1" aria-hidden="true" tabindex="-1"></a>namespace std::meta {</span>
<span id="cb207-2"><a href="#cb207-2" aria-hidden="true" tabindex="-1"></a>  consteval bool type_is_void(info type) {</span>
<span id="cb207-3"><a href="#cb207-3" aria-hidden="true" tabindex="-1"></a>    // one example implementation</span>
<span id="cb207-4"><a href="#cb207-4" aria-hidden="true" tabindex="-1"></a>    return extract&lt;bool&gt;(substitute(^is_void_v, {type}));</span>
<span id="cb207-5"><a href="#cb207-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb207-6"><a href="#cb207-6" aria-hidden="true" tabindex="-1"></a>    // another example implementation</span>
<span id="cb207-7"><a href="#cb207-7" aria-hidden="true" tabindex="-1"></a>    type = dealias(type);</span>
<span id="cb207-8"><a href="#cb207-8" aria-hidden="true" tabindex="-1"></a>    return type == ^void</span>
<span id="cb207-9"><a href="#cb207-9" aria-hidden="true" tabindex="-1"></a>        || type == ^const void</span>
<span id="cb207-10"><a href="#cb207-10" aria-hidden="true" tabindex="-1"></a>        || type == ^volatile void</span>
<span id="cb207-11"><a href="#cb207-11" aria-hidden="true" tabindex="-1"></a>        || type == ^const volatile void;</span>
<span id="cb207-12"><a href="#cb207-12" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb207-13"><a href="#cb207-13" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.unary.comp-composite-type-categories">[meta.reflection.unary.comp]
Composite type categories<a href="#meta.reflection.unary.comp-composite-type-categories" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_242" id="pnum_242">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>TRAIT</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>TRAIT</em><span class="op">(^</span>T<span class="op">)</span></code>
equals the value of the corresponding unary type trait <code class="sourceCode cpp">std<span class="op">::</span><em>TRAIT</em>_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.5.3 <a href="https://wg21.link/meta.unary.comp">[meta.unary.comp]</a></span>.</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> type_is_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-2"><a href="#cb208-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_arithmetic<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-3"><a href="#cb208-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_fundamental<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-4"><a href="#cb208-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_object<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-5"><a href="#cb208-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_scalar<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-6"><a href="#cb208-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_compound<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb208-7"><a href="#cb208-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_member_pointer<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.unary.prop-type-properties">[meta.reflection.unary.prop]
Type properties<a href="#meta.reflection.unary.prop-type-properties" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_243" id="pnum_243">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>UNARY-TRAIT</em></code>
defined in this clause with signature <code class="sourceCode cpp"><span class="dt">bool</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>UNARY-TRAIT</em><span class="op">(^</span>T<span class="op">)</span></code>
equals the value of the corresponding type property <code class="sourceCode cpp">std<span class="op">::</span><em>UNARY-TRAIT</em>_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.5.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_244" id="pnum_244">2</a></span>
For any types or type aliases <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code>, for each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>BINARY-TRAIT</em></code>
defined in this clause with signature <code class="sourceCode cpp"><span class="dt">bool</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info, std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>BINARY-TRAIT</em><span class="op">(^</span>T, <span class="op">^</span>U<span class="op">)</span></code>
equals the value of the corresponding type property <code class="sourceCode cpp">std<span class="op">::</span><em>BINARY-TRAIT</em>_v<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code>
as specified in <span>21.3.5.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_245" id="pnum_245">3</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, pack
of types or type aliases
<code class="sourceCode cpp">U<span class="op">...</span></code>, and
range <code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;(</span>r<span class="op">)</span> <span class="op">==</span> vector<span class="op">{^</span>U<span class="op">...}</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, for
each function template <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-TRAIT</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-TRAIT</em><span class="op">(^</span>T, r<span class="op">)</span></code>
equals the value of the corresponding type property <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC-TRAIT</em>_v<span class="op">&lt;</span>T, U<span class="op">...&gt;</span></code>
as specified in <span>21.3.5.4 <a href="https://wg21.link/meta.unary.prop">[meta.unary.prop]</a></span>.</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> type_is_const<span class="op">(</span>info type<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> type_is_volatile<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-3"><a href="#cb209-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivial<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-4"><a href="#cb209-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_copyable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-5"><a href="#cb209-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_standard_layout<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-6"><a href="#cb209-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_empty<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-7"><a href="#cb209-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_polymorphic<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-8"><a href="#cb209-8" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_abstract<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-9"><a href="#cb209-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_final<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-10"><a href="#cb209-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_aggregate<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-11"><a href="#cb209-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_signed<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-12"><a href="#cb209-12" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_unsigned<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-13"><a href="#cb209-13" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_bounded_array<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-14"><a href="#cb209-14" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_unbounded_array<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-15"><a href="#cb209-15" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_scoped_enum<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-16"><a href="#cb209-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-17"><a href="#cb209-17" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb209-18"><a href="#cb209-18" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_constructible<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb209-19"><a href="#cb209-19" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_default_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-20"><a href="#cb209-20" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_copy_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-21"><a href="#cb209-21" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_move_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-22"><a href="#cb209-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-23"><a href="#cb209-23" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_assignable<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-24"><a href="#cb209-24" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_copy_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-25"><a href="#cb209-25" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_move_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-26"><a href="#cb209-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-27"><a href="#cb209-27" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_swappable_with<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-28"><a href="#cb209-28" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_swappable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-29"><a href="#cb209-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-30"><a href="#cb209-30" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_destructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-31"><a href="#cb209-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-32"><a href="#cb209-32" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb209-33"><a href="#cb209-33" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_constructible<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb209-34"><a href="#cb209-34" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_default_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-35"><a href="#cb209-35" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_copy_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-36"><a href="#cb209-36" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_move_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-37"><a href="#cb209-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-38"><a href="#cb209-38" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_assignable<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-39"><a href="#cb209-39" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_copy_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-40"><a href="#cb209-40" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_move_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-41"><a href="#cb209-41" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_trivially_destructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-42"><a href="#cb209-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-43"><a href="#cb209-43" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb209-44"><a href="#cb209-44" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_constructible<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb209-45"><a href="#cb209-45" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_default_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-46"><a href="#cb209-46" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_copy_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-47"><a href="#cb209-47" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_move_constructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-48"><a href="#cb209-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-49"><a href="#cb209-49" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_assignable<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-50"><a href="#cb209-50" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_copy_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-51"><a href="#cb209-51" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_move_assignable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-52"><a href="#cb209-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-53"><a href="#cb209-53" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_swappable_with<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-54"><a href="#cb209-54" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_swappable<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-55"><a href="#cb209-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-56"><a href="#cb209-56" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_destructible<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-57"><a href="#cb209-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-58"><a href="#cb209-58" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_implicit_lifetime<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-59"><a href="#cb209-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-60"><a href="#cb209-60" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_has_virtual_destructor<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-61"><a href="#cb209-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-62"><a href="#cb209-62" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_has_unique_object_representations<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb209-63"><a href="#cb209-63" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb209-64"><a href="#cb209-64" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_reference_constructs_from_temporary<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span>
<span id="cb209-65"><a href="#cb209-65" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_reference_converts_from_temporary<span class="op">(</span>info type_dst, info type_src<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.unary.prop.query-type-property-queries">[meta.reflection.unary.prop.query]
Type property queries<a href="#meta.reflection.unary.prop.query-type-property-queries" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_246" id="pnum_246">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>PROP</em></code>
defined in this clause with signature <code class="sourceCode cpp"><span class="dt">size_t</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>PROP</em><span class="op">(^</span>T<span class="op">)</span></code>
equals the value of the corresponding type property <code class="sourceCode cpp">std<span class="op">::</span><em>PROP</em>_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.6 <a href="https://wg21.link/meta.unary.prop.query">[meta.unary.prop.query]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_247" id="pnum_247">2</a></span>
For any type or type alias <code class="sourceCode cpp">T</code> and
unsigned integer value <code class="sourceCode cpp">I</code>, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_extent<span class="op">(^</span>T, I<span class="op">)</span></code>
equals <code class="sourceCode cpp">std<span class="op">::</span>extent_v<span class="op">&lt;</span>T, I<span class="op">&gt;</span></code>
([meta.unary.prop.query]).</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">size_t</span> type_alignment_of<span class="op">(</span>info type<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">size_t</span> type_rank<span class="op">(</span>info type<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">size_t</span> type_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>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.rel-type-relations">[meta.reflection.rel], Type
relations<a href="#meta.reflection.rel-type-relations" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_248" id="pnum_248">1</a></span>
The consteval functions specified in this clause may be used to query
relationships between types at compile time.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_249" id="pnum_249">2</a></span>
For any types or type aliases <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code>, for each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>REL</em></code>
defined in this clause with signature <code class="sourceCode cpp"><span class="dt">bool</span><span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info, std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>REL</em><span class="op">(^</span>T, <span class="op">^</span>U<span class="op">)</span></code>
equals the value of the corresponding type relation <code class="sourceCode cpp">std<span class="op">::</span><em>REL</em>_v<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code>
as specified in <span>21.3.7 <a href="https://wg21.link/meta.rel">[meta.rel]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_250" id="pnum_250">3</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, pack
of types or type aliases
<code class="sourceCode cpp">U<span class="op">...</span></code>, and
range <code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;(</span>r<span class="op">)</span> <span class="op">==</span> vector<span class="op">{^</span>U<span class="op">...}</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, for
each binary function template <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-REL</em></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-REL</em><span class="op">(^</span>T, r<span class="op">)</span></code>
equals the value of the corresponding type relation <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC-REL</em>_v<span class="op">&lt;</span>T, U<span class="op">...&gt;</span></code>
as specified in <span>21.3.7 <a href="https://wg21.link/meta.rel">[meta.rel]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_251" id="pnum_251">4</a></span>
For any types or type aliases <code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">R</code>, pack of types or type aliases
<code class="sourceCode cpp">U<span class="op">...</span></code>, and
range <code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;(</span>r<span class="op">)</span> <span class="op">==</span> vector<span class="op">{^</span>U<span class="op">...}</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, for
each ternary function template <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-REL-R</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-REL-R</em><span class="op">(^</span>R, <span class="op">^</span>T, r<span class="op">)</span></code>
equals the value of the corresponding type relation <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC-REL-R</em>_v<span class="op">&lt;</span>R, T, U<span class="op">...&gt;</span></code>
as specified in <span>21.3.7 <a href="https://wg21.link/meta.rel">[meta.rel]</a></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> type_is_same<span class="op">(</span>info type1, info type2<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> type_is_base_of<span class="op">(</span>info type_base, info type_derived<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> type_is_convertible<span class="op">(</span>info type_src, info type_dst<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> type_is_nothrow_convertible<span class="op">(</span>info type_src, info type_dst<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> type_is_layout_compatible<span class="op">(</span>info type1, info type2<span class="op">)</span>;</span>
<span id="cb211-6"><a href="#cb211-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_pointer_interconvertible_base_of<span class="op">(</span>info type_base, info type_derived<span class="op">)</span>;</span>
<span id="cb211-7"><a href="#cb211-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb211-8"><a href="#cb211-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb211-9"><a href="#cb211-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_invocable<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb211-10"><a href="#cb211-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb211-11"><a href="#cb211-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_invocable_r<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="cb211-12"><a href="#cb211-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb211-13"><a href="#cb211-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb211-14"><a href="#cb211-14" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_invocable<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb211-15"><a href="#cb211-15" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb211-16"><a href="#cb211-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> type_is_nothrow_invocable_r<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_252" id="pnum_252">5</a></span>
<span class="note"><span>[ <em>Note 1:</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">type_is_same<span class="op">(</span>t, u<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>.
<code class="sourceCode cpp">t <span class="op">==</span> dealias<span class="op">(</span>u<span class="op">)</span></code>
is also
<code class="sourceCode cpp"><span class="kw">true</span></code>.<span>
— <em>end note</em> ]</span></span>.</p>
</div>
</blockquote>
</div>
<h3 class="unnumbered" id="meta.reflection.trans-transformations-between-types">[meta.reflection.trans],
Transformations between types<a href="#meta.reflection.trans-transformations-between-types" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_253" id="pnum_253">1</a></span>
Subclause [meta.reflection.trans] contains consteval functions that may
be used to transform one type to another following some predefined
rule.</p>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.cv-const-volatile-modifications">[meta.reflection.trans.cv],
Const-volatile modifications<a href="#meta.reflection.trans.cv-const-volatile-modifications" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_254" id="pnum_254">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.2 <a href="https://wg21.link/meta.trans.cv">[meta.trans.cv]</a></span>.</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> info type_remove_const<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb212-2"><a href="#cb212-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_remove_volatile<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb212-3"><a href="#cb212-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_remove_cv<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb212-4"><a href="#cb212-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_const<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb212-5"><a href="#cb212-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_volatile<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb212-6"><a href="#cb212-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_cv<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.ref-reference-modifications">[meta.reflection.trans.ref],
Reference modifications<a href="#meta.reflection.trans.ref-reference-modifications" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_255" id="pnum_255">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.3 <a href="https://wg21.link/meta.trans.ref">[meta.trans.ref]</a></span>.</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> info type_remove_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb213-2"><a href="#cb213-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_lvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb213-3"><a href="#cb213-3" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_rvalue_reference<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.sign-sign-modifications">[meta.reflection.trans.sign],
Sign modifications<a href="#meta.reflection.trans.sign-sign-modifications" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_256" id="pnum_256">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.4 <a href="https://wg21.link/meta.trans.sign">[meta.trans.sign]</a></span>.</p>
<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">consteval</span> info type_make_signed<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb214-2"><a href="#cb214-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_make_unsigned<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.arr-array-modifications">[meta.reflection.trans.arr],
Array modifications<a href="#meta.reflection.trans.arr-array-modifications" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_257" id="pnum_257">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.5 <a href="https://wg21.link/meta.trans.arr">[meta.trans.arr]</a></span>.</p>
<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> info type_remove_extent<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb215-2"><a href="#cb215-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_remove_all_extents<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.ptr-pointer-modifications">[meta.reflection.trans.ptr],
Pointer modifications<a href="#meta.reflection.trans.ptr-pointer-modifications" class="self-link"></a></h4>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_258" id="pnum_258">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.6 <a href="https://wg21.link/meta.trans.ptr">[meta.trans.ptr]</a></span>.</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> info type_remove_pointer<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb216-2"><a href="#cb216-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_add_pointer<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h4 class="unnumbered" id="meta.reflection.trans.other-other-transformations">[meta.reflection.trans.other],
Other transformations<a href="#meta.reflection.trans.other-other-transformations" class="self-link"></a></h4>
<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">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_259" id="pnum_259">1</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, for
each function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em></code>
defined in this clause with signature <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">)</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>MOD</em><span class="op">(^</span>T<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>MOD</em>_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as specified in <span>21.3.8.7 <a href="https://wg21.link/meta.trans.other">[meta.trans.other]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_260" id="pnum_260">2</a></span>
For any pack of types or type aliases
<code class="sourceCode cpp">T<span class="op">...</span></code> and
range <code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;(</span>r<span class="op">)</span> <span class="op">==</span> vector<span class="op">{^</span>T<span class="op">...}</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, for
each unary function template <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-MOD</em></code>
defined in this clause, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_<em>VARIADIC-MOD</em><span class="op">(</span>r<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span><em>VARIADIC-MOD</em>_t<span class="op">&lt;</span>T<span class="op">...&gt;</span></code>
as specified in <span>21.3.8.7 <a href="https://wg21.link/meta.trans.other">[meta.trans.other]</a></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_261" id="pnum_261">3</a></span>
For any type or type alias <code class="sourceCode cpp">T</code>, pack
of types or type aliases
<code class="sourceCode cpp">U<span class="op">...</span></code>, and
range <code class="sourceCode cpp">r</code> such that <code class="sourceCode cpp">ranges<span class="op">::</span>to<span class="op">&lt;</span>vector<span class="op">&gt;(</span>r<span class="op">)</span> <span class="op">==</span> vector<span class="op">{^</span>U<span class="op">...}</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>type_invoke_result<span class="op">(^</span>T, r<span class="op">)</span></code>
returns the reflection of the corresponding type <code class="sourceCode cpp">std<span class="op">::</span>invoke_result_t<span class="op">&lt;</span>T, U<span class="op">...&gt;</span></code>
(<span>21.3.8.7 <a href="https://wg21.link/meta.trans.other">[meta.trans.other]</a></span>).</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> info type_remove_cvref<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb217-2"><a href="#cb217-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_decay<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb217-3"><a href="#cb217-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb217-4"><a href="#cb217-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_common_type<span class="op">(</span>R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb217-5"><a href="#cb217-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb217-6"><a href="#cb217-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_common_reference<span class="op">(</span>R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb217-7"><a href="#cb217-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_underlying_type<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb217-8"><a href="#cb217-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>reflection_range R <span class="op">=</span> span<span class="op">&lt;</span>info <span class="kw">const</span><span class="op">&gt;&gt;</span></span>
<span id="cb217-9"><a href="#cb217-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_invoke_result<span class="op">(</span>info type, R<span class="op">&amp;&amp;</span> type_args<span class="op">)</span>;</span>
<span id="cb217-10"><a href="#cb217-10" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_unwrap_reference<span class="op">(</span>info type<span class="op">)</span>;</span>
<span id="cb217-11"><a href="#cb217-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_unwrap_ref_decay<span class="op">(</span>info type<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_262" id="pnum_262">4</a></span></p>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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="co">// example implementation</span></span>
<span id="cb218-2"><a href="#cb218-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> info type_unwrap_reference<span class="op">(</span>info type<span class="op">)</span> <span class="op">{</span></span>
<span id="cb218-3"><a href="#cb218-3" aria-hidden="true" tabindex="-1"></a>  type <span class="op">=</span> dealias<span class="op">(</span>type<span class="op">)</span>;</span>
<span id="cb218-4"><a href="#cb218-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>has_template_arguments<span class="op">(</span>type<span class="op">)</span> <span class="op">&amp;&amp;</span> template_of<span class="op">(</span>type<span class="op">)</span> <span class="op">==</span> <span class="op">^</span>reference_wrapper<span class="op">)</span> <span class="op">{</span></span>
<span id="cb218-5"><a href="#cb218-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> type_add_lvalue_reference<span class="op">(</span>template_arguments_of<span class="op">(</span>type<span class="op">)[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb218-6"><a href="#cb218-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb218-7"><a href="#cb218-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> type;</span>
<span id="cb218-8"><a href="#cb218-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb218-9"><a href="#cb218-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
</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.11 <a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb219"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb219-1"><a href="#cb219-1" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_coroutine 201902L</span>
<span id="cb219-2"><a href="#cb219-2" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_destroying_delete 201806L</span>
<span id="cb219-3"><a href="#cb219-3" aria-hidden="true" tabindex="-1"></a>  __cpp_impl_three_way_comparison 201907L</span>
<span id="cb219-4"><a href="#cb219-4" aria-hidden="true" tabindex="-1"></a><span class="va">+ __cpp_impl_reflection 2024XXL</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="cb220"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb220-1"><a href="#cb220-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ #define __cpp_lib_reflection 2024XXL // also in &lt;meta&gt;</span></span></code></pre></div>
</div>
</blockquote>
</div>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">6</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-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-P1061R5" class="csl-entry" role="doc-biblioentry">
[P1061R5] Barry Revzin, Jonathan Wakely. 2023-05-18. Structured Bindings
can introduce a Pack. <a href="https://wg21.link/p1061r5"><div class="csl-block">https://wg21.link/p1061r5</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] Andrew Sutton, Sam Goodrick, Daveed Vandevoorde, and Dan Katz.
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-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-P2758R1" class="csl-entry" role="doc-biblioentry">
[P2758R1] Barry Revzin. 2023-12-09. Emitting messages at compile time.
<a href="https://wg21.link/p2758r1"><div class="csl-block">https://wg21.link/p2758r1</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-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-P3068R1" class="csl-entry" role="doc-biblioentry">
[P3068R1] Hana Dusíková. 2024-03-18. Allowing exception throwing in
constant-evaluation. <a href="https://wg21.link/p3293r0"><div class="csl-block">https://wg21.link/p3293r0</div></a>
</div>
<div id="ref-P3096R1" class="csl-entry" role="doc-biblioentry">
[P3096R1] Adam Lach and Walter Genovese. 2024-04-29. Function Parameter
Reflection in Reflection for C++26. <a href="https://wg21.link/p3096r1"><div class="csl-block">https://wg21.link/p3096r1</div></a>
</div>
<div id="ref-P3293R0" class="csl-entry" role="doc-biblioentry">
[P3293R0] Peter Dimov, Dan Katz, Barry Revzin, and Daveed Vandevoorde.
2024-05-19. Splicing a base class subobject. <a href="https://wg21.link/p3293r0"><div class="csl-block">https://wg21.link/p3293r0</div></a>
</div>
<div id="ref-P3295R0" class="csl-entry" role="doc-biblioentry">
[P3295R0] Ben Craig. 2024-05-18. 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>
</div>
</div>
</body>
</html>
