<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2025-01-13" />
  <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>P3420R1 <a href="https://wg21.link/P3420">[Latest]</a> <a href="https://wg21.link/P3420/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-01-13</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="#revision-history" id="toc-revision-history"><span class="toc-section-number">1</span> Revision
History<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation<span></span></a>
<ul>
<li><a href="#example-logging-and-forwarding" id="toc-example-logging-and-forwarding"><span class="toc-section-number">2.1</span> Example: Logging and
Forwarding<span></span></a></li>
<li><a href="#example-logging_vector" id="toc-example-logging_vector"><span class="toc-section-number">2.2</span> Example:
<code class="sourceCode cpp">logging_vector</code><span></span></a>
<ul>
<li><a href="#renaming-and-projection" id="toc-renaming-and-projection"><span class="toc-section-number">2.2.1</span> Renaming and
Projection<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#metafunctions-for-template-declarations" id="toc-metafunctions-for-template-declarations"><span class="toc-section-number">3</span> Metafunctions for Template
Declarations<span></span></a>
<ul>
<li><a href="#synopsis" id="toc-synopsis"><span class="toc-section-number">3.1</span> Synopsis<span></span></a>
<ul>
<li><a href="#declaration_of" id="toc-declaration_of"><span class="toc-section-number">3.1.1</span>
<code class="sourceCode cpp">declaration_of</code><span></span></a></li>
<li><a href="#set_name" id="toc-set_name"><span class="toc-section-number">3.1.2</span>
<code class="sourceCode cpp">set_name</code><span></span></a></li>
<li><a href="#template_alternatives_of" id="toc-template_alternatives_of"><span class="toc-section-number">3.1.3</span>
<code class="sourceCode cpp">template_alternatives_of</code><span></span></a></li>
<li><a href="#template_parameters_of" id="toc-template_parameters_of"><span class="toc-section-number">3.1.4</span>
<code class="sourceCode cpp">template_parameters_of</code><span></span></a></li>
<li><a href="#template_parameter_list" id="toc-template_parameter_list"><span class="toc-section-number">3.1.5</span>
<code class="sourceCode cpp">template_parameter_list</code><span></span></a></li>
<li><a href="#attributes_of-add_attribute-remove_attribute" id="toc-attributes_of-add_attribute-remove_attribute"><span class="toc-section-number">3.1.6</span>
<code class="sourceCode cpp">attributes_of</code>,
<code class="sourceCode cpp">add_attribute</code>,
<code class="sourceCode cpp">remove_attribute</code><span></span></a></li>
<li><a href="#set_requires_clause-add_requires_clause_conjunction-add_requires_clause_disjunction" id="toc-set_requires_clause-add_requires_clause_conjunction-add_requires_clause_disjunction"><span class="toc-section-number">3.1.7</span>
<code class="sourceCode cpp">set_requires_clause</code>,
<code class="sourceCode cpp">add_requires_clause_conjunction</code>,
<code class="sourceCode cpp">add_requires_clause_disjunction</code><span></span></a></li>
<li><a href="#is_primary_template" id="toc-is_primary_template"><span class="toc-section-number">3.1.8</span>
<code class="sourceCode cpp">is_primary_template</code><span></span></a></li>
<li><a href="#overloads_of" id="toc-overloads_of"><span class="toc-section-number">3.1.9</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">3.1.10</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">3.1.11</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="#set_noexcept_clause-add_noexcept_clause_conjunction-add_noexcept_clause_disjunction" id="toc-set_noexcept_clause-add_noexcept_clause_conjunction-add_noexcept_clause_disjunction"><span class="toc-section-number">3.1.12</span>
<code class="sourceCode cpp">set_noexcept_clause</code>,
<code class="sourceCode cpp">add_noexcept_clause_conjunction</code>,
<code class="sourceCode cpp">add_noexcept_clause_disjunction</code><span></span></a></li>
<li><a href="#set_explicit_clause-add_explicit_clause_conjunction-add_explicit_clause_disjunction" id="toc-set_explicit_clause-add_explicit_clause_conjunction-add_explicit_clause_disjunction"><span class="toc-section-number">3.1.13</span>
<code class="sourceCode cpp">set_explicit_clause</code>,
<code class="sourceCode cpp">add_explicit_clause_conjunction</code>,
<code class="sourceCode cpp">add_explicit_clause_disjunction</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">3.1.14</span>
<code class="sourceCode cpp">is_declared_constexpr</code>,
<code class="sourceCode cpp">is_declared_consteval</code><span></span></a></li>
<li><a href="#parameters_of" id="toc-parameters_of"><span class="toc-section-number">3.1.15</span>
<code class="sourceCode cpp">parameters_of</code><span></span></a></li>
<li><a href="#parameter_list" id="toc-parameter_list"><span class="toc-section-number">3.1.16</span>
<code class="sourceCode cpp">parameter_list</code><span></span></a></li>
<li><a href="#forward_parameter_list" id="toc-forward_parameter_list"><span class="toc-section-number">3.1.17</span>
<code class="sourceCode cpp">forward_parameter_list</code><span></span></a></li>
<li><a href="#set_trailing_requires_clause-add_trailing_requires_clause_conjunction-add_trailing_requires_clause_disjunction" id="toc-set_trailing_requires_clause-add_trailing_requires_clause_conjunction-add_trailing_requires_clause_disjunction"><span class="toc-section-number">3.1.18</span>
<code class="sourceCode cpp">set_trailing_requires_clause</code>, <code class="sourceCode cpp">add_trailing_requires_clause_conjunction</code>,
<code class="sourceCode cpp">add_trailing_requires_clause_disjunction</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">4</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">5</span> Future Work<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span>
Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>Since <span class="citation" data-cites="P3420R0">[<a href="https://wg21.link/p3420r0" role="doc-biblioref">P3420R0</a>]</span>:</p>
<ul>
<li>replaced API that returns portions of a function declaration as a
token sequence with a functional-style API that takes a declaration and
returns a modified declaration</li>
<li>for implementation friendliness, removed metafunctions returning
code that potentially contains a mix of dependent and non-dependent
identifiers as token sequences</li>
<li>consequently, no need for the “as-if” rule for compiler-returned
token sequences</li>
</ul>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="motivation"><span class="header-section-number">2</span>
Motivation<a href="#motivation" class="self-link"></a></h1>
<p>A key trait that makes a reflection facility powerful is
<em>completeness</em>—the ability to reflect the entire 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, the language must necessarily reflect on 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 dependent
types are 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
two-pronged strategy for reflecting components of template
declarations:</p>
<ul>
<li>template parameter names and function parameter names can be
reflected as <em>token sequences</em>, as proposed in <span class="citation" data-cites="P3294R2">[<a href="https://wg21.link/p3294r2" role="doc-biblioref">P3294R2</a>]</span>;</li>
<li>the other elements of a template declaration—constraints, predicate
in the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> or
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
specifiers, default template arguments, and default function
arguments—are kept together with the template declaration;</li>
<li>new declarations are obtained from existing declarations in a
functional manner, and the “deltas” are expressed as token
sequences.</li>
</ul>
<p>The initial proposal <span class="citation" data-cites="P3420R0">[<a href="https://wg21.link/p3420r0" role="doc-biblioref">P3420R0</a>]</span> allowed accessing all parts of
a template definition as token sequences. However, for some
implementations performing such extrication was deemed difficult. Also,
separating parts of a function declaration made it difficult to define
how names are looked up after splicing.</p>
<p>We paid special attention to preserve the spirit and design style of
<span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> and to ensure seamless
interoperation with it.</p>
<h2 data-number="2.1" id="example-logging-and-forwarding"><span class="header-section-number">2.1</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">struct</span> Widget <span class="op">{}</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-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>
<span id="cb2-4"><a href="#cb2-4" 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-5"><a href="#cb2-5" 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, S<span class="op">&amp;)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> logger<span class="op">(</span><span class="kw">const</span> Ts<span class="op">&amp;..</span> values<span class="op">)</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="co">// Introspection will add declarations here.</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> logged <span class="op">{</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Widget <span class="op">{}</span>;  <span class="co">// for exposition purposes</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>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="co">// Given a function func, create a function logged::func that logs arguments.</span></span>
<span id="cb2-16"><a href="#cb2-16" 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-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">::</span>meta;</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>  namespace_inject<span class="op">(^^::</span>logged, <span class="op">^^{</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">[:</span>\<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)):]</span> <span class="op">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>      logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span> <span class="op">+</span> identifier_of<span class="op">(</span>f<span class="op">)</span> <span class="op">+</span> <span class="st">&quot;(&quot;</span>, \tokens<span class="op">(</span>parameter_list<span class="op">(</span>f<span class="op">))</span>, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">[:</span>f<span class="op">:]&lt;</span>\tokens<span class="op">(</span>template_parameter_list<span class="op">(</span>f<span class="op">))&gt;(</span>\tokens<span class="op">(</span>forward_parameter_list<span class="op">(</span>f<span class="op">)))</span>;</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>  make_logged<span class="op">(^^</span>fun<span class="op">)</span>;</span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent hand-written code:</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a><span class="co">// namespace logged {</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a><span class="co">//     template &lt;typename T&gt;</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a><span class="co">//     requires std::is_copy_constructible_v&lt;T&gt;</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a><span class="co">//     void fun(const T&amp; value, const ::Widget&amp; __p0) {</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a><span class="co">//         logger(&quot;Call to &quot;, &quot;fun&quot;, &quot;(&quot;, value, __p0, &quot;)&quot;);</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a><span class="co">//         return fun&lt;T&gt;(std::forward&lt;T&gt;(value), std::forward&lt;T&gt;(__p0));</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a><span class="co">//     }</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a><span class="co">// }</span></span></code></pre></div>
</blockquote>
</div>
<p>The code uses <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>namespace_inject</code>
as defined in <span class="citation" data-cites="P3294R1">[<a href="https://wg21.link/p3294r1" role="doc-biblioref">P3294R1</a>]</span> to create a function definition
from a token sequence in a given namespace, in this case
<code class="sourceCode cpp">logged</code>. We identify a few high-level
metafunctions that facilitate such manipulation of template
declarations. First, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>declaration_of<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info f<span class="op">)</span></code>
returns a reflection handle (i.e. an <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
value) corresponding to the declaration (prototype) of the function
template reflected by <code class="sourceCode cpp">f</code>. The
template parameters,
<code class="sourceCode cpp"><span class="kw">requires</span></code> and
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clauses (if present), function parameters, and return type are all part
of the returned reflection. Most importantly, the declaration can be
modified and spliced back into code.</p>
<p>Names used in <code class="sourceCode cpp">declaration_of</code> are
handled in a hygienic manner that prevents unintended binding. All
non-dependent names are looked up in the original declaration. Thus,
even if namespace <code class="sourceCode cpp">logged</code> defines a
type called <code class="sourceCode cpp">Widget</code>, the declaration
returned by <code class="sourceCode cpp">declaration_of</code> uses the
same <code class="sourceCode cpp">Widget</code> as the original
declaration (which is why we used
<code class="sourceCode cpp"><span class="op">::</span>Widget</code> in
the comment representing equivalent code). Dependent names are, as
expected, not looked up. The name of the function itself also
information about what scope <code class="sourceCode cpp">f</code> was
defined in (in our example the global namespace), but the primitive
<code class="sourceCode cpp">namespace_inject</code> ignores that
information and injects a new function of the same name in the given
namespace.</p>
<p>The metafunction <code class="sourceCode cpp">template_parameter_list<span class="op">(</span>f<span class="op">)</span></code>
returns, for the reflection <code class="sourceCode cpp">f</code> of a
function template, a token sequence consisting of the comma-separated
list of that function’s template parameters. That token sequence can be
spliced in code that generates the instantiation of <code class="sourceCode cpp"><span class="op">[:</span>f<span class="op">:]</span></code>
or a template with similar parameters. The names of the parameters are
implementation-defined and bear no relationship with the user-given
parameter names in the declaration of
<code class="sourceCode cpp">f</code>; this avoids possible ambiguities
created by duplicate declarations and also sidesteps awkward issues such
as handling unnamed parameters. User code may assume each parameter name
is world-unique, which implies that <code class="sourceCode cpp">template_parameter_list<span class="op">(</span>f<span class="op">)</span></code>
is meaningful only from within a declaration created with
<code class="sourceCode cpp">declaration_of</code> (or from within the
function reflected by <code class="sourceCode cpp">f</code> itself).</p>
<p>Next, <code class="sourceCode cpp">parameter_list<span class="op">(</span>f<span class="op">)</span></code>
produces a token sequence consisting of the comma-separated list of the
parameters of <code class="sourceCode cpp">f</code>, with pack expansion
suffix where applicable. The list can be spliced in code that passes the
function parameters to another function call. In our case,
<code class="sourceCode cpp">parameter_list</code> is used to pass all
parameters to template function
<code class="sourceCode cpp">logger</code>. Just like with
<code class="sourceCode cpp">template_parameter_list</code>, the
parameter names are chosen by the implementation and can be considered
world-unique.</p>
<p>Finally, <code class="sourceCode cpp">forward_parameter_list<span class="op">(</span>f<span class="op">)</span></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. The example uses
<code class="sourceCode cpp">forward_parameter_list</code> to pass the
generated function’s arguments down to the implementation.</p>
<p>To recap, we propose generating new functions (or function templates)
from existing ones by splicing
<code class="sourceCode cpp">declaration_of</code> for copying the
function prototype, followed by the new function body as a token
sequence. To access and pass around template parameters (when
appropriate) and function parameters, we propose the helper
metafunctions
<code class="sourceCode cpp">template_parameter_list</code>,
<code class="sourceCode cpp">parameter_list</code>, and
<code class="sourceCode cpp">forward_parameter_list</code>. These
primitives allow manipulating parameters without needing to name them
explicitly.</p>
<h2 data-number="2.2" id="example-logging_vector"><span class="header-section-number">2.2</span> Example:
<code class="sourceCode cpp">logging_vector</code><a href="#example-logging_vector" class="self-link"></a></h2>
<p>Consider a more elaborate example of a class template
<code class="sourceCode cpp">logging_vector</code>, which defines a
functional equivalent of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
but that uses a function <code class="sourceCode cpp">logger</code> to
log all calls to its member functions. Here, we need to iterate the
public members of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
and insert appropriate copies of declarations.</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> A <span class="op">=</span> std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> logging_vector <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span> data;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">::</span>meta;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">:</span> get_public_members<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;))</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>is_type_alias<span class="op">(</span>r<span class="op">)</span> <span class="op">||</span> is_class_type<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        queue_injection<span class="op">(^^{</span> <span class="kw">using</span> \id<span class="op">(</span>identifier_of<span class="op">(</span>r<span class="op">))</span> <span class="op">=</span> <span class="op">[:</span>\<span class="op">(</span>r<span class="op">):]</span>; <span class="op">})</span>;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>is_function<span class="op">(</span>r<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">!</span>is_special_member_function<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        queue_injection<span class="op">(^^{</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>          <span class="op">[:</span>\<span class="op">(</span>declaration_of<span class="op">(</span>r<span class="op">)):]</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>            logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span>, identifier_of<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;)</span>, <span class="st">&quot;::&quot;</span>,</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>              identifier_of<span class="op">(</span>r<span class="op">)</span>, <span class="st">&quot;(&quot;</span>, \tokens<span class="op">(</span>parameter_list<span class="op">(</span>r<span class="op">))</span>, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> data<span class="op">.[:</span>r<span class="op">:](</span>forward_param_list_of<span class="op">(</span>r<span class="op">))</span>;</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>is_function_template<span class="op">(</span>r<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">!</span>is_constructor<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>        queue_injection<span class="op">(^^{</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>          <span class="op">[:</span>\<span class="op">(</span>declaration_of<span class="op">(</span>r<span class="op">)):]</span> <span class="op">{</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>            logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span>, identifier_of<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;)</span>, <span class="st">&quot;::&quot;</span>,</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>              identifier_of<span class="op">(</span>r<span class="op">)</span>, <span class="st">&quot;(&quot;</span>, \tokens<span class="op">(</span>parameter_list<span class="op">(</span>r<span class="op">))</span>, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> data<span class="op">.</span><span class="kw">template</span> <span class="op">[:</span>r<span class="op">:]&lt;</span>\tokens<span class="op">(</span>template_parameter_list<span class="op">(</span>r<span class="op">))&gt;(</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>              \tokens<span class="op">(</span>forward_parameters_list<span class="op">(</span>r<span class="op">))</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span>;</span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>is_constructor<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>        queue_injection<span class="op">(^^{</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>          <span class="op">[:</span>\<span class="op">(</span>declaration_of<span class="op">(</span>r<span class="op">)):]</span> <span class="op">:</span> data<span class="op">(</span>\tokens<span class="op">(</span>forward_parameters_list<span class="op">(</span>r<span class="op">)))</span> <span class="op">{}</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Ignore other nested declarations.</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>(Refer to <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> for metafunctions
<code class="sourceCode cpp">get_public_members</code>,
<code class="sourceCode cpp">is_type_alias</code>,
<code class="sourceCode cpp">is_class_type</code>,
<code class="sourceCode cpp">is_function</code>,
<code class="sourceCode cpp">is_function_template</code>, and
<code class="sourceCode cpp">identifier_of</code>, of which semantics
should be intuitive as we discuss the context.) Here, as the code
iterates declarations in class <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>
(an instance, not the template class itself, which simplifies a few
aspects of the example), it takes action depending on the nature of the
declaration found. For
<code class="sourceCode cpp"><span class="kw">typedef</span></code> (or
equivalent
<code class="sourceCode cpp"><span class="kw">using</span></code>)
declarations and for nested class declaration, a
<code class="sourceCode cpp"><span class="kw">using</span></code>
declaration of the form
<code class="sourceCode cpp"><span class="kw">using</span></code>
<em>name</em> <code class="sourceCode cpp"><span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;::</span>name;</code>
is issued for each corresponding <em>name</em> found in <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>.</p>
<p>If the iterated declaration introduces a non-special function
(filtered with the test <code class="sourceCode cpp">is_function<span class="op">(</span>r<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">!</span>is_special_member_function<span class="op">(</span>r<span class="op">)</span></code>),
a new function is defined with the same signature. The definition issues
a call to <code class="sourceCode cpp">logger</code> passing the
parameters list, followed by a forwarding action to the original
function for the <code class="sourceCode cpp">data</code> member.</p>
<p>If the iterated declaration is that of a non-special function
template (filtered by testing <code class="sourceCode cpp">is_function_template<span class="op">(</span>r<span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="op">!</span>is_constructor<span class="op">(</span>r<span class="op">)</span></code>),
the code synthesizes a function template. Although the the template
declaration has considerably more elements, the same
<code class="sourceCode cpp">declaration_of</code> metafunction
primitive is used. In the synthesized declaration, all names are already
looked up in the context of the <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>
instantiation; for example,
<code class="sourceCode cpp">begin<span class="op">()</span></code>
returns type <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;::</span>iterator</code>
and not <code class="sourceCode cpp">logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;::</span>iterator</code>
(even if that name has been declared as an alias).</p>
<p>Finally, if the iterated declaration is a constructor, it is handled
separately because the generated code has a distinct syntax. For
constructors (whether templated or not), the generated code simply
forwards all parameters to the constructor of the payload.</p>
<p>For seeing how variadic parameters are handled, consider the function
<code class="sourceCode cpp">emplace</code> that is declared as a
variadic function template with the signature <code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> A<span class="op">&gt;</span> iterator emplace<span class="op">(</span>const_iterator, A<span class="op">&amp;&amp;...)</span>;</code>.
For the reflection of <code class="sourceCode cpp">emplace</code>,
calling <code class="sourceCode cpp">template_parameter_list</code>
returns the token sequence <code class="sourceCode cpp"><span class="op">^^{</span> _T0<span class="op">...</span> <span class="op">}</span></code>
(exact name chosen by the implementation), which is suitable for passing
to the instantiation of another template. Correspondingly,
<code class="sourceCode cpp">parameter_list</code> returns the token
sequence <code class="sourceCode cpp"><span class="op">^^{</span> __p0, __p1<span class="op">...</span> <span class="op">}</span></code>.
This token sequence can be expanded anywhere the arguments of the called
function are needed.</p>
<p>It is worth noting that the forwarding call syntaxes <code class="sourceCode cpp">data<span class="op">.[:</span>r<span class="op">:](...)</span></code>
(for regular functions) and <code class="sourceCode cpp">data<span class="op">.</span><span class="kw">template</span> <span class="op">[:</span>r<span class="op">:]&lt;...&gt;(...)</span></code>
(for function templates) are already defined with the expected semantics
in <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>, and work properly in the
prototype implementations. The only added elements are the metafunctions
<code class="sourceCode cpp">template_parameter_list</code>,
<code class="sourceCode cpp">parameter_list</code>, and
<code class="sourceCode cpp">forward_parameter_list</code>, which ensure
proper passing down of parameter names from the synthesized function to
to the corresponding member function.</p>
<h3 data-number="2.2.1" id="renaming-and-projection"><span class="header-section-number">2.2.1</span> Renaming and Projection<a href="#renaming-and-projection" class="self-link"></a></h3>
<p>The <code class="sourceCode cpp">logging_vector</code> example has an
issue related to member functions of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
that refer to
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
itself in their signature, such as <code class="sourceCode cpp"><span class="dt">void</span> swap<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;&amp;)</span></code>.
The example as written above will generate code equivalent to the
following:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> A<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> logging_vector <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;&amp;</span> other<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span>, <span class="st">&quot;std::vector&lt;T, A&gt;&quot;</span>, <span class="st">&quot;::&quot;</span>,</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;swap&quot;</span>, <span class="st">&quot;(&quot;</span>, other, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> data<span class="op">.</span>swap<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>other<span class="op">)&gt;(</span>other<span class="op">))</span>;</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The declaration is technically correct, but not what was intended. We
need to define <code class="sourceCode cpp">swap</code> as taking
another instance of <code class="sourceCode cpp">logging_vector</code>,
i.e., <code class="sourceCode cpp"><span class="dt">void</span> swap<span class="op">(</span>logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;&amp;)</span></code>:</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="dt">void</span> swap<span class="op">(</span>logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;&amp;</span> other<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span>, <span class="st">&quot;std::vector&lt;T, A&gt;&quot;</span>, <span class="st">&quot;::&quot;</span>,</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>      <span class="st">&quot;swap&quot;</span>, <span class="st">&quot;(&quot;</span>, other<span class="op">.</span>data, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> data<span class="op">.</span>swap<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>other<span class="op">)&gt;(</span>other<span class="op">).</span>data<span class="op">)</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>There are two fundamental transformation we need to perform to morph
the original <code class="sourceCode cpp">vector<span class="op">&lt;</span>T, A<span class="op">&gt;::</span>swap</code>
into its desired counterpart inside
<code class="sourceCode cpp">logging_vector</code>:</p>
<ul>
<li><em>Replacement:</em> for all parameters in the signature that have
type <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>,
change their type to <code class="sourceCode cpp">logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>;
and</li>
<li><em>Projection:</em> for all parameters
<code class="sourceCode cpp">p</code> in the function body that have
type <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>,
replace <code class="sourceCode cpp">p</code> with
<code class="sourceCode cpp">p<span class="op">.</span>data</code>.</li>
</ul>
<p>For replacement, we propose a primitive metafunction
<code class="sourceCode cpp">replace</code> that replaces a type with
another throughout a declaration, potentially in multiple places, in a
manner reminiscent to the <a href="https://opendsa.cs.vt.edu/ODSA/Books/PL/html/AlphaConversion.html">alpha
renaming</a> notion found in lambda calculus. To that end we define
<code class="sourceCode cpp">replace</code> for declarations, with the
signature:</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>info replace<span class="op">(</span>info declaration, info replace_this, info with_this<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The metafunction returns a new declaration with the replacements
effected. To improve the
<code class="sourceCode cpp">logging_vector</code> example above, we’d
need to replace the uses of <code class="sourceCode cpp">declaration_of<span class="op">(</span>f<span class="op">)</span></code>
with <code class="sourceCode cpp">replace<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)</span>, <span class="op">^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span>, <span class="op">^^</span>logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;))</span></code>.
The construct would transform properly all declarations.</p>
<p>Projection is trickier because not all parameters should be affected,
only those whose type (after removing cvref qualifiers) is <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>.
To effect projection, user code defines a <em>projection
function</em>:</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="co">// Inside logging_vector&#39;s definition</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> X<span class="op">&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> project<span class="op">(</span>X<span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>X<span class="op">&gt;</span>, std<span class="op">::</span>logging_vector<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">.</span>data<span class="op">)&gt;(</span>x<span class="op">.</span>data<span class="op">)</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>forward<span class="op">&lt;</span>X<span class="op">&gt;(</span>x<span class="op">)</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We then propose a standard metafunction that applies a projection
function to each parameter of a function:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>info project_parameters<span class="op">(</span>info declaration, info projection_function<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Armed with these artifacts, we can have reflection generate proper
forwarding functions from existing member functions of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
like this:</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="co">// For member functions of std::vector&lt;T, A&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> my_decl <span class="op">=</span> replace<span class="op">(</span>declaration_of<span class="op">(</span>r<span class="op">)</span>, <span class="op">^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span>, <span class="op">^^</span>logging_vector<span class="op">&lt;</span>T, A<span class="op">&gt;)</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> my_params <span class="op">=</span> project_parameters<span class="op">(</span>r, <span class="op">^^</span>project<span class="op">)</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>        queue_injection<span class="op">(^^{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>          <span class="op">[:</span>\<span class="op">(</span>decl<span class="op">):]</span> <span class="op">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>            logger<span class="op">(</span><span class="st">&quot;Calling &quot;</span>, identifier_of<span class="op">(^^</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;)</span>, <span class="st">&quot;::&quot;</span>,</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>              identifier_of<span class="op">(</span>r<span class="op">)</span>, <span class="st">&quot;(&quot;</span>, \tokens<span class="op">(</span>my_params<span class="op">)</span>, <span class="st">&quot;)&quot;</span><span class="op">)</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> data<span class="op">.[:</span>r<span class="op">:](</span>forward_param_list_of<span class="op">(</span>my_params<span class="op">))</span>;</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The code for member function templates is similar. One notable detail
is that <code class="sourceCode cpp">forward_param_list_of</code> works
seamlessly on function declarations and on projected parameter lists
(flexibility made possible by the uniform representation of code
artifacts as <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
objects).</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="metafunctions-for-template-declarations"><span class="header-section-number">3</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">declaration_of<span class="op">(</span>f<span class="op">)</span></code>
may seem sufficient. 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. Therefore, we aim to identify structural components of the
declaration and define primitives that manipulate each in turn. That
way, we offer unbounded customization opportunities by allowing users to
amend the original declaration with custom code.</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="3.1" id="synopsis"><span class="header-section-number">3.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="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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Returns the reflection of the declaration of a template</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> declaration_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Replacement</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> replace<span class="op">(</span>info declaration, info replace_this, info with_this<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Projection</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> project_parameters<span class="op">(</span>info declaration, info projection_function<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Returns given declaration with a changed name</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> set_name<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">//  Multiple explicit specializations and/or partial specializations</span></span>
<span id="cb10-11"><a href="#cb10-11" 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="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Template parameters vector</span></span>
<span id="cb10-13"><a href="#cb10-13" 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="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Comma-separated template parameter list</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> template_parameter_list<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Attributes - extension of semantics in P3385</span></span>
<span id="cb10-17"><a href="#cb10-17" 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="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_attribute<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> remove_attribute<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Template-level requires clause</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> set_requires_clause<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_requires_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_requires_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Is this the reflection of the primary template declaration?</span></span>
<span id="cb10-25"><a href="#cb10-25" 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="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Overloads of a given function name</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> overloads_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="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Inline specifier present?</span></span>
<span id="cb10-29"><a href="#cb10-29" 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="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// cvref qualifiers and others - extensions of semantics in P2996</span></span>
<span id="cb10-31"><a href="#cb10-31" 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="cb10-32"><a href="#cb10-32" 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="cb10-33"><a href="#cb10-33" 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="cb10-34"><a href="#cb10-34" 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="cb10-35"><a href="#cb10-35" 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="cb10-36"><a href="#cb10-36" 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="cb10-37"><a href="#cb10-37" 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="cb10-38"><a href="#cb10-38" 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="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>    <span class="co">// predicate for `noexcept`</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> set_noexcept_clause<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_noexcept_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_noexcept_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `explicit` present? - extension of P2996</span></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a>    <span class="co">// predicate for `explicit`</span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> set_explicit_clause<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_explicit_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_explicit_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `constexpr` present?</span></span>
<span id="cb10-49"><a href="#cb10-49" 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="cb10-50"><a href="#cb10-50" aria-hidden="true" tabindex="-1"></a>    <span class="co">// `consteval` present?</span></span>
<span id="cb10-51"><a href="#cb10-51" 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="cb10-52"><a href="#cb10-52" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Function template parameters</span></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> 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="cb10-54"><a href="#cb10-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> parameter_list<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="cb10-55"><a href="#cb10-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> forward_parameter_list<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="cb10-56"><a href="#cb10-56" aria-hidden="true" tabindex="-1"></a>    <span class="co">//</span></span>
<span id="cb10-57"><a href="#cb10-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> set_trailing_requires_clause<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-58"><a href="#cb10-58" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_trailing_requires_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-59"><a href="#cb10-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> add_trailing_requires_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb10-60"><a href="#cb10-60" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="3.1.1" id="declaration_of"><span class="header-section-number">3.1.1</span>
<code class="sourceCode cpp">declaration_of</code><a href="#declaration_of" class="self-link"></a></h3>
<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">consteval</span> <span class="kw">auto</span> declaration_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the reflection of the declaration of a type or template.
Subsequently that reflection can be inserted as part of a token
sequence. Typical uses issue a call
<code class="sourceCode cpp">declaration_of</code> and then compute a
slightly modified declaration before splicing it.</p>
<h3 data-number="3.1.2" id="set_name"><span class="header-section-number">3.1.2</span>
<code class="sourceCode cpp">set_name</code><a href="#set_name" class="self-link"></a></h3>
<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>info set_name<span class="op">(</span>info, string_view new_name<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given a reflection, returns a reflection that is identical except for
the name which is <code class="sourceCode cpp">new_name</code>.
Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" 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="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f <span class="op">=</span> <span class="op">^^</span>fun;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  queue_injection<span class="op">(^^{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">[:</span>\<span class="op">(</span>set_name<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)</span>, <span class="st">&quot;my_fun&quot;</span><span class="op">)):]</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">[:</span>f<span class="op">:]&lt;</span>\tokens<span class="op">(</span>template_parameters_of<span class="op">(</span>f<span class="op">))&gt;(</span>\tokens<span class="op">(</span>forward_parameter_list<span class="op">(</span>f<span class="op">)))</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent code:</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="co">// template &lt;typename T&gt;</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a><span class="co">// void my_fun(const T&amp; value) {</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a><span class="co">//   return fun&lt;T&gt;(value);</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="co">// }</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="3.1.3" id="template_alternatives_of"><span class="header-section-number">3.1.3</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="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-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="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="co">// Primary template declaration</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="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="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization</span></span>
<span id="cb15-4"><a href="#cb15-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="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Partial specialization</span></span>
<span id="cb15-6"><a href="#cb15-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> in the
example above 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="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="co">// Primary declaration</span></span>
<span id="cb16-2"><a href="#cb16-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="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization</span></span>
<span id="cb16-4"><a href="#cb16-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="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicit specialization, depends on the previous one</span></span>
<span id="cb16-6"><a href="#cb16-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="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Partial specialization, may depend on both previous ones</span></span>
<span id="cb16-8"><a href="#cb16-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="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">typename</span> T<span class="op">&gt;</span> <span class="kw">class</span> C;</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> C<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">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="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Get reflections for the primary and the two specializations</span></span>
<span id="cb17-6"><a href="#cb17-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="cb17-7"><a href="#cb17-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="cb17-8"><a href="#cb17-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="3.1.4" id="template_parameters_of"><span class="header-section-number">3.1.4</span>
<code class="sourceCode cpp">template_parameters_of</code><a href="#template_parameters_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> template_parameters_of<span class="op">(</span>info<span class="op">)</span>;</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 parameter names (a
parameter pack counts as one parameter and is followed by
<code class="sourceCode cpp"><span class="op">...</span></code>). To
avoid name clashes, the implementation chooses unique names. (Our
examples use <code class="sourceCode cpp"><span class="st">&quot;_T&quot;</span></code>
followed by a number.) For function templates, it is guaranteed that
<code class="sourceCode cpp">declaration_of</code> and
<code class="sourceCode cpp">template_parameters_of</code> will use the
same names. For example, <code class="sourceCode cpp">template_parameters_of<span class="op">(^^</span>A<span class="op">)</span></code>
may yield the token sequences <code class="sourceCode cpp"><span class="op">^^{</span>_T0<span class="op">}</span></code>,
<code class="sourceCode cpp"><span class="op">^^{</span>_T1<span class="op">}</span></code>,
and <code class="sourceCode cpp"><span class="op">^^{</span>_T2<span class="op">...}</span></code>.</p>
<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="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>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="co">// r refers to A&lt;int&gt;</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> 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">// pick specialization</span></span>
<span id="cb19-6"><a href="#cb19-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>For partial specializations of class templates,
<code class="sourceCode cpp">template_parameters_of</code> returns the
parameters of the partial specialization (not those of the primary
template). For example:</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">&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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<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>T, U<span class="op">&gt;&gt;</span>;</span>
<span id="cb20-3"><a href="#cb20-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 class="co">// pick specialization</span></span>
<span id="cb20-4"><a href="#cb20-4" 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>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>Given a class template <code class="sourceCode cpp">A</code> that has
explicit instantiations and/or partial specializations declared,
referring the template by name in 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="3.1.5" id="template_parameter_list"><span class="header-section-number">3.1.5</span>
<code class="sourceCode cpp">template_parameter_list</code><a href="#template_parameter_list" class="self-link"></a></h3>
<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">consteval</span> <span class="kw">auto</span> template_parameter_list<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span></code></pre></div>
</blockquote>
</div>
<p>Returns the result of
<code class="sourceCode cpp">template_parameters_of</code> as a
comma-separated list in a token sequence. Variadics, if any, are
followed by
<code class="sourceCode cpp"><span class="op">...</span></code>.</p>
<h3 data-number="3.1.6" id="attributes_of-add_attribute-remove_attribute"><span class="header-section-number">3.1.6</span>
<code class="sourceCode cpp">attributes_of</code>,
<code class="sourceCode cpp">add_attribute</code>,
<code class="sourceCode cpp">remove_attribute</code><a href="#attributes_of-add_attribute-remove_attribute" class="self-link"></a></h3>
<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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> attributes_of<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>info add_attribute<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>info remove_attribute<span class="op">(</span>info, info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p><code class="sourceCode cpp">attributes_of</code> 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 <span class="citation" data-cites="P3385R0">[<a href="https://wg21.link/p3385r0" role="doc-biblioref">P3385R0</a>]</span> to template declarations.</p>
<p><code class="sourceCode cpp">add_attribute<span class="op">(</span>r, attr<span class="op">)</span></code>
returns a reflection that adds the attribute
<code class="sourceCode cpp">attr</code> to the given reflection
<code class="sourceCode cpp">r</code>. If
<code class="sourceCode cpp">r</code> already had the attribute, it is
returned.</p>
<p><code class="sourceCode cpp">remove_attribute</code> returns a
reflection that removes the attribute
<code class="sourceCode cpp">attr</code> from the given reflection
<code class="sourceCode cpp">r</code>. If
<code class="sourceCode cpp">r</code> did now have the attribute, it is
returned.</p>
<p>We defer details and particulars to <span class="citation" data-cites="P3385R0">[<a href="https://wg21.link/p3385r0" role="doc-biblioref">P3385R0</a>]</span>.</p>
<h3 data-number="3.1.7" id="set_requires_clause-add_requires_clause_conjunction-add_requires_clause_disjunction"><span class="header-section-number">3.1.7</span>
<code class="sourceCode cpp">set_requires_clause</code>,
<code class="sourceCode cpp">add_requires_clause_conjunction</code>,
<code class="sourceCode cpp">add_requires_clause_disjunction</code><a href="#set_requires_clause-add_requires_clause_conjunction-add_requires_clause_disjunction" 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>info set_requires_clause<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>info add_requires_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>info add_requires_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template,
<code class="sourceCode cpp">set_requires_clause</code> returns a
reflection of an identical template but with the
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause replaced by the token sequence given in the second parameter. The
existing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause in the template, if any, is ignored. 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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb24-2"><a href="#cb24-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">64</span><span class="op">)</span></span>
<span id="cb24-3"><a href="#cb24-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="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="kw">consteval</span> <span class="op">{</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f <span class="op">=</span> <span class="op">^^</span>fun;</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  queue_injection<span class="op">(^^{</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">[:</span>\<span class="op">(</span>set_requires_clause<span class="op">(</span>set_name<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)</span>, <span class="st">&quot;my_fun&quot;</span><span class="op">))</span>,</span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">^^{</span> <span class="kw">sizeof</span><span class="op">(</span>\tokens<span class="op">(</span>template_parameters_of<span class="op">(</span>f<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span> <span class="op">==</span> <span class="dv">128</span> <span class="op">}):]</span>;</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent code:</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a><span class="co">// template &lt;typename T&gt;</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a><span class="co">// requires (sizeof(T) == 128)</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a><span class="co">// void my_fun(const T&amp; value);</span></span></code></pre></div>
</blockquote>
</div>
<p>The functions
<code class="sourceCode cpp">add_requires_clause_conjunction</code> and
<code class="sourceCode cpp">add_requires_clause_disjunction</code>
compose the given token sequence with the existing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause. (If no such clause exists, it is assumed to be the expression
<code class="sourceCode cpp"><span class="kw">true</span></code>.) The
<code class="sourceCode cpp">add_requires_clause_conjunction</code>
metafunction performs a conjunction (logical “and”) between the clause
given in the token sequence and the existing token sequence. The
<code class="sourceCode cpp">add_requires_clause_disjunction</code>
metafunction performs a disjunction (logical “or”) between the clause
given in the token sequence and the existing token sequence.</p>
<p>Calling <code class="sourceCode cpp">set_requires_clause</code>,
<code class="sourceCode cpp">add_requires_clause_conjunction</code>, or
<code class="sourceCode cpp">add_requires_clause_disjunction</code>
against a non-template, as in <code class="sourceCode cpp">set_requires_clause<span class="op">(^^</span><span class="dt">int</span>, <span class="op">^^{</span><span class="kw">true</span><span class="op">})</span></code>,
fails to evaluate to a constant expression.</p>
<h3 data-number="3.1.8" id="is_primary_template"><span class="header-section-number">3.1.8</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="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="dt">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="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">class</span><span class="op">&gt;</span> <span class="kw">class</span> A;</span>
<span id="cb26-2"><a href="#cb26-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="cb26-3"><a href="#cb26-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="cb26-4"><a href="#cb26-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="cb26-5"><a href="#cb26-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="cb26-6"><a href="#cb26-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="3.1.9" id="overloads_of"><span class="header-section-number">3.1.9</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="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-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> (<span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>) can be used. 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="dt">void</span> f<span class="op">()</span>;</span>
<span id="cb28-2"><a href="#cb28-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="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Name f has two overloads present.</span></span>
<span id="cb28-5"><a href="#cb28-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="3.1.10" id="is_inline"><span class="header-section-number">3.1.10</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="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="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="3.1.11" 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">3.1.11</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="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="dt">bool</span> is_const<span class="op">(</span>info<span class="op">)</span>;</span>
<span id="cb30-2"><a href="#cb30-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="cb30-3"><a href="#cb30-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="cb30-4"><a href="#cb30-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="cb30-5"><a href="#cb30-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="cb30-6"><a href="#cb30-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="cb30-7"><a href="#cb30-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="cb30-8"><a href="#cb30-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 <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> to function templates.</p>
<p>For <code class="sourceCode cpp">is_noexcept</code> and
<code class="sourceCode cpp">is_explicit</code>,
<code class="sourceCode cpp"><span class="kw">true</span></code> is
returned if the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> and
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
clause, respectively, is predicated.</p>
<h3 data-number="3.1.12" id="set_noexcept_clause-add_noexcept_clause_conjunction-add_noexcept_clause_disjunction"><span class="header-section-number">3.1.12</span>
<code class="sourceCode cpp">set_noexcept_clause</code>,
<code class="sourceCode cpp">add_noexcept_clause_conjunction</code>,
<code class="sourceCode cpp">add_noexcept_clause_disjunction</code><a href="#set_noexcept_clause-add_noexcept_clause_conjunction-add_noexcept_clause_disjunction" 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>info set_noexcept_clause<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>info add_noexcept_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>info add_noexcept_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template,
<code class="sourceCode cpp">set_noexcept_clause</code> returns a
reflection of an identical template but with the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause replaced by the token sequence given in the second parameter. The
existing
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause in the template, if any, is ignored. 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="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="kw">noexcept</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">64</span><span class="op">)</span></span>
<span id="cb32-3"><a href="#cb32-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="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f <span class="op">=</span> <span class="op">^^</span>fun;</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>  queue_injection<span class="op">(^^{</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">[:</span>\<span class="op">(</span>set_noexcept_clause<span class="op">(</span>set_name<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)</span>, <span class="st">&quot;my_fun&quot;</span><span class="op">))</span>,</span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">^^{</span> <span class="kw">sizeof</span><span class="op">(</span>\tokens<span class="op">(</span>template_parameters_of<span class="op">(</span>f<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span> <span class="op">==</span> <span class="dv">128</span> <span class="op">}):]</span>;</span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent code:</span></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a><span class="co">// template &lt;typename T&gt;</span></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a><span class="co">// noexcept (sizeof(T) == 128)</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a><span class="co">// void my_fun(const T&amp; value);</span></span></code></pre></div>
</blockquote>
</div>
<p>The functions
<code class="sourceCode cpp">add_noexcept_clause_conjunction</code> and
<code class="sourceCode cpp">add_noexcept_clause_disjunction</code>
compose the given token sequence with the existing
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause. (If no such clause exists, it is assumed to be the expression
<code class="sourceCode cpp"><span class="kw">true</span></code>.) The
<code class="sourceCode cpp">add_noexcept_clause_conjunction</code>
metafunction performs a conjunction (logical “and”) between the clause
given in the token sequence and the existing token sequence. The
<code class="sourceCode cpp">add_noexcept_clause_disjunction</code>
metafunction performs a disjunction (logical “or”) between the clause
given in the token sequence and the existing token sequence.</p>
<p>Calling <code class="sourceCode cpp">set_noexcept_clause</code>,
<code class="sourceCode cpp">add_noexcept_clause_conjunction</code>, or
<code class="sourceCode cpp">add_noexcept_clause_disjunction</code>
against a non-template, as in <code class="sourceCode cpp">set_noexcept_clause<span class="op">(^^</span><span class="dt">int</span>, <span class="op">^^{</span><span class="kw">true</span><span class="op">})</span></code>,
fails to evaluate to a constant expression.</p>
<h3 data-number="3.1.13" id="set_explicit_clause-add_explicit_clause_conjunction-add_explicit_clause_disjunction"><span class="header-section-number">3.1.13</span>
<code class="sourceCode cpp">set_explicit_clause</code>,
<code class="sourceCode cpp">add_explicit_clause_conjunction</code>,
<code class="sourceCode cpp">add_explicit_clause_disjunction</code><a href="#set_explicit_clause-add_explicit_clause_conjunction-add_explicit_clause_disjunction" 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>info set_explicit_clause<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>info add_explicit_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>info add_explicit_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template,
<code class="sourceCode cpp">set_explicit_clause</code> returns a
reflection of an identical template but with the
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
clause replaced by the token sequence given in the second parameter. The
existing
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
specifier in the template, if any, is ignored.</p>
<p>The functions
<code class="sourceCode cpp">add_explicit_clause_conjunction</code> and
<code class="sourceCode cpp">add_explicit_clause_disjunction</code>
compose the given token sequence with the existing
<code class="sourceCode cpp"><span class="kw">explicit</span></code>
clause. (If no such clause exists, it is assumed to be the expression
<code class="sourceCode cpp"><span class="kw">true</span></code>.) The
<code class="sourceCode cpp">add_explicit_clause_conjunction</code>
metafunction performs a conjunction (logical “and”) between the clause
given in the token sequence and the existing token sequence. The
<code class="sourceCode cpp">add_explicit_clause_disjunction</code>
metafunction performs a disjunction (logical “or”) between the clause
given in the token sequence and the existing token sequence.</p>
<p>Calling <code class="sourceCode cpp">set_explicit_clause</code>,
<code class="sourceCode cpp">add_explicit_clause_conjunction</code>, or
<code class="sourceCode cpp">add_explicit_clause_disjunction</code>
against a non-template, as in <code class="sourceCode cpp">set_explicit_clause<span class="op">(^^</span><span class="dt">int</span>, <span class="op">^^{</span><span class="kw">true</span><span class="op">})</span></code>,
fails to evaluate to a constant expression.</p>
<h3 data-number="3.1.14" id="is_declared_constexpr-is_declared_consteval"><span class="header-section-number">3.1.14</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="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_declared_constexpr<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_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="3.1.15" id="parameters_of"><span class="header-section-number">3.1.15</span>
<code class="sourceCode cpp">parameters_of</code><a href="#parameters_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>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> parameters_of<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Returns an array of token sequences containing the parameter names of
the function template represented by
<code class="sourceCode cpp">info</code>. Parameter names are chosen by
the implementation. It is guaranteed that the nmes returned by <code class="sourceCode cpp">parameters_of<span class="op">(</span>f<span class="op">)</span></code>
are consistent with the names returned by <code class="sourceCode cpp">parameters_of<span class="op">(</span>f<span class="op">)</span></code>
for any reflection <code class="sourceCode cpp">f</code> of a function
template.</p>
<p>This function bears similarities with
<code class="sourceCode cpp">parameters_of</code> in <span class="citation" data-cites="P3096R3">[<a href="https://wg21.link/p3096r3" role="doc-biblioref">P3096R3</a>]</span>. 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="3.1.16" id="parameter_list"><span class="header-section-number">3.1.16</span>
<code class="sourceCode cpp">parameter_list</code><a href="#parameter_list" 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 parameter_list<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Convenience function that returns the parameters returned by
<code class="sourceCode cpp">parameters_of</code> in the form of a
comma-separated list. The result is returned as a token sequence.</p>
<h3 data-number="3.1.17" id="forward_parameter_list"><span class="header-section-number">3.1.17</span>
<code class="sourceCode cpp">forward_parameter_list</code><a href="#forward_parameter_list" 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>info forward_parameter_list<span class="op">(</span>info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Convenience function that returns the parameters returned by
<code class="sourceCode cpp">parameters_of</code> in the form of a
comma-separated list, each passed to
<code class="sourceCode cpp">std<span class="op">::</span>forward</code>
appropriately. The result is returned as a token sequence and can be
spliced in a call to foward all parameters to another function.</p>
<h3 data-number="3.1.18" id="set_trailing_requires_clause-add_trailing_requires_clause_conjunction-add_trailing_requires_clause_disjunction"><span class="header-section-number">3.1.18</span>
<code class="sourceCode cpp">set_trailing_requires_clause</code>, <code class="sourceCode cpp">add_trailing_requires_clause_conjunction</code>,
<code class="sourceCode cpp">add_trailing_requires_clause_disjunction</code><a href="#set_trailing_requires_clause-add_trailing_requires_clause_conjunction-add_trailing_requires_clause_disjunction" 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 set_trailing_requires_clause<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>info add_trailing_requires_clause_conjunction<span class="op">(</span>info, info<span class="op">)</span>;</span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>info add_trailing_requires_clause_disjunction<span class="op">(</span>info, info<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Given the reflection of a template,
<code class="sourceCode cpp">set_trailing_requires_clause</code> returns
a reflection of an identical template but with the
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause replaced by the token sequence given in the second parameter. The
existing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause in the template, if any, is ignored. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb39-2"><a href="#cb39-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">64</span><span class="op">)</span></span>
<span id="cb39-3"><a href="#cb39-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="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f <span class="op">=</span> <span class="op">^^</span>fun;</span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a>  queue_injection<span class="op">(^^{</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">[:</span>\<span class="op">(</span>set_trailing_requires_clause<span class="op">(</span>set_name<span class="op">(</span>declaration_of<span class="op">(</span>f<span class="op">)</span>, <span class="st">&quot;my_fun&quot;</span><span class="op">))</span>,</span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">^^{</span> <span class="kw">sizeof</span><span class="op">(</span>\tokens<span class="op">(</span>template_parameters_of<span class="op">(</span>f<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span> <span class="op">==</span> <span class="dv">128</span> <span class="op">}):]</span>;</span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">})</span>;</span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent code:</span></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a><span class="co">// template &lt;typename T&gt;</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a><span class="co">// requires (sizeof(T) == 128)</span></span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a><span class="co">// void my_fun(const T&amp; value);</span></span></code></pre></div>
</blockquote>
</div>
<p>The functions <code class="sourceCode cpp">add_trailing_requires_clause_conjunction</code>
and <code class="sourceCode cpp">add_trailing_requires_clause_disjunction</code>
compose the given token sequence with the existing
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause. (If no such clause exists, it is assumed to be the expression
<code class="sourceCode cpp"><span class="kw">true</span></code>.) The
<code class="sourceCode cpp">add_trailing_requires_clause_conjunction</code>
metafunction performs a conjunction (logical “and”) between the clause
given in the token sequence and the existing token sequence. The <code class="sourceCode cpp">add_trailing_requires_clause_disjunction</code>
metafunction performs a disjunction (logical “or”) between the clause
given in the token sequence and the existing token sequence.</p>
<p>Calling
<code class="sourceCode cpp">set_trailing_requires_clause</code>, <code class="sourceCode cpp">add_trailing_requires_clause_conjunction</code>,
or <code class="sourceCode cpp">add_trailing_requires_clause_disjunction</code>
against a non-template, as in <code class="sourceCode cpp">set_trailing_requires_clause<span class="op">(^^</span><span class="dt">int</span>, <span class="op">^^{</span><span class="kw">true</span><span class="op">})</span></code>,
fails to evaluate to a constant expression.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="metafunctions-for-iterating-members-of-class-templates"><span class="header-section-number">4</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, <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> 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="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Container <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-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="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>    size_type size<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="future-work"><span class="header-section-number">5</span> Future
Work<a href="#future-work" class="self-link"></a></h1>
<p>Like <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>, this proposal is designed to
grow by accretion. Future revisions will add more primitives that
complement the existing ones and improve the comprehensiveness of the
reflection facility for templates.</p>
<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>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">6</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-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-P3096R3" class="csl-entry" role="doc-biblioentry">
[P3096R3] Adam Lach, Walter Genovese. 2024-09-15. Function Parameter
Reflection in Reflection for C++26. <a href="https://wg21.link/p3096r3"><div class="csl-block">https://wg21.link/p3096r3</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-P3294R1" class="csl-entry" role="doc-biblioentry">
[P3294R1] Barry Revzin, Andrei Alexandrescu, Daveed Vandevoorde.
2024-07-16. Code Injection with Token Sequences. <a href="https://wg21.link/p3294r1"><div class="csl-block">https://wg21.link/p3294r1</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 id="ref-P3420R0" class="csl-entry" role="doc-biblioentry">
[P3420R0] Andrei Alexandrescu, Barry Revzin, Daveed Vandevoorde, Michael
Garland. 2024-10-16. Reflection of Templates. <a href="https://wg21.link/p3420r0"><div class="csl-block">https://wg21.link/p3420r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
