<!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-10-16" />
  <title>Reflection of Templates</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 of Templates</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3240R0 <a href="https://wg21.link/P3240">[Latest]</a> <a href="https://wg21.link/P3240/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-10-16</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<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
      Andrei Alexandrescu, NVIDIA<br>&lt;<a href="mailto:andrei@nvidia.com" class="email">andrei@nvidia.com</a>&gt;<br>
      Daveed Vandevoorde, EDG<br>&lt;<a href="mailto:daveed@edg.com" class="email">daveed@edg.com</a>&gt;<br>
      Michael Garland, NVIDIA<br>&lt;<a href="mailto:mgarland@nvidia.com" class="email">mgarland@nvidia.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">1</span> Motivation<span></span></a>
<ul>
<li><a href="#the-as-if-rule-for-token-sequences-returned-by-reflection-metafunctions" id="toc-the-as-if-rule-for-token-sequences-returned-by-reflection-metafunctions"><span class="toc-section-number">1.1</span> The “As-If” Rule for Token
Sequences Returned by Reflection Metafunctions<span></span></a></li>
<li><a href="#example-logging-and-forwarding" id="toc-example-logging-and-forwarding"><span class="toc-section-number">1.2</span> Example: Logging and
Forwarding<span></span></a></li>
</ul></li>
<li><a href="#metafunctions-for-template-declarations" id="toc-metafunctions-for-template-declarations"><span class="toc-section-number">2</span> Metafunctions for Template
Declarations<span></span></a>
<ul>
<li><a href="#synopsis" id="toc-synopsis"><span class="toc-section-number">2.1</span> Synopsis<span></span></a>
<ul>
<li><a href="#template_alternatives_of" id="toc-template_alternatives_of"><span class="toc-section-number">2.1.1</span>
<code class="sourceCode cpp">template_alternatives_of</code><span></span></a></li>
<li><a href="#template_parameters_of-template_parameter_prefix" id="toc-template_parameters_of-template_parameter_prefix"><span class="toc-section-number">2.1.2</span>
<code class="sourceCode cpp">template_parameters_of</code>,
<code class="sourceCode cpp">template_parameter_prefix</code><span></span></a></li>
<li><a href="#attributes_of" id="toc-attributes_of"><span class="toc-section-number">2.1.3</span>
<code class="sourceCode cpp">attributes_of</code><span></span></a></li>
<li><a href="#requires_clause_of" id="toc-requires_clause_of"><span class="toc-section-number">2.1.4</span>
<code class="sourceCode cpp">requires_clause_of</code><span></span></a></li>
<li><a href="#is_primary_template" id="toc-is_primary_template"><span class="toc-section-number">2.1.5</span>
<code class="sourceCode cpp">is_primary_template</code><span></span></a></li>
<li><a href="#specialization_arguments_of" id="toc-specialization_arguments_of"><span class="toc-section-number">2.1.6</span>
<code class="sourceCode cpp">specialization_arguments_of</code><span></span></a></li>
<li><a href="#template_bases_of" id="toc-template_bases_of"><span class="toc-section-number">2.1.7</span>
<code class="sourceCode cpp">template_bases_of</code><span></span></a></li>
<li><a href="#template_data_type" id="toc-template_data_type"><span class="toc-section-number">2.1.8</span>
<code class="sourceCode cpp">template_data_type</code><span></span></a></li>
<li><a href="#template_data_initializer" id="toc-template_data_initializer"><span class="toc-section-number">2.1.9</span>
<code class="sourceCode cpp">template_data_initializer</code><span></span></a></li>
<li><a href="#alias_template_declarator" id="toc-alias_template_declarator"><span class="toc-section-number">2.1.10</span>
<code class="sourceCode cpp">alias_template_declarator</code><span></span></a></li>
<li><a href="#overloads_of" id="toc-overloads_of"><span class="toc-section-number">2.1.11</span>
<code class="sourceCode cpp">overloads_of</code><span></span></a></li>
<li><a href="#is_inline" id="toc-is_inline"><span class="toc-section-number">2.1.12</span>
<code class="sourceCode cpp">is_inline</code><span></span></a></li>
<li><a href="#is_const-is_explicit-is_volatile-is_rvalue_reference_qualified-is_lvalue_reference_qualified-is_static_member-has_static_linkage-is_noexcept" id="toc-is_const-is_explicit-is_volatile-is_rvalue_reference_qualified-is_lvalue_reference_qualified-is_static_member-has_static_linkage-is_noexcept"><span class="toc-section-number">2.1.13</span>
<code class="sourceCode cpp">is_const</code>,
<code class="sourceCode cpp">is_explicit</code>,
<code class="sourceCode cpp">is_volatile</code>,
<code class="sourceCode cpp">is_rvalue_reference_qualified</code>,
<code class="sourceCode cpp">is_lvalue_reference_qualified</code>,
<code class="sourceCode cpp">is_static_member</code>,
<code class="sourceCode cpp">has_static_linkage</code>,
<code class="sourceCode cpp">is_noexcept</code><span></span></a></li>
<li><a href="#noexcept_of" id="toc-noexcept_of"><span class="toc-section-number">2.1.14</span>
<code class="sourceCode cpp">noexcept_of</code><span></span></a></li>
<li><a href="#explicit_specifier_of" id="toc-explicit_specifier_of"><span class="toc-section-number">2.1.15</span>
<code class="sourceCode cpp">explicit_specifier_of</code><span></span></a></li>
<li><a href="#is_declared_constexpr-is_declared_consteval" id="toc-is_declared_constexpr-is_declared_consteval"><span class="toc-section-number">2.1.16</span>
<code class="sourceCode cpp">is_declared_constexpr</code>,
<code class="sourceCode cpp">is_declared_consteval</code><span></span></a></li>
<li><a href="#template_return_type_of" id="toc-template_return_type_of"><span class="toc-section-number">2.1.17</span>
<code class="sourceCode cpp">template_return_type_of</code><span></span></a></li>
<li><a href="#template_function_parameters_of-function_parameter_prefix" id="toc-template_function_parameters_of-function_parameter_prefix"><span class="toc-section-number">2.1.18</span>
<code class="sourceCode cpp">template_function_parameters_of</code>,
<code class="sourceCode cpp">function_parameter_prefix</code><span></span></a></li>
<li><a href="#trailing_requires_clause_of" id="toc-trailing_requires_clause_of"><span class="toc-section-number">2.1.19</span>
<code class="sourceCode cpp">trailing_requires_clause_of</code><span></span></a></li>
<li><a href="#body_of" id="toc-body_of"><span class="toc-section-number">2.1.20</span>
<code class="sourceCode cpp">body_of</code><span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#metafunctions-for-iterating-members-of-class-templates" id="toc-metafunctions-for-iterating-members-of-class-templates"><span class="toc-section-number">3</span> Metafunctions for Iterating Members
of Class Templates<span></span></a></li>
<li><a href="#future-work" id="toc-future-work"><span class="toc-section-number">4</span> Future Work<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<div lang="en" style="hyphens: auto;">

<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="motivation"><span class="header-section-number">1</span>
Motivation<a href="#motivation" class="self-link"></a></h1>
<p>A key characteristic that makes a reflection facility powerful is
<em>completeness</em>, i.e., the ability to reflect the entirety of the
source language. Current proposals facilitate reflection of certain
declarations in a namespace or a
<code class="sourceCode cpp"><span class="kw">struct</span></code>/<code class="sourceCode cpp"><span class="kw">class</span></code>/<code class="sourceCode cpp"><span class="kw">union</span></code>
definition. Although <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>’s
<code class="sourceCode cpp">members_of</code> metafunction includes
template members (function template and class template declarations), it
does not offer primitives for reflection of template declarations
themselves. In this proposal, we aim to define a comprehensive API for
reflection of C++ templates.</p>
<p>A powerful archetypal motivator—argued in <span class="citation" data-cites="P3157R1">[<a href="https://wg21.link/p3157r1" role="doc-biblioref">P3157R1</a>]</span> and at length in the CppCon
2024 talk “Reflection Is Not Contemplation”— is the <em>identity</em>
metafunction. This function, given a class type, creates a replica of
it, crucially providing the ability to make minute changes to the copy,
such as changing its name, adding or removing members, changing the
signature of existing member functions, and so on. By means of
example:</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">class</span> Widget <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> a;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><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">class</span> T<span class="op">&gt;</span> <span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span>T, <span class="dt">int</span><span class="op">&gt;)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    Widget<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;)</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> Widget<span class="op">&amp;</span> f<span class="op">(</span><span class="kw">const</span> Widget<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">&amp;</span>;</span>
<span id="cb1-7"><a href="#cb1-7" 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="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> g<span class="op">()</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    identity<span class="op">(^^</span>Widget, <span class="st">&quot;Gadget&quot;</span><span class="op">)</span>;</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="co">// Same effect as this handwritten code:</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">// class Gadget {</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="co">//     int a;</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="co">// public:</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="co">//     template &lt;class T&gt; requires (std::is_convertible_v&lt;T, int&gt;)</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="co">//     Gadget(const T&amp;);</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="co">//     const Gadget&amp; f(const Gadget&amp;) const &amp;;</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="co">//     template &lt;class T&gt;</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="co">//     void g();</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="co">// };</span></span></code></pre></div>
</blockquote>
</div>
<p>While an exact copy of a type is not particularly interesting—and
although a compiler could easily provide a primitive to do so, such a
feature would miss the point—the ability to deconstruct a type into its
components (bases, data members, member functions, nested types, nested
template declarations, etc.) and reassemble them in a different context
enables a vast array of applications. These include various forms of
instrumentation, creating parallel hierarchies as required by several
design patterns, generating arbitrary subsets of an interface (the
<em>powerset</em> of an interface), logging, tracing, debugging, timing
measurements, and many more. We consider
<code class="sourceCode cpp">identity</code>’s ability to perform the
roundtrip from a type to its components and back to the type the
quintessential goal of reflection, which is at the same time the proof
of reflection’s completeness and the fountainhead of many of its
applications.</p>
<!-- P2996 template-related reflection primitives:
- `template_arguments_of`
- `has_template_arguments`
- `template_of`
- `is_template`
- `is_function_template`
- `is_variable_template`
- `is_class_template`
- `is_alias_template`
- `is_conversion_function_template`
- `is_operator_function_template`
- `is_literal_operator_template`
- `is_constructor_template`
- `substitute`
- `can_substitute`
- `reflect_invoke`
-->
<p>In order to reflect on nontrivial C++ code and splice it back with
controlled modifications, it is necessary to reflect all templates—class
templates and specializations thereof, function templates, variable
templates, and alias templates. This is not an easy task; templates pose
unique challenges to a reflection engine because, by their nature, they
are only partially analyzed semantically; for example, neither parameter
types nor the return type of a function template can be represented as
reflections of types because some of those types are often not known
until the template is instantiated. The same thinking goes for a variety
of declarations that can be found inside a class template; C++ templates
are more akin to patterns by which code is to be generated than to
standalone, semantically verified code. For that reason, the reflection
facilities proposed in P2996 intended for non-templated declarations are
not readily applicable to templates.</p>
<p>Conversely, reflection code would be seriously hamstrung if it lacked
the ability to reflect on template code (and subsequently manipulate and
generate related code), especially because templates are ubiquitous in
today’s C++ codebases. Furthermore, limiting reflection to
instantiations of class templates (which would fit the charter of P2996)
does not suffice because class templates commonly define inner function
templates (e.g., every instantiation of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
defines several constructor templates and other function templates such
as <code class="sourceCode cpp">insert</code> and
<code class="sourceCode cpp">emplace_back</code>). Therefore, to the
extent reflection of C++ declarations is deemed useful, reflection of
templates is essential.</p>
<p>Given that many elements of a template cannot be semantically
analyzed early (at template definition time), this proposal adopts a
consistent strategy for reflecting components of template declarations:
each element of a template declaration—such as the parameter list,
constraints, and template argument list—is represented as a <em>token
sequence</em>, as proposed in <span class="citation" data-cites="P3294R2">[<a href="https://wg21.link/p3294r2" role="doc-biblioref">P3294R2</a>]</span>. We consider token sequences a
key enabler of the ability to introspect templates as proposed in this
paper. Though operating with token sequences is a departure from P2996’s
<em>modus operandi</em>, we paid special attention to ensure seamless
interoperation with it.</p>
<p>As lightly structured representations of components of template
declarations, token sequences have several important advantages:</p>
<ul>
<li><em>Simplicity:</em> C++ template declarations and the rules for
substitution and looking up symbols are quite complex. Adding new
language elements dedicated to handling, for example, reflection of
dependent types would complicate the language immensely. In contrast,
token sequences are a simple, uniform, and effective means to represent
any part of a template declaration because they fundamentally are
created from, and consist of, C++ source code.</li>
<li><em>Interoperation:</em> Token sequences will seamlessly
interoperate with, and take advantage of, all primitives and facilities
introduced in P3294 related to token sequences.</li>
<li><em>Code generation ability:</em> A key aspect of reflection is the
ability to “hook into” code by generating new code that copies existing
functionality and adds elements such as code instrumentation, logging,
or tracing. Generating instrumented templates from components of
existing template declarations is simple and straightforward—as simple
as any use of token sequences for code generation.</li>
<li><em>Implementation friendliness:</em> Token sequences do not require
heavy infrastructure or a specific implementation design. In addition,
this proposal grants important freedom and latitude to compilers, as
detailed in the next section.</li>
</ul>
<h2 data-number="1.1" id="the-as-if-rule-for-token-sequences-returned-by-reflection-metafunctions"><span class="header-section-number">1.1</span> The “As-If” Rule for Token
Sequences Returned by Reflection Metafunctions<a href="#the-as-if-rule-for-token-sequences-returned-by-reflection-metafunctions" class="self-link"></a></h2>
<p>Most metafunctions proposed in this paper return token sequences.
Some implementations may not preserve the exact tokens as initially
present in source code for a variety of reasons. First, it is possible
that an implementation “normalizes” code that may have different forms
in source, for example replacing <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></code>
with the equivalent <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></code>
or vice versa. Second, a compiler may run some simple front-end
processing during tokenization, replacing e.g. <code class="sourceCode cpp"><span class="op">+</span><span class="dv">1</span></code>
or <code class="sourceCode cpp"><span class="bn">01</span></code> with
<code class="sourceCode cpp"><span class="dv">1</span></code>. Third,
compilers may look up some types early and replace them with the
internal representation thereof, which is fully constant-folded and with
all default arguments substituted—again, making it tenuous to return
looked-up types exactly in the form originally present in source code.
Fourth, some implementations are known to parse templates eagerly and
drop the tokens early in the processing pipeline. For such a compiler,
producing the tokens would be difficult and inefficient.</p>
<p>Given these realities of current compiler implementations, demanding
that the compiler returns the exact tokens present in the initial source
code may entail unnecessary burden on some implementations. We therefore
stipulate that metafunctions that return token sequences are bound by
the following minimal requirements:</p>
<ul>
<li>Metafunctions that return token sequences originating from existing
code must return code that, when spliced back into source, compiles and
runs with the same semantics as the original source code.</li>
<li>Implementations are allowed to return token sequences that contain
nonstandard code (including handles into compiler-internal data
structure), again as long as the result of splicing has the same
semantics as the original source code.</li>
<li>Returning empty token sequences is always observed.</li>
<li>There is no other guaranteed assumption about metafunctions that
return tokens.</li>
</ul>
<p>In particular, user code should not assume token sequences returned
by implementation-defined metafunctions compare equal with tokens
assumed to be equivalent. The only guarantee is that splicing the tokens
back has the same effect. We hope that this proposal sets a useful
precedent for all future standard metafunctions that return tokenized
representation of existing code.</p>
<p>Producing a printable token stream on demand remains important for
debugging purposes. We consider it a quality of implementation
matter.</p>
<h2 data-number="1.2" id="example-logging-and-forwarding"><span class="header-section-number">1.2</span> Example: Logging and
Forwarding<a href="#example-logging-and-forwarding" class="self-link"></a></h2>
<p>As a conceptual stylized example, consider the matter of creating a
function template
<code class="sourceCode cpp">logged<span class="op">::</span>func</code>
for any free function template <code class="sourceCode cpp">func</code>
in such a way that
<code class="sourceCode cpp">logged<span class="op">::</span>func</code>
has the same signature and semantics as
<code class="sourceCode cpp">func</code>, with the added behavior that
it logs the call and its parameters prior to execution. We illustrate
the matter for function templates because it is more difficult (and more
complete) than the case of simple functions.</p>
<div class="std">
<blockquote>
<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> T<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_copy_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> fun<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">void</span> make_logged<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    queue_injection<span class="op">(^^{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">namespace</span> logged <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>            \tokens<span class="op">(</span>copy_signature<span class="op">(</span>f, name_of<span class="op">(</span>f<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>                logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span> <span class="op">+</span> name_of<span class="op">(</span>f<span class="op">)</span> <span class="op">+</span> <span class="st">&quot; with arguments: &quot;</span>, \tokens<span class="op">(</span>params_of<span class="op">(</span>f<span class="op">)))</span>;</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> \tokens<span class="op">(</span>make_fwd_call<span class="op">(</span>f<span class="op">))</span>;</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>  <span class="co">// end manespace logged</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    make_logged<span class="op">(^^</span>fun<span class="op">)</span>;</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent hand-written code:</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="co">// namespace logged {</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="co">//     template &lt;typename T&gt;</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="co">//     requires std::is_copy_constructible_v&lt;T&gt;</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="co">//     void fun(const T&amp; value) {</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="co">//         logger(&quot;Call to &quot;, &quot;fun&quot;, &quot; with arguments: &quot;, value);</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="co">//         return fun&lt;T&gt;(std::forward&lt;T&gt;(value));</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="co">//     }</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="co">// }</span></span></code></pre></div>
</blockquote>
</div>
<p>We identify a few high-level metafunctions that facilitate such
manipulation of template declarations. <code class="sourceCode cpp">copy_signature<span class="op">(</span>info f, std<span class="op">::</span>string_view name<span class="op">)</span></code>
produces the token sequence corresponding to the signature of the
function template reflected by <code class="sourceCode cpp">f</code>,
under a new name. (The example above uses the same name in a distinct
namespace.) The template parameters,
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause, function parameters, and return type are all part of the copied
tokens. (In the general case, we do want to have separate access to each
element for customization purposes, so
<code class="sourceCode cpp">copy_signature</code> would combine more
fine-grained primitives.) Next, <code class="sourceCode cpp">params_of<span class="op">(</span>f<span class="op">)</span></code>
produces a comma-separated list of the parameters of
<code class="sourceCode cpp">f</code>, with pack expansion suffix where
applicable. Finally, <code class="sourceCode cpp">make_fwd_call</code>
creates the tokens of a call to the function reflected by
<code class="sourceCode cpp">f</code> with the appropriate insertion of
calls to
<code class="sourceCode cpp">std<span class="op">::</span>forward</code>,
again with pack expansion suffix where appropriate.</p>
<p>In order to be able to define metafunctions such as
<code class="sourceCode cpp">copy_signature</code>,
<code class="sourceCode cpp">params_of</code>, and
<code class="sourceCode cpp">make_fwd_call</code>, we need access to the
lower-level components of a template declaration.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="metafunctions-for-template-declarations"><span class="header-section-number">2</span> Metafunctions for Template
Declarations<a href="#metafunctions-for-template-declarations" class="self-link"></a></h1>
<p>All template declarations (whether a class template or specialization
thereof, a function template, an alias template, or a variable
template), have some common elements: a template parameter list, an
optional list of attributes, and an optional template-level
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause.</p>
<p>If our goal were simply to splice a template declaration back in its
entirety—possibly with a different name and/or with normalized parameter
names—the introspection metafunction <code class="sourceCode cpp">copy_signature<span class="op">(^^</span>X, <span class="st">&quot;Y&quot;</span><span class="op">)</span></code>
showcased above could be defined as an implementation-defined primitive
that simply splices the entire declaration of template
<code class="sourceCode cpp">X</code> to declare a new template
<code class="sourceCode cpp">Y</code> that is (save for the name)
identical to <code class="sourceCode cpp">X</code>. However, most often
code generation needs to tweak elements of the declaration—for example,
adding a conjunction to the
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause or eliminating the <code class="sourceCode cpp">deprecated</code>
attribute. Simply returning an opaque token sequence of the entire
declaration and leaving it to user-level code to painstakingly parse it
once again would be inefficient and burdensome; therefore, we aim to
identify structural components of the declaration and define primitives
that return each in turn. That way, we offer unbounded customization
opportunities by allowing users to mix and match elements of the
original declaration with custom code. Once we have all components of
the template declaration, implementing
<code class="sourceCode cpp">copy_signature</code> as a shorthand for
assembling them together is trivially easy.</p>
<p>In addition to template parameters,
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause, and attributes, certain template declarations have additional
elements as follows:</p>
<ul>
<li>Class templates and variable templates may add explicit
specializations and partial specializations</li>
<li>Function templates may create overload sets (possibly alongside
regular functions of the same name)</li>
<li>Alias templates contain a declarator</li>
<li>Member variables of class templates, and also variable templates,
have a type and an optional initializer</li>
<li>Function template declarations may contain these additional
elements:
<ul>
<li><code class="sourceCode cpp"><span class="kw">inline</span></code>
specifier</li>
<li><code class="sourceCode cpp"><span class="kw">static</span></code>
linkage</li>
<li><code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause (possibly predicated)</li>
<li>cvref qualifiers</li>
<li><code class="sourceCode cpp"><span class="kw">explicit</span></code>
specifier (possibly predicated)</li>
<li><code class="sourceCode cpp"><span class="kw">constexpr</span></code>
or <code class="sourceCode cpp"><span class="kw">consteval</span></code>
specifier</li>
<li>return type</li>
<li>function parameters</li>
<li>trailing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause</li>
<li>function template body</li>
</ul></li>
</ul>
<p>Armed with a these insights and with the strategy of using token
sequences throughout, we propose the following reflection primitives for
templates.</p>
<h2 data-number="2.1" id="synopsis"><span class="header-section-number">2.1</span> Synopsis<a href="#synopsis" class="self-link"></a></h2>
<p>The declarations below summarize the metafunctions proposed, with
full explanations for each following. Some (where noted) have identical
declarations with metafunctions proposed in P2996, to which we propose
extended semantics.</p>
<div class="std">
<blockquote>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">//  Multiple explicit specializations and/or partial specializations</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_alternatives_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Template parameter normalization prefix</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> string_view template_parameter_prefix;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Template parameter list</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_parameters_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Attributes - extension of semantics in P3385</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> attributes_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Template-level requires clause</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> requires_clause_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Is this the reflection of the primary template declaration?</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_primary_template<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Arguments of an explicit specialization or partial specialization</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> specialization_arguments_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Bases of a class template</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_bases_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Type of a data member in a class template or of a variable template</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_data_type<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Type of a data member in a class template</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_data_initializer<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Declarator part of an alias template</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> alias_template_declarator<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Inline specifier present?</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_inline<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// cvref qualifiers and others - extensions of semantics in P2996</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_const<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_explicit<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_volatile<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_rvalue_reference_qualified<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_lvalue_reference_qualified<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_static_member<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> has_static_linkage<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_noexcept<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>    <span class="co">// predicate for `noexcept`</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> noexcept_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `explicit` present? - extension of P2996</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a>    <span class="co">// predicate for `explicit`</span></span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> explicit_specifier_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `constexpr` present?</span></span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_declared_constexpr<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `consteval` present?</span></span>
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> is_declared_consteval<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Function template return type</span></span>
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_return_type_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Function template parameter normalization prefix</span></span>
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> string_view function_parameter_prefix;</span>
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Function parameters</span></span>
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_function_parameters_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span>
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Trailing `requires`</span></span>
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> trailing_requires_clause_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Function template body</span></span>
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> body_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.1" id="template_alternatives_of"><span class="header-section-number">2.1.1</span>
<code class="sourceCode cpp">template_alternatives_of</code><a href="#template_alternatives_of" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_alternatives_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>In addition to general template declarations, a class template or a
variable template may declare explicit specializations and/or partial
specializations. 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="co">// Primary template declaration</span></span>
<span id="cb5-2"><a href="#cb5-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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span><span class="op">&gt;</span> <span class="kw">typename</span> A, <span class="kw">auto</span> x<span class="op">&gt;</span> <span class="kw">class</span> C;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> C<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>allocator, <span class="dv">42</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Partial specialization</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">class</span> C<span class="op">&lt;</span>T, std<span class="op">::</span>allocator, <span class="dv">100</span><span class="op">&gt;</span> <span class="op">{}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Each specialization must be accessible for reflection in separation
from the others; in particular, there should be a mechanism to iterate
<code class="sourceCode cpp"><span class="op">^^</span>C</code> to
reveal <code class="sourceCode cpp">info</code> handles for the three
available variants (the primary declaration, the explicit
specialization, and the partial specialization). Each specialization may
contain the same syntactic elements as the primary template declaration.
In addition to those, explicit specializations and partial
specializations also contain the specialization’s template arguments (in
the code above: <code class="sourceCode cpp"><span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>allocator, <span class="dv">42</span><span class="op">&gt;</span></code>
and <code class="sourceCode cpp"><span class="op">&lt;</span>T, std<span class="op">::</span>allocator, <span class="dv">100</span><span class="op">&gt;</span></code>,
respectively), which we also set out to be accessible through
reflection.</p>
<p>Given the reflection of a class template or variable template,
<code class="sourceCode cpp">template_alternatives_of</code> returns the
reflections of all explicit specializations and all partial
specializations thereof (including the primary declaration).
Declarations are returned in syntactic order. This is important because
a specialization may depend on a previous one, as shown below:</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="co">// Primary declaration</span></span>
<span id="cb6-2"><a href="#cb6-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="kw">struct</span> A <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> A<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization, depends on the previous one</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">struct</span> A<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="op">:</span> A<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Partial specialization, may depend on both previous ones</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> U<span class="op">&gt;</span> <span class="kw">struct</span> A<span class="op">&lt;</span>std<span class="op">::</span>tuple<span class="op">&lt;</span>T, U<span class="op">&gt;&gt;</span> <span class="op">:</span> A<span class="op">&lt;</span>T<span class="op">&gt;</span>, A<span class="op">&lt;</span>U<span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>As a consequence of the source-level ordering, the primary
declaration’s reflection is always the first element of the returned
vector. Example:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">class</span> C;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> C<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb7-3"><a href="#cb7-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">class</span> C<span class="op">&lt;</span>std<span class="op">::</span>pair<span class="op">&lt;</span><span class="dt">int</span>, T<span class="op">&gt;&gt;</span> <span class="op">{}</span>;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Get reflections for the primary and the two specializations</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>C<span class="op">)</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>r<span class="op">.</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><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>C<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.2" id="template_parameters_of-template_parameter_prefix"><span class="header-section-number">2.1.2</span>
<code class="sourceCode cpp">template_parameters_of</code>,
<code class="sourceCode cpp">template_parameter_prefix</code><a href="#template_parameters_of-template_parameter_prefix" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_parameters_of<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> string_view template_parameter_prefix <span class="op">=</span> <em>unspecified</em>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template,
<code class="sourceCode cpp">template_parameters_of</code> returns an
array of token sequences containing the template’s parameters (a
parameter pack counts as one parameter). Template parameter names are
normalized by naming them the concatenation of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>template_parameter_prefix</code>
and an integral counter starting at 0 and incremented with each
parameter introduction, left to right. For example, <code class="sourceCode cpp">template_parameters_of<span class="op">(^^</span>A<span class="op">)</span></code>
yields the token sequences <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">typename</span> _T0<span class="op">}</span></code>,
<code class="sourceCode cpp"><span class="op">^^{</span>_T0 _T1<span class="op">}</span></code>,
and <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">auto</span><span class="op">...</span> _T2<span class="op">}</span></code>.
Note that the second parameter has been described as
<code class="sourceCode cpp">_T0 _T1</code> (renaming the dependent name
correctly). The template parameter prefix <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>template_parameter_prefix</code>
is an implementation-reserved name such as <code class="sourceCode cpp"><span class="st">&quot;_T&quot;</span></code> or
<code class="sourceCode cpp"><span class="st">&quot;__t&quot;</span></code>.
(Our examples use <code class="sourceCode cpp"><span class="st">&quot;_T&quot;</span></code>.)</p>
<p>For example:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, T x, <span class="kw">auto</span><span class="op">...</span> f<span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>template_parameters_of<span class="op">(^^</span>A<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="co">// r0 is ^^{typename _T0}</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r0 <span class="op">=</span> template_parameters_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="co">// r1 is ^^{_T0 x}</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> template_parameters_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="co">// r2 is ^^{auto... _T0}</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> template_parameters_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">2</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>As noted above, an implementation may return token sequences
equivalent to those in the source code, e.g. <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">class</span> _T0<span class="op">}</span></code>
instead of <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">typename</span> _T0<span class="op">}</span></code>.</p>
<p>Defaulted parameters, if any, are included in the token sequences
returned. For example:</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">typename</span> U <span class="op">=</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="kw">class</span> A;</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="co">// r is ^^{typename _T0 = int}</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_parameters_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>For explicit specializations of class templates,
<code class="sourceCode cpp">template_parameters_of</code> returns an
empty vector:</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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;</span><span class="dt">int</span><span class="op">&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="co">// r refers to A&lt;int&gt;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;  <span class="co">// definition below</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>template_parameters_of<span class="op">(</span>r<span class="op">).</span>empty<span class="op">())</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If a non-type template parameter has a non-dependent type, the tokens
returned for that parameter include the fully looked-up name. For
example:</p>
<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">namespace</span> Lib <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span>S s<span class="op">&gt;</span> <span class="kw">class</span> C <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;  <span class="co">// illustrates a potential ambiguity</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">// r is ^^{::Lib::S _T0}, not ^^{S _T0}</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_parameters_of<span class="op">(^^</span>Lib<span class="op">::</span>C<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given a class template <code class="sourceCode cpp">A</code> that has
explicit instantiations and/or partial specializations declared, the
call <code class="sourceCode cpp">template_parameters_of<span class="op">(^^</span>A<span class="op">)</span></code>
is not ambiguous—it refers to the primary declaration of the
template.</p>
<p>Calling <code class="sourceCode cpp">template_parameters_of</code>
against a non-template entity, as in <code class="sourceCode cpp">template_parameters_of<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>
or <code class="sourceCode cpp">template_parameters_of<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>,
fails to evaluate to a constant expression.</p>
<h3 data-number="2.1.3" id="attributes_of"><span class="header-section-number">2.1.3</span>
<code class="sourceCode cpp">attributes_of</code><a href="#attributes_of" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> attributes_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns all attributes associated with
<code class="sourceCode cpp">info</code>. The intent is to extend the
functionality of <code class="sourceCode cpp">attributes_of</code> as
defined in <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3385r0.html">P3385</a>
to template declarations. We defer details and particulars to that
proposal.</p>
<h3 data-number="2.1.4" id="requires_clause_of"><span class="header-section-number">2.1.4</span>
<code class="sourceCode cpp">requires_clause_of</code><a href="#requires_clause_of" class="self-link"></a></h3>
<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>info requires_clause_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template, returns the template-level
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause as a token sequence. The names of template parameters found in
the <code class="sourceCode cpp"><span class="kw">requires</span></code>
clause are normalized. Non-dependent identifiers are returned in
fully-qualified form. For example:</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">struct</span> X <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>X<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">256</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>is_default_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;)</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> A;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns `^^{(sizeof(::X) &gt; 1 &amp;&amp; ::std::is_default_constructible_v&lt;_T0&gt;)}`</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> requires_clause_of<span class="op">(^^</span>A<span class="op">)</span>;</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><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">&gt;</span> <span class="dv">1</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>is_default_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;)</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> V <span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns `^^{(sizeof(_T0) &gt; 1 &amp;&amp; ::std::is_default_constructible_v&lt;_T0&gt;)}`</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> r2 <span class="op">=</span> requires_clause_of<span class="op">(^^</span>V<span class="op">)</span>;</span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-16"><a href="#cb15-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="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> <span class="op">(</span>std<span class="op">::</span>is_convertible_v<span class="op">&lt;</span><span class="dt">int</span>, T<span class="op">&gt;)</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> zero <span class="op">=</span> T<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns `^^{(::std::is_convertible_v&lt;int, _T0&gt;)}`</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r3 <span class="op">=</span> requires_clause_of<span class="op">(^^</span>zero<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Calling <code class="sourceCode cpp">requires_clause_of</code>
against a template that has no such clause returns an empty token
sequence. Calling <code class="sourceCode cpp">requires_clause_of</code>
against a non-template, as in <code class="sourceCode cpp">requires_clause_of<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>
or <code class="sourceCode cpp">requires_clause_of<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>,
fails to evaluate to a constant expression.</p>
<h3 data-number="2.1.5" id="is_primary_template"><span class="header-section-number">2.1.5</span>
<code class="sourceCode cpp">is_primary_template</code><a href="#is_primary_template" class="self-link"></a></h3>
<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="dt">bool</span> is_primary_template<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">info</code> refers to the primary
declaration of a class template or variable template,
<code class="sourceCode cpp"><span class="kw">false</span></code> in all
other cases (including cases in which the query does not apply, such as
<code class="sourceCode cpp">is_primary_template<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>).
In particular, this metafunction is useful for distinguishing between a
primary template and its explicit specializations or partial
specializations. For example:</p>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_primary_template<span class="op">(^^</span>A<span class="op">))</span>;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_primary_template<span class="op">(</span>template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span>;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_primary_template<span class="op">(</span>template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]))</span>;</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_primary_template<span class="op">(^^</span><span class="dt">int</span><span class="op">))</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.6" id="specialization_arguments_of"><span class="header-section-number">2.1.6</span>
<code class="sourceCode cpp">specialization_arguments_of</code><a href="#specialization_arguments_of" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> specialization_arguments_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>For an explicit specialization or a partial specialization of a class
template or variable template, returns that specialization’s arguments.
For example:</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">typename</span> T<span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>;</span>
<span id="cb19-3"><a href="#cb19-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">class</span> A<span class="op">&lt;</span>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, T<span class="op">&gt;&gt;</span>;</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the reflection of the first explicit specialization</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the argument of that specialization, i.e. ^^{int}</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r11 <span class="op">=</span> specialization_arguments_of<span class="op">(</span>r1<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the reflection of the second explicit specialization</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">2</span><span class="op">]</span>;</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the arguments of that specialization, i.e. ^^{std::tuple&lt;int, T&gt;}</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r21 <span class="op">=</span> specialization_arguments_of<span class="op">(</span>r2<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If an explicit specialization uses default arguments, those will be
made part of the return of
<code class="sourceCode cpp">specialization_arguments_of</code>, even if
they are not syntactically present in the source code:</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> T <span class="op">=</span> <span class="dt">int</span><span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicitly specialize A&lt;int&gt;.</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;&gt;</span>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the explicit specialization</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="co">// r1 will be ^^{int}</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> specialization_arguments_of<span class="op">(</span>r<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Note that
<code class="sourceCode cpp">specialization_arguments_of</code> may
return an empty vector. For example:</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">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">class</span> A;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;&gt;</span>;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="co">// No specialization arguments present</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>specialization_arguments_of<span class="op">(</span>r<span class="op">).</span>empty<span class="op">())</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The metafunction
<code class="sourceCode cpp">specialization_arguments_of</code> has a
similar role but is qualitatively different from
<code class="sourceCode cpp">template_arguments_of</code> in P2996
because the latter returns resolved entities (types, values, or template
names), whereas the former returns token sequences of the arguments.</p>
<p>Non-dependent types returned are always returned in fully
namespace-qualified form. Example:</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="kw">namespace</span> N <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> S <span class="op">{}</span>;</span>
<span id="cb22-3"><a href="#cb22-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">class</span> A;</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Explicitly specialize A&lt;int&gt;.</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;&gt;</span> <span class="kw">class</span> A<span class="op">&lt;</span>S<span class="op">&gt;</span>;</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{}</span>;  <span class="co">// to illustrate a possible ambiguity</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="co">// Get the explicit specialization</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> template_alternatives_of<span class="op">(^^</span>N<span class="op">::</span>A<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="co">// r1 will be ^^{::N::S}, not ^^{S}</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> specialization_arguments_of<span class="op">(</span>r<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">specialization_arguments_of</code> is
called with an <code class="sourceCode cpp">info</code> that is not an
explicit template specialization, the call fails to resolve to a
constant expression.</p>
<h3 data-number="2.1.7" id="template_bases_of"><span class="header-section-number">2.1.7</span>
<code class="sourceCode cpp">template_bases_of</code><a href="#template_bases_of" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_bases_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the bases of a class template, in declaration order, as token
sequences. Access specifiers are part of the returned tokens in such a
way that reassembling the result of
<code class="sourceCode cpp">template_bases_of</code> as a
comma-separated list produces a valid base classes specifier.
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">class</span> B1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb24-2"><a href="#cb24-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">class</span> B2 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb24-3"><a href="#cb24-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">class</span> C <span class="op">:</span> <span class="kw">public</span> B1, <span class="kw">public</span> B2<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Contains ^^{public ::B1}</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> template_bases_of<span class="op">(^^</span>C<span class="op">)[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Contains ^^{public ::B2&lt;_T0&gt;}</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> template_bases_of<span class="op">(^^</span>C<span class="op">)[</span><span class="dv">1</span><span class="op">]</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.8" id="template_data_type"><span class="header-section-number">2.1.8</span>
<code class="sourceCode cpp">template_data_type</code><a href="#template_data_type" class="self-link"></a></h3>
<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>info template_data_type<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a data member of a class template or of a
variable template, returns the type of the member as a token sequence.
Returning a type reflection, as is the case for P2996’s
<code class="sourceCode cpp">type_of</code>, is not possible in most
cases. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> T<span class="op">&amp;</span> x;</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 class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> zero <span class="op">=</span> T<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Call P2996&#39;s nonstatic_data_members_of extended for templates</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="co">// r1 contains ^^{_T0 const&amp;}</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> template_data_type<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>C<span class="op">)[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="co">// r2 contains ^^{_T0(0)}</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> template_data_type<span class="op">(^^</span>zero<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.9" id="template_data_initializer"><span class="header-section-number">2.1.9</span>
<code class="sourceCode cpp">template_data_initializer</code><a href="#template_data_initializer" class="self-link"></a></h3>
<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>info template_data_initializer<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the initializer part of a data member of a class template or
of a variable template declaration, as a token sequence. Example:</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">class</span> T<span class="op">&gt;</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>    T x <span class="op">=</span> T<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">)</span>;</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>    T y;</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>
<span id="cb28-7"><a href="#cb28-7" 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="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> zero <span class="op">=</span> T<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a><span class="co">// r1 contains `^^{_T0(&quot;hello&quot;)}`</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r1 <span class="op">=</span> template_data_initializer<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>S<span class="op">)[</span><span class="dv">0</span><span class="op">])</span>;</span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a><span class="co">// r2 contains `^^{}`</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r2 <span class="op">=</span> template_data_initializer<span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>S<span class="op">)[</span><span class="dv">1</span><span class="op">])</span>;</span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a><span class="co">// r3 contains `^^{_T0(0)}`</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r3 <span class="op">=</span> template_data_initializer<span class="op">(^^</span>zero<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">template_data_initializer</code> is
called with an <code class="sourceCode cpp">info</code> that is not an
alias template, the call fails to resolve to a constant expression.</p>
<h3 data-number="2.1.10" id="alias_template_declarator"><span class="header-section-number">2.1.10</span>
<code class="sourceCode cpp">alias_template_declarator</code><a href="#alias_template_declarator" class="self-link"></a></h3>
<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>info alias_template_declarator<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the declarator part of an alias template declaration, as a
token sequence. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> V <span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns `^^{::std::vector&lt;_T0, ::std::allocator&lt;_T0&gt;&gt;}`</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> alias_template_declarator<span class="op">(^^</span>V<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If <code class="sourceCode cpp">alias_template_declarator</code> is
called with an <code class="sourceCode cpp">info</code> that is not an
alias template, the call fails to resolve to a constant expression.</p>
<h3 data-number="2.1.11" id="overloads_of"><span class="header-section-number">2.1.11</span>
<code class="sourceCode cpp">overloads_of</code><a href="#overloads_of" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> overloads_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns an array of all overloads of a given function, usually passed
in as a reflection of an identifier (e.g.,
<code class="sourceCode cpp"><span class="op">^^</span>func</code>). All
overloads are included, template and nontemplate. To distinguish
functions from function templates,
<code class="sourceCode cpp">is_function_template</code> (P2996) can be
used. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span>;</span>
<span id="cb32-2"><a href="#cb32-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> f<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;)</span>;</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Name f has two overloads present.</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>overloads_of<span class="op">(^^</span>f<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">2</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The order of overloads in the results is the same as encountered in
source code.</p>
<p>If a function <code class="sourceCode cpp">f</code> has only one
declaration (no overloads), <code class="sourceCode cpp">overloads_of<span class="op">(^^</span>f<span class="op">)</span></code>
returns a vector with one element, which is equal to
<code class="sourceCode cpp"><span class="op">^^</span>f</code>.
Therefore, for such functions,
<code class="sourceCode cpp"><span class="op">^^</span>f</code> and
<code class="sourceCode cpp">overloads_of<span class="op">(^^</span>f<span class="op">)[</span><span class="dv">0</span><span class="op">]</span></code>
can be used interchangeably.</p>
<p>Each <code class="sourceCode cpp">info</code> returned by
<code class="sourceCode cpp">overloads_of</code> is the reflection of a
fully resolved symbol that doesn’t participate in any further overload
resolution. In other words, for any function
<code class="sourceCode cpp">f</code> (overloaded or not), <code class="sourceCode cpp">overloads_of<span class="op">(</span>overloads_of<span class="op">(^^</span>f<span class="op">)[</span>i<span class="op">])</span></code>
is the same as <code class="sourceCode cpp">overloads_of<span class="op">(^^</span>f<span class="op">)[</span>i<span class="op">]</span></code>
for all appropriate values of <code class="sourceCode cpp">i</code>.</p>
<h3 data-number="2.1.12" id="is_inline"><span class="header-section-number">2.1.12</span>
<code class="sourceCode cpp">is_inline</code><a href="#is_inline" class="self-link"></a></h3>
<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="dt">bool</span> is_inline<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns
<code class="sourceCode cpp"><span class="kw">true</span></code> if and
only if the given reflection handle refers to a function, function
template, or namespace that has the
<code class="sourceCode cpp"><span class="kw">inline</span></code>
specifier. In all other cases, such as <code class="sourceCode cpp">is_inline<span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>,
returns false.</p>
<p>Note that this metafunctions has applicability beyond templates as it
applies to regular functions and namespaces. Because of this it is
possible to migrate this metafunction to a future revision of P2996.</p>
<h3 data-number="2.1.13" id="is_const-is_explicit-is_volatile-is_rvalue_reference_qualified-is_lvalue_reference_qualified-is_static_member-has_static_linkage-is_noexcept"><span class="header-section-number">2.1.13</span>
<code class="sourceCode cpp">is_const</code>,
<code class="sourceCode cpp">is_explicit</code>,
<code class="sourceCode cpp">is_volatile</code>,
<code class="sourceCode cpp">is_rvalue_reference_qualified</code>,
<code class="sourceCode cpp">is_lvalue_reference_qualified</code>,
<code class="sourceCode cpp">is_static_member</code>,
<code class="sourceCode cpp">has_static_linkage</code>,
<code class="sourceCode cpp">is_noexcept</code><a href="#is_const-is_explicit-is_volatile-is_rvalue_reference_qualified-is_lvalue_reference_qualified-is_static_member-has_static_linkage-is_noexcept" class="self-link"></a></h3>
<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="dt">bool</span> is_const<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_explicit<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_volatile<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_rvalue_reference_qualified<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_lvalue_reference_qualified<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_static_member<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> has_static_linkage<span class="op">(</span>info<span class="op">)</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_noexcept<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Extends the homonym metafunctions defined by P2996 to function
templates.</p>
<p>In order to avoid confusion, in case a predicate is present for
<code class="sourceCode cpp">is_noexcept</code> or
<code class="sourceCode cpp">is_explicit</code>, the call fails to
resolve to a constant expression. Therefore, for templates it is best to
use the <code class="sourceCode cpp">noexcept_of</code> and
<code class="sourceCode cpp">explicit_specifier_of</code> metafunctions
(below), which support all cases.</p>
<h3 data-number="2.1.14" id="noexcept_of"><span class="header-section-number">2.1.14</span>
<code class="sourceCode cpp">noexcept_of</code><a href="#noexcept_of" class="self-link"></a></h3>
<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>info noexcept_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause of a function or function template, if any, as a token sequence,
as follows:</p>
<ul>
<li>if no
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause is present, returns the empty token sequence;</li>
<li>if
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> is
unconditional, returns the token sequence <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">noexcept</span><span class="op">}</span></code>;</li>
<li>if
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> is
conditional (e.g., <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span>expression<span class="op">)</span></code>),
returns the conditional noexcept in tokenized form;</li>
<li>if
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
would not be applicable (e.g., <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(^^</span><span class="dt">int</span><span class="op">)</span></code>),
the call fails to evaluate to a constant expression.</li>
</ul>
<h3 data-number="2.1.15" id="explicit_specifier_of"><span class="header-section-number">2.1.15</span>
<code class="sourceCode cpp">explicit_specifier_of</code><a href="#explicit_specifier_of" class="self-link"></a></h3>
<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>info explicit_specifier_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
specifier of the given <code class="sourceCode cpp">info</code> of a
constructor. If the constructor has no explicit specifier, returns the
empty sequence. If the constructor has an unconditional
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
specifier, returns the token sequence <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">explicit</span><span class="op">}</span></code>.
If the constructor has a predicated <code class="sourceCode cpp"><span class="kw">explicit</span><span class="op">(</span>constant<span class="op">-</span>expression<span class="op">)</span></code>,
returns the token sequence <code class="sourceCode cpp"><span class="op">^^{</span><span class="kw">explicit</span><span class="op">(</span>constant<span class="op">-</span>expression<span class="op">)}</span></code>.
All nondependent identifier in the token sequence are fully
namespace-qualified.</p>
<h3 data-number="2.1.16" id="is_declared_constexpr-is_declared_consteval"><span class="header-section-number">2.1.16</span>
<code class="sourceCode cpp">is_declared_constexpr</code>,
<code class="sourceCode cpp">is_declared_consteval</code><a href="#is_declared_constexpr-is_declared_consteval" class="self-link"></a></h3>
<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="dt">bool</span> is_declared_constexpr<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> is_declared_consteval<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns
<code class="sourceCode cpp"><span class="kw">true</span></code> if and
only if <code class="sourceCode cpp">info</code> refers to a declaration
that is
<code class="sourceCode cpp"><span class="kw">constexpr</span></code> or
<code class="sourceCode cpp"><span class="kw">consteval</span></code>,
respectively. In all other cases, returns
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<h3 data-number="2.1.17" id="template_return_type_of"><span class="header-section-number">2.1.17</span>
<code class="sourceCode cpp">template_return_type_of</code><a href="#template_return_type_of" class="self-link"></a></h3>
<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>info template_return_type_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the return type of the function template represented by
<code class="sourceCode cpp">info</code>. This function is similar with
<code class="sourceCode cpp">return_type_of</code> in P3096. However,
one key difference is that
<code class="sourceCode cpp">return_type_of</code> returns the
reflection of a type, whereas
<code class="sourceCode cpp">template_return_type_of</code> returns the
token sequence of the return type (given that the type is often not
known before instantiation or may be <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">&amp;</span></code>
etc).</p>
<h3 data-number="2.1.18" id="template_function_parameters_of-function_parameter_prefix"><span class="header-section-number">2.1.18</span>
<code class="sourceCode cpp">template_function_parameters_of</code>,
<code class="sourceCode cpp">function_parameter_prefix</code><a href="#template_function_parameters_of-function_parameter_prefix" class="self-link"></a></h3>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_function_parameters_of<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> string_view function_parameter_prefix;</span></code></pre></div>
</blockquote>
</div>
<p>Returns an array of parameters (type and name for each) of the
function template represented by
<code class="sourceCode cpp">info</code>, as token sequences. Parameter
names are normalized by naming them the concatenation of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>function_parameter_prefix</code>
and an integral counter starting at 0 and incremented with each
parameter introduction, left to right. Normalizing parameter names makes
it easy for splicing code to generate forwarding argument lists such as
the metafunctions <code class="sourceCode cpp">params_of</code> and
<code class="sourceCode cpp">make_fwd_call</code> in the opening
example.</p>
<p>This function bears similarities with
<code class="sourceCode cpp">parameters_of</code> in P3096. However, one
key difference is that <code class="sourceCode cpp">parameters_of</code>
returns reflection of types, whereas
<code class="sourceCode cpp">template_return_type_of</code> returns the
token sequence of the return type (given that the type is often not
known before instantiation or may be <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">&amp;</span></code>
etc).</p>
<h3 data-number="2.1.19" id="trailing_requires_clause_of"><span class="header-section-number">2.1.19</span>
<code class="sourceCode cpp">trailing_requires_clause_of</code><a href="#trailing_requires_clause_of" class="self-link"></a></h3>
<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>info trailing_requires_clause_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the <code class="sourceCode cpp">info</code> of a function
template, returns the trailing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause of the declaration as a token sequence. Example:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><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">&gt;</span> <span class="dv">8</span><span class="op">)</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="kw">requires</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span> <span class="op">&lt;</span> <span class="dv">64</span><span class="op">)</span>;</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Will contain ^^{ (sizeof(T) &lt; 64) }</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> trailing_requires_clause_of<span class="op">(^^</span>f<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.20" id="body_of"><span class="header-section-number">2.1.20</span>
<code class="sourceCode cpp">body_of</code><a href="#body_of" class="self-link"></a></h3>
<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>info body_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the <code class="sourceCode cpp">info</code> of a function
template, returns the function’s body as a token sequence, without the
top-level braces (which can be added with ease if needed). All parameter
names are normalized and all non-dependent identifiers are fully
qualified. Example:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>T x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x <span class="op">&lt;</span> <span class="dv">0</span> <span class="op">?</span> <span class="op">-</span>x <span class="op">:</span> x;</span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Will contain ^^{ return _p0 &lt; 0 ? -_p0 : _p0; }</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> body_of<span class="op">(^^</span>f<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="metafunctions-for-iterating-members-of-class-templates"><span class="header-section-number">3</span> Metafunctions for Iterating
Members of Class Templates<a href="#metafunctions-for-iterating-members-of-class-templates" class="self-link"></a></h1>
<p>The metafunctions described above need to be complemented with
metafunctions that enumerate the contents of a class template.
Fortunately, P2996 already defines number of metafunctions for doing so:
<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">nonstatic_data_members_of</code>,
<code class="sourceCode cpp">enumerators_of</code>,
<code class="sourceCode cpp">subobjects_of</code>. To these, P2996 adds
access-aware metafunctions
<code class="sourceCode cpp">accessible_members_of</code>,
<code class="sourceCode cpp">accessible_bases_of</code>,
<code class="sourceCode cpp">accessible_static_data_members_of</code>,
<code class="sourceCode cpp">accessible_nonstatic_data_members_of</code>,
and <code class="sourceCode cpp">accessible_subobjects_of</code>. Here,
we propose that these functions are extended in semantics to also
support <code class="sourceCode cpp">info</code> representing class
templates. The reflections of members of class templates, however, are
not the same as the reflection of corresponding members of regular
classes;</p>
<p>One important addendum to P2996 that is crucial for code generation
is that when applied to members, these discovery metafunctions return
members in lexical order. Otherwise, attempts to implement
<code class="sourceCode cpp">identity</code> will fail for class
templates. Consider:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Container <span class="op">{</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> size_type <span class="op">=</span> <span class="dt">size_t</span>;</span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>    size_type size<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The reflections of template components returned by
<code class="sourceCode cpp">members_of</code> and others can be
inspected with template-specific primitives, not the primitives defined
in P2996. For example, the data members returned by
<code class="sourceCode cpp">nonstatic_data_members_of</code> can be
inspected with <code class="sourceCode cpp">template_data_type</code>
and <code class="sourceCode cpp">template_data_initializer</code>, but
not with <code class="sourceCode cpp">offset_of</code>,
<code class="sourceCode cpp">size_of</code>,
<code class="sourceCode cpp">alignment_of</code>, or
<code class="sourceCode cpp">bit_size_of</code> because at the template
definition time the layout has not been created.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="future-work"><span class="header-section-number">4</span> Future
Work<a href="#future-work" class="self-link"></a></h1>
<p>This proposal is designed to interoperate with <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>, <span class="citation" data-cites="P3157R1">[<a href="https://wg21.link/p3157r1" role="doc-biblioref">P3157R1</a>]</span>, <span class="citation" data-cites="P3294R2">[<a href="https://wg21.link/p3294r2" role="doc-biblioref">P3294R2</a>]</span>, and <span class="citation" data-cites="P3385R0">[<a href="https://wg21.link/p3385r0" role="doc-biblioref">P3385R0</a>]</span>. Changes in these proposals may
influence this proposal. Also, certain metafunctions proposed herein
(such as <code class="sourceCode cpp">is_inline</code>) may migrate to
these proposals.</p>
<p>The normalization scheme for template parameters and function
parameters is rigid. We plan to refine it in future revisions of this
document.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-P2996R7" class="csl-entry" role="doc-biblioentry">
[P2996R7] Wyatt Childers, Peter Dimov, Dan Katz, Barry Revzin, Andrew
Sutton, Faisal Vali, and Daveed Vandevoorde. 2024-10-12. Reflection for
C++26. <a href="https://wg21.link/p2996r7"><div class="csl-block">https://wg21.link/p2996r7</div></a>
</div>
<div id="ref-P3157R1" class="csl-entry" role="doc-biblioentry">
[P3157R1] Andrei Alexandrescu, Barry Revzin, Bryce Lelbach, Michael
Garland. 2024-05-22. Generative Extensions for Reflection. <a href="https://wg21.link/p3157r1"><div class="csl-block">https://wg21.link/p3157r1</div></a>
</div>
<div id="ref-P3294R2" class="csl-entry" role="doc-biblioentry">
[P3294R2] Andrei Alexandrescu, Barry Revzin, and Daveed Vandevoorde.
2024-10-15. Code Injection with Token Sequences. <a href="https://wg21.link/p3294r2"><div class="csl-block">https://wg21.link/p3294r2</div></a>
</div>
<div id="ref-P3385R0" class="csl-entry" role="doc-biblioentry">
[P3385R0] Aurelien Cassagnes, Aurelien Cassagnes, Roman Khoroshikh,
Anders Johansson. 2024-09-16. Attributes reflection. <a href="https://wg21.link/p3385r0"><div class="csl-block">https://wg21.link/p3385r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
