<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-05-22" />
  <title>Generative Extensions for Reflection</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; }
</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">Generative Extensions for
Reflection</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3157R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-05-22</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, SG7<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Andrei Alexandrescu, NVIDIA<br>&lt;<a href="mailto:andrei@nvidia.com" class="email">andrei@nvidia.com</a>&gt;<br>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
      Bryce Lelbach, NVIDIA<br>&lt;<a href="mailto:blelbach@nvidia.com" class="email">blelbach@nvidia.com</a>&gt;<br>
      Michael Garland, NVIDIA<br>&lt;<a href="mailto:garland@nvidia.com" class="email">garland@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="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#function-descriptor-metafunctions" id="toc-function-descriptor-metafunctions"><span class="toc-section-number">2</span> Function Descriptor
Metafunctions<span></span></a>
<ul>
<li><a href="#inject_function" id="toc-inject_function"><span class="toc-section-number">2.1</span>
<code class="sourceCode cpp">inject_function</code><span></span></a></li>
<li><a href="#declare_function" id="toc-declare_function"><span class="toc-section-number">2.2</span>
<code class="sourceCode cpp">declare_function</code><span></span></a></li>
<li><a href="#set_name" id="toc-set_name"><span class="toc-section-number">2.3</span>
<code class="sourceCode cpp">set_name</code><span></span></a></li>
<li><a href="#set_qualified_name" id="toc-set_qualified_name"><span class="toc-section-number">2.4</span>
<code class="sourceCode cpp">set_qualified_name</code><span></span></a></li>
<li><a href="#access-set_access" id="toc-access-set_access"><span class="toc-section-number">2.5</span>
<code class="sourceCode cpp">access</code>,
<code class="sourceCode cpp">set_access</code><span></span></a></li>
<li><a href="#ref_qualifier-set_ref_qualifier" id="toc-ref_qualifier-set_ref_qualifier"><span class="toc-section-number">2.6</span>
<code class="sourceCode cpp">ref_qualifier</code>,
<code class="sourceCode cpp">set_ref_qualifier</code><span></span></a></li>
<li><a href="#is_static-set_static-is_virtual-set_virtual-is_override-set_override-is_final-set_final-is_consteval-set_consteval-is_constexpr-set_constexpr-is_explicit-set_explicit-is_inline-set_inline-is_pure-set_pure-is_deleted-set_deleted-is_default-set_default" id="toc-is_static-set_static-is_virtual-set_virtual-is_override-set_override-is_final-set_final-is_consteval-set_consteval-is_constexpr-set_constexpr-is_explicit-set_explicit-is_inline-set_inline-is_pure-set_pure-is_deleted-set_deleted-is_default-set_default"><span class="toc-section-number">2.7</span>
<code class="sourceCode cpp">is_static</code>,
<code class="sourceCode cpp">set_static</code>,
<code class="sourceCode cpp">is_virtual</code>,
<code class="sourceCode cpp">set_virtual</code>,
<code class="sourceCode cpp">is_override</code>,
<code class="sourceCode cpp">set_override</code>,
<code class="sourceCode cpp">is_final</code>,
<code class="sourceCode cpp">set_final</code>,
<code class="sourceCode cpp">is_consteval</code>,
<code class="sourceCode cpp">set_consteval</code>,
<code class="sourceCode cpp">is_constexpr</code>,
<code class="sourceCode cpp">set_constexpr</code>,
<code class="sourceCode cpp">is_explicit</code>,
<code class="sourceCode cpp">set_explicit</code>,
<code class="sourceCode cpp">is_inline</code>,
<code class="sourceCode cpp">set_inline</code>,
<code class="sourceCode cpp">is_pure</code>
<code class="sourceCode cpp">set_pure</code>,
<code class="sourceCode cpp">is_deleted</code>,
<code class="sourceCode cpp">set_deleted</code>,
<code class="sourceCode cpp">is_default</code>,
<code class="sourceCode cpp">set_default</code><span></span></a></li>
</ul></li>
<li><a href="#proxy-classes-and-instrumented-classes" id="toc-proxy-classes-and-instrumented-classes"><span class="toc-section-number">3</span> Proxy Classes and Instrumented
Classes<span></span></a></li>
<li><a href="#embedded-domain-specific-languages" id="toc-embedded-domain-specific-languages"><span class="toc-section-number">4</span> Embedded Domain Specific
Languages<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">1</span>
Introduction<a href="#introduction" class="self-link"></a></h1>
<p>Since the recent implementation of the reflection facilities proposed
in <span class="citation" data-cites="P2996R3">[<a href="https://wg21.link/p2996r3" role="doc-biblioref">P2996R3</a>]</span>, we explored how the proposal
would help fundamental challenges we are facing today. We believe
reflection has great potential to solve important problems that we and
the C++ community at large both face, and that a few specific
enhancements on top of P2996 would help realize that potential. Based on
our initial experience, this document (and its companions <span class="citation" data-cites="P3294R0">[<a href="https://wg21.link/p3294r0" role="doc-biblioref">P3294R0</a>]</span> and <span class="citation" data-cites="P3289R0">[<a href="https://wg21.link/p3289r0" role="doc-biblioref">P3289R0</a>]</span>) builds function synthesis
capability on the foundation of P2996 that we think will help C++
reflection have a stronger and more timely positive impact on the state
of affairs in the C++ language. We anticipate that C++ reflection, if
sufficiently powerful, could dramatically reduce costs of developing and
maintaining C++ code while at the same time improving code size,
readability, compilation time, and execution speed. We expect to have a
proof-of-concept implementation of our design available shortly.</p>
<p>C++ code from a variety of domains naturally leads to boilerplate.
Proxy classes are commonplace, whether to interface different codebases
or as an organic part of design. The guideline <a href="https://en.wikipedia.org/wiki/Composition_over_inheritance">“prefer
composition over inheritance”</a> leads to many forward-to-member
functions. Other useful <a href="https://en.wikipedia.org/wiki/Design_Patterns">design patterns</a>
such as Visitor, Observer, Decorator, Adapter, and <a href="https://www.slideshare.net/tcab22/null-object-design-pattern-presentation">Null
Object</a> require de facto maintenance of parallel class hierarchies
and/or parallel function declarations (plus in many cases mechanical
definitions). Foreign language/API interfaces typically consist of large
swaths of code following repetitive patterns. Implementing
high-performance parallel algorithms typically requires specialized
patterns for a variety of size, stride, and type combinations. All of
these instances feature enough irregularities and variations to make
existing template metaprogramming techniques difficult to deploy, and if
deployed, difficult to understand and maintain.</p>
<p>The rest of this paper is structured as follows. Section “Function
Descriptor Metafunctions” proposes a design for manipulating the
reflection of functions, with an emphasis on generation capabilities.
These capabilities—in conjunction with P2996, P3294, P3289, and <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3096r0.pdf">P3096</a>—provide
a mechanism for querying and synthesizing function definitions in a
powerful and flexible manner that makes reflection-based code simple and
intuitive. Section “Proxy Classes and Instrumented Classes” defines
essential use cases of reflection metaprogramming that motivate and
inform the design and implementation of function synthesis. We consider
strong use cases essential to setting goals for reflective
metaprogramming. To be compelling, use cases must demonstrate
meaningful, desirable functionality (albeit in a simplistic,
proof-of-concept style) that is impossible or prohibitively difficult
within the current C++. Section “Embedded Domain Specific Languages” is
even more forward-looking, setting up the long-range trajectory of our
proposal.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="function-descriptor-metafunctions"><span class="header-section-number">2</span> Function Descriptor
Metafunctions<a href="#function-descriptor-metafunctions" class="self-link"></a></h1>
<p>This proposal is a companion to <a href="https://brevzin.github.io/cpp_proposals/3294_code_injection/p3294r0.html">P3294</a>
and meant to complement and work in conjunction with it. P3294 uses
<code class="sourceCode cpp">decl_of<span class="op">(</span>info<span class="op">)</span></code>
(where <code class="sourceCode cpp">info</code> is the reflection of a
function) as a key mechanism to expand reflections of existing functions
into declarations, to which user code can subsequently attach
definitions. This proposal focuses on creating and manipulating
reflections of functions, to be later used with <code class="sourceCode cpp">decl_of<span class="op">(</span>info<span class="op">)</span></code>
as per P3294.</p>
<p>Given an existing function, we propose a number of <em>function
descriptor metafunctions</em> that allow querying all aspects of it.
Similar functions can be used to synthesize new functions.</p>
<p>Given a function declaration <code class="sourceCode cpp">f</code>,
its reflection
<code class="sourceCode cpp"><span class="op">^</span>f</code> is a
mutable object that can be subsequently modified. That does not affect
the initial declaration in any way, but can be used to generate new
declarations and definitions. Using
<code class="sourceCode cpp"><span class="op">^</span>f</code> once
again returns a new copy of its reflection, so there is no loss of
information.</p>
<p>The definitions of the proposed metafunctions are shown below. A
subsection will be dedicated to describing each.</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// inject a function definition given its reflection and body</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> inject_function<span class="op">(</span>info, info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// inject a function definition given its reflection, parameter prefix, and body</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> inject_function<span class="op">(</span>info, string_view, info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// create a new function declaration from tokens and return its reflection</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> declare_function<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> info;</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// present in P2996, applies to functions as well</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// change the name of the function</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_name<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// present in P2996, applies to functions as well</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> qualified_name_of<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// change the qualfied name of the function</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_qualified_name<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get and set `static`</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_static<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_static<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get and set `static`</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_virtual<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_virtual<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get and set `static`</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_override<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_override<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get and set `static`</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_final<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_final<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// &quot;&quot;, &quot;public&quot;, &quot;protected&quot;, &quot;private&quot;, or &quot;friend&quot;</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> access<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_access<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// &quot;&quot;, &quot;&amp;&quot;, or &quot;&amp;&amp;&quot;</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> ref_qualifier<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> string_view;</span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_ref_qualifier<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>  <span class="co">// all user-defined attributes</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> attributes<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>string<span class="op">&gt;</span>;</span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> add_attribute<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> remove_attribute<span class="op">(</span>info, string_view<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// true if the function is consteval</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_consteval<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_consteval<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>  <span class="co">// true if the function is constexpr</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_constexpr<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_constexpr<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>  <span class="co">// true if explicit ctor or conversion operator</span></span>
<span id="cb1-45"><a href="#cb1-45" 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="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_explicit<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>  <span class="co">// true if the function is inline</span></span>
<span id="cb1-48"><a href="#cb1-48" 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="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_inline<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>  <span class="co">// indicates whether the function is pure virtual</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_pure<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_pure<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>  <span class="co">// indicates whether the function is deleted</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_deleted<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_deleted<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>  <span class="co">// indicates whether the function is a default constructor or operator</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> is_default<span class="op">(</span>info<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="kw">auto</span> set_default<span class="op">(</span>info, <span class="dt">bool</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h2 data-number="2.1" id="inject_function"><span class="header-section-number">2.1</span>
<code class="sourceCode cpp">inject_function</code><a href="#inject_function" class="self-link"></a></h2>
<p>These metafunctions inject a new function definition given the
reflection of a function declaration and tokens for the function body.
The optional <code class="sourceCode cpp">string_view</code> parameter
provides a prefix for function parameters; by default, parameters are
<code class="sourceCode cpp">_0</code>,
<code class="sourceCode cpp">_1</code>,
<code class="sourceCode cpp">_2</code> etc. For example:</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="dt">double</span> fun<span class="op">(</span><span class="dt">double</span>, std<span class="op">::</span>string<span class="op">)</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span>  <span class="co">// see P3289R0, &quot;Consteval Blocks&quot;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// for @tokens see P3294, &quot;Code Injection with Token Sequences&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  inject_function<span class="op">(^</span>fun, <span class="op">@</span>tokens<span class="op">{</span> <span class="cf">return</span> _0 <span class="op">+</span> _1<span class="op">.</span>size<span class="op">()</span>; <span class="op">})</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent hand-written definition:</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="co">// double fun(double _1, std::string _2) { return _1 + _2.size(); }</span></span></code></pre></div>
</blockquote>
</div>
<p>If a prefix is specified, it will replace the leading underscore in
parameter names. For example:</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="dt">double</span> fun<span class="op">(</span><span class="dt">double</span>, std<span class="op">::</span>string<span class="op">)</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  inject_function<span class="op">(^</span>fun, <span class="st">&quot;p&quot;</span>, <span class="op">@</span>tokens<span class="op">{</span> <span class="cf">return</span> p0 <span class="op">+</span> p1<span class="op">.</span>size<span class="op">()</span>; <span class="op">})</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h2 data-number="2.2" id="declare_function"><span class="header-section-number">2.2</span>
<code class="sourceCode cpp">declare_function</code><a href="#declare_function" class="self-link"></a></h2>
<p>This metafunction creates a new function declaration from tokens and
returns the reflection of that declaration. For example:</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">consteval</span> <span class="op">{</span>  <span class="co">// see P3289R0, &quot;Consteval Blocks&quot;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> r <span class="op">=</span> declare_function<span class="op">(@</span>tokens<span class="op">{</span> <span class="dt">void</span> my_function<span class="op">(</span><span class="dt">double</span><span class="op">)</span>; <span class="op">})</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// see P3294, &quot;Code Injection with Token Sequences&quot;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  inject_function<span class="op">(</span>r, <span class="op">@</span>tokens<span class="op">{</span> std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;Hello, world!</span><span class="sc">\n</span><span class="st">&quot;</span>; <span class="op">})</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The code above simply defines (albeit in an alembicated manner) the
following function:</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> my_function<span class="op">(</span><span class="dt">double</span> _1<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;Hello, world!</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>The advantage of using reflection is, of course, when there’s a need
to manipulate some elements of the function’s definition prior to
injection.</p>
<h2 data-number="2.3" id="set_name"><span class="header-section-number">2.3</span>
<code class="sourceCode cpp">set_name</code><a href="#set_name" class="self-link"></a></h2>
<p>This metafunction allows setting the name of a function’s reflection,
allowing user code to generate functions identical or similar in
signature with existing functions. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^</span>f;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  set_name<span class="op">(</span>r, <span class="st">&quot;g&quot;</span><span class="op">)</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  inject_function<span class="op">(</span>r, <span class="op">@</span>tokens<span class="op">{</span> <span class="cf">return</span> f<span class="op">()</span>; <span class="op">})</span>;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent to:</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="co">// int g() noexcept { return f(); }</span></span></code></pre></div>
</blockquote>
</div>
<p>Note how the signature including the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
attribute gets carried from <code class="sourceCode cpp">f</code> to
<code class="sourceCode cpp">g</code>.</p>
<h2 data-number="2.4" id="set_qualified_name"><span class="header-section-number">2.4</span>
<code class="sourceCode cpp">set_qualified_name</code><a href="#set_qualified_name" class="self-link"></a></h2>
<p>Works similarly to <code class="sourceCode cpp">set_name</code>, but
accepts a fully qualified name, which allows creating declarations and
definitions outside the current namespace. This works per the existing
language rules, i.e. the current scope must enclose the scope in which
the function is injcted.</p>
<h2 data-number="2.5" id="access-set_access"><span class="header-section-number">2.5</span>
<code class="sourceCode cpp">access</code>,
<code class="sourceCode cpp">set_access</code><a href="#access-set_access" class="self-link"></a></h2>
<p>The <code class="sourceCode cpp">access</code> metafunction returns
the access level of the given reflection as one of the empty <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>,
<code class="sourceCode cpp"><span class="st">&quot;public&quot;</span></code>,
<code class="sourceCode cpp"><span class="st">&quot;protected&quot;</span></code>,
<code class="sourceCode cpp"><span class="st">&quot;private&quot;</span></code>,
or <code class="sourceCode cpp"><span class="st">&quot;friend&quot;</span></code>.
If not applicable (e.g. top-level declaration), the empty
<code class="sourceCode cpp">string_view</code> is returned. The setter
metafunction <code class="sourceCode cpp">set_access</code> must be
called with a <code class="sourceCode cpp">string_view</code> in the
same set and forces the access level for the given reflection
object.</p>
<h2 data-number="2.6" id="ref_qualifier-set_ref_qualifier"><span class="header-section-number">2.6</span>
<code class="sourceCode cpp">ref_qualifier</code>,
<code class="sourceCode cpp">set_ref_qualifier</code><a href="#ref_qualifier-set_ref_qualifier" class="self-link"></a></h2>
<p>The <code class="sourceCode cpp">ref_qualifier</code> metafunction
returns the access level of the given reflection as one of the empty
<code class="sourceCode cpp">std<span class="op">::</span>string_view</code>,
<code class="sourceCode cpp"><span class="st">&quot;&amp;&quot;</span></code>,
or <code class="sourceCode cpp"><span class="st">&quot;&amp;&amp;&quot;</span></code>.
If not applicable (e.g. top-level declaration), the empty
<code class="sourceCode cpp">string_view</code> is returned. The setter
metafunction <code class="sourceCode cpp">set_ref_qualifier</code> must
be called with a <code class="sourceCode cpp">string_view</code> in the
same set and forces the access level for the given reflection
object.</p>
<h2 data-number="2.7" id="is_static-set_static-is_virtual-set_virtual-is_override-set_override-is_final-set_final-is_consteval-set_consteval-is_constexpr-set_constexpr-is_explicit-set_explicit-is_inline-set_inline-is_pure-set_pure-is_deleted-set_deleted-is_default-set_default"><span class="header-section-number">2.7</span>
<code class="sourceCode cpp">is_static</code>,
<code class="sourceCode cpp">set_static</code>,
<code class="sourceCode cpp">is_virtual</code>,
<code class="sourceCode cpp">set_virtual</code>,
<code class="sourceCode cpp">is_override</code>,
<code class="sourceCode cpp">set_override</code>,
<code class="sourceCode cpp">is_final</code>,
<code class="sourceCode cpp">set_final</code>,
<code class="sourceCode cpp">is_consteval</code>,
<code class="sourceCode cpp">set_consteval</code>,
<code class="sourceCode cpp">is_constexpr</code>,
<code class="sourceCode cpp">set_constexpr</code>,
<code class="sourceCode cpp">is_explicit</code>,
<code class="sourceCode cpp">set_explicit</code>,
<code class="sourceCode cpp">is_inline</code>,
<code class="sourceCode cpp">set_inline</code>,
<code class="sourceCode cpp">is_pure</code>
<code class="sourceCode cpp">set_pure</code>,
<code class="sourceCode cpp">is_deleted</code>,
<code class="sourceCode cpp">set_deleted</code>,
<code class="sourceCode cpp">is_default</code>,
<code class="sourceCode cpp">set_default</code><a href="#is_static-set_static-is_virtual-set_virtual-is_override-set_override-is_final-set_final-is_consteval-set_consteval-is_constexpr-set_constexpr-is_explicit-set_explicit-is_inline-set_inline-is_pure-set_pure-is_deleted-set_deleted-is_default-set_default" class="self-link"></a></h2>
<p>These get/set metafunctions retrieve and set the respective aspects
of the given reflection. Example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="dt">int</span> f<span class="op">()</span>;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^</span>f;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  set_name<span class="op">(</span>r, <span class="st">&quot;g&quot;</span><span class="op">)</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>is_static<span class="op">(</span>r<span class="op">))</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  set_static<span class="op">(</span>r, <span class="kw">false</span><span class="op">)</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  inject_function<span class="op">(</span>r, <span class="op">@</span>tokens<span class="op">{</span> <span class="cf">return</span> f<span class="op">()</span>; <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="co">// Equivalent to:</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="co">// int g() { return f(); }</span></span></code></pre></div>
</blockquote>
</div>
<p>Calling <code class="sourceCode cpp">is_xxx</code> on reflection
objects where they are not applicable (e.g. reflections of data or
expressions) returns
<code class="sourceCode cpp"><span class="kw">false</span></code>.
Calling <code class="sourceCode cpp">set_xxx</code> where it isn’t
applicable results in a compile-time error.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proxy-classes-and-instrumented-classes"><span class="header-section-number">3</span> Proxy Classes and Instrumented
Classes<a href="#proxy-classes-and-instrumented-classes" class="self-link"></a></h1>
<p>Consider the task of defining interface classes for API integration,
including foreign language bindings. Such a task involves creating
classes with member functions that perform the same basic duties—such as
validating arguments, converting data formats, and adjusting reference
and pointer notations—before calling similarly named functions in
another class, sometimes followed by analogous postprocessing of the
results.</p>
<p>Such use cases generalize to creating <em>instrumented classes:</em>
developing direct substitutes for existing classes while embedding
specific hooks (such as tracing, logging, counters, argument
verification, result validation, and naming convention changes) into
some or all member functions. Successfully reflecting on and
reconstructing a class in this manner serves as a critical test of a
language’s reflective metaprogramming capabilities, similar to how the
identity function evaluates a language’s functional programming
features.</p>
<p>As a simple example, consider the Null Object design pattern, a safe
alternative to the dreaded null pointer. Given an interface
<code class="sourceCode cpp">T</code> that defines several pure virtual
member functions, <code class="sourceCode cpp">null_object<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
would yield an implementation of <code class="sourceCode cpp">T</code>
that defines all of its virtuals to either throw an exception or return
a default-constructed value of their result type. Defining a null object
for a given interface is tediously simple, yet maintaining it is an
exercise in frustration and a source of aggravation. Reflection should
allow defining <code class="sourceCode cpp">null_object</code> for any
type and behavior with ease.</p>
<p>A more involved example would be defining a class such as <code class="sourceCode cpp">instrumented_vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>
that wraps an <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>
and adds instrumentation (e.g., bounds checking) to some or all of its
methods. The key here is to make
<code class="sourceCode cpp">instrumented_vector</code> a drop-in
replacement for
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
without incurring the cost of copying all of its member function
declarations. Needless to say, defining such a proxy class by hand is
quite discouraging, and reflective metaprogramming should offer a
complete and flexible solution.</p>
<p>The ability to create proxy classes would also put to rest the
unpleasantness of following the adage “prefer composition over
inheritance” in C++. As mentioned, in many composition situations,
numerous forward-to-member functions must be written and maintained;
automating these stubs would make it much easier to follow the guideline
therefore improving code quality without adding to its bulk. Making
valuable programming idioms more accessible has repeatedly proven to be
a wise investment.</p>
<p>An important part of defining instrumented classes is querying all
members of an existing class (static and nonstatic data member, regular
and special member functions,
<code class="sourceCode cpp"><span class="kw">enum</span></code>
declarations, friend declarations…) and generating similar definitions
within the context of a new class definition. The
<code class="sourceCode cpp">define_class</code> primitive in P2996R1 is
the fundamental mechanism for implementing a proxy class, and although
it currently does not support adding member functions, it alludes to
such a possibility in section 4.4.12: “For now, only non-static data
member reflections are supported (via
<code class="sourceCode cpp">nsdm_description</code>) but the API takes
in a range of <code class="sourceCode cpp">info</code> anticipating
expanding this in the near future.” We believe the ability to define
full-fledged classes is a quintessential, defining feature of a
reflective metaprogramming feature for C++. Here are a few key
components needed:</p>
<ul>
<li>Signatures of all functions must be accessible for introspection,
and primitives for accessing full information of a function’s signature
must be defined.</li>
<li>Synthesis of function signatures must be possible, e.g. a library
may need to build a signature from scratch, or from a similar signature
(e.g., create a new signature from a given signature by adding or
removing an attribute).</li>
<li>There must be an ability to attach code to the reflection of a
function signature; for example, a library may want to define a proxy
class that inserts logging for each function’s arguments and result. The
most fit candidate for attaching such functionality to reflection is a
generic function literal that is a friend of the generated class.</li>
<li>Finally, <code class="sourceCode cpp">define_class</code> would
accept synthesized member functions in addition to (and in a manner
similar to) <code class="sourceCode cpp">nsdm_description</code>.
Implementing member function synthesis should be feasible following a
design similar to <code class="sourceCode cpp">nsdm_description</code>—a
function <code class="sourceCode cpp">memfun_description</code> would
take an <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
(either synthesized or coming from the introspection of another member
function) a <code class="sourceCode cpp">memfun_options</code> object
that has, among other members, a lambda function to serve as the body of
the budding member function. The result of the call to
<code class="sourceCode cpp">memfun_description</code> would be passed
to <code class="sourceCode cpp">define_class</code>.</li>
</ul>
<p>One aspect of function synthesis is <em>code cloning</em>—the ability
to compile a reflected function template under different constraints
(e.g. different concepts and attributes). As an example, this aspect is
important to CUDA C++ libraries that need to add
<code class="sourceCode cpp">__device__</code> attributes to all methods
of replicas of standard types—such as
<code class="sourceCode cpp">std<span class="op">::</span>pair</code>,
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>optional</code>—and
subsequently compile the resulting code for use on the device. The
alternative—copying and pasting code with minute changes—is a
proverbially bad practice.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="embedded-domain-specific-languages"><span class="header-section-number">4</span> Embedded Domain Specific
Languages<a href="#embedded-domain-specific-languages" class="self-link"></a></h1>
<p>Python’s many frameworks (e.g., PyTorch and TensorFlow, among many
others) have demonstrated the importance of Embedded Domain Specific
Languages (EDSLs) in today’s world, especially for AI applications. A
reflective metaprogramming facility for C++ is expected to make it
possible to express EDSLs much better than C++ currently allows.</p>
<p>EDSL-related features would place emphasis on the <em>generative</em>
aspect of reflective metaprogramming. For example, an aspirational EDSL
way of doing things for GPU-accelerated code could take in an algorithm
written concisely in a high-level array language and generate during
compilation specialized CUDA C++ code implementing the algorithm with
the same efficiency as if this low-level code were written by hand.</p>
<p>The utility of EDSLs is, of course, much broader. An EDSL essentially
allows the programmer to author a high-level expressive specification
adapted to the problem domain (function differentiation, relational
databases, networking protocols, regular expressions, EBNF grammars,
document formatting…), to then generate C++ code from it. The approach
is advantageous if writing the same C++ code by hand would be a much
more costly proposition. Domain-specific libraries can provide the
desired level of abstraction, but struggle to optimize execution in ways
that cross abstraction boundaries. EDSL-style approaches can provide
this missing capability.</p>
<p>The <em>amplification</em> aspect is an important desired outcome:
the ultimate goal of a reflection facility is to allow new code to build
on existing code in a combinatorial manner, to the effect of automating
tedious and repetitive aspects of the coding process. To wit, the
examples in P2996R1 and those shown above invariably would take more
code to implement without reflection. Allowing generation of meaningful
code from specifications encoded in EDSLs would be the ultimate goal of
a reflection engine.</p>
<p>EDSL processors (toolchains that act as embedded interpreters or
compilers) play a pivotal role in the EDSL ecosystem. Though an EDSL
processor itself can be seen as an ordinary EDSL that takes in a grammar
specification and produces a language translator, once the EDSL
toolchain is available it can be used to process any other EDSL, either
during compilation or at runtime. Therefore, an EDSL toolchain defined
as an EDSL is a foundational “seed EDSL” that we consider a crucial
milestone of a reflection metaprogramming engine.</p>
<p>For such a task to be feasible, the <em>synthesis</em> aspect of the
proposal is important—building on the
<code class="sourceCode cpp">memfun_description</code> function
discussed above, we envision adding primitives that synthesize types,
functions, and templates in addition to the
<code class="sourceCode cpp">define_class</code>/<code class="sourceCode cpp">nsdm_description</code>
facility that allows definition of classes with direct data members.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-P2996R3" class="csl-entry" role="doc-biblioentry">
[P2996R3] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, and Dan Katz. 2024-05-22. Reflection
for C++26. <a href="https://wg21.link/p2996r3"><div class="csl-block">https://wg21.link/p2996r3</div></a>
</div>
<div id="ref-P3289R0" class="csl-entry" role="doc-biblioentry">
[P3289R0] Wyatt Childers, Barry Revzin, and Daveed Vandevoorde.
2024-05-18.
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
blocks. <a href="https://wg21.link/p3289r0"><div class="csl-block">https://wg21.link/p3289r0</div></a>
</div>
<div id="ref-P3294R0" class="csl-entry" role="doc-biblioentry">
[P3294R0] Andrei Alexandrescu, Barry Revzin, and Daveed Vandevoorde.
2024-05-22. Code Injection with Token Sequences. <a href="https://wg21.link/p3294r0"><div class="csl-block">https://wg21.link/p3294r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
