<!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>Code Injection with Token Sequences</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">Code Injection with Token
Sequences</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3294R0</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>
      SG7, EWG<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>
      Daveed Vandevoorde<br>&lt;<a href="mailto:daveed@edg.com" class="email">daveed@edg.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#a-comparison-of-injection-models" id="toc-a-comparison-of-injection-models"><span class="toc-section-number">2</span> A Comparison of Injection
Models<span></span></a>
<ul>
<li><a href="#the-spec-api" id="toc-the-spec-api"><span class="toc-section-number">2.1</span> The Spec API<span></span></a></li>
<li><a href="#the-codereckons-api" id="toc-the-codereckons-api"><span class="toc-section-number">2.2</span> The CodeReckons
API<span></span></a></li>
<li><a href="#string-injection" id="toc-string-injection"><span class="toc-section-number">2.3</span> String
Injection<span></span></a></li>
<li><a href="#fragments" id="toc-fragments"><span class="toc-section-number">2.4</span> Fragments<span></span></a></li>
</ul></li>
<li><a href="#token-sequences" id="toc-token-sequences"><span class="toc-section-number">3</span> Token Sequences<span></span></a>
<ul>
<li><a href="#tokens-literal" id="toc-tokens-literal"><span class="toc-section-number">3.1</span>
<code class="sourceCode cpp"><span class="op">@</span>tokens</code>
literal<span></span></a></li>
<li><a href="#quoting-into-a-token-sequence" id="toc-quoting-into-a-token-sequence"><span class="toc-section-number">3.2</span> Quoting into a token
sequence<span></span></a></li>
<li><a href="#examples" id="toc-examples"><span class="toc-section-number">3.3</span> Examples<span></span></a></li>
<li><a href="#logging-vector-cloning-a-type" id="toc-logging-vector-cloning-a-type"><span class="toc-section-number">3.4</span> Logging Vector: Cloning a
Type<span></span></a></li>
<li><a href="#logging-vector-ii-cloning-with-modifications" id="toc-logging-vector-ii-cloning-with-modifications"><span class="toc-section-number">3.5</span> Logging Vector II: Cloning with
Modifications<span></span></a></li>
</ul></li>
<li><a href="#hygienic-macros" id="toc-hygienic-macros"><span class="toc-section-number">4</span> Hygienic Macros<span></span></a>
<ul>
<li><a href="#forwarding" id="toc-forwarding"><span class="toc-section-number">4.1</span> Forwarding<span></span></a></li>
<li><a href="#assertion" id="toc-assertion"><span class="toc-section-number">4.2</span> Assertion<span></span></a></li>
<li><a href="#string-interpolation" id="toc-string-interpolation"><span class="toc-section-number">4.3</span> String
Interpolation<span></span></a></li>
<li><a href="#control-flow-operator" id="toc-control-flow-operator"><span class="toc-section-number">4.4</span> Control Flow
Operator<span></span></a></li>
<li><a href="#alternate-syntax" id="toc-alternate-syntax"><span class="toc-section-number">4.5</span> Alternate
Syntax<span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">5</span> Proposal<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="introduction"><span class="header-section-number">1</span>
Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This paper is proposing augmenting <span class="citation" data-cites="P2996R3">[<a href="https://wg21.link/p2996r3" role="doc-biblioref">P2996R3</a>]</span> to add code injection in the
form of token sequences.</p>
<p>We consider the motivation for this feature to some degree pretty
obvious, so we will not repeat it here, since there are plenty of other
things to cover here. Instead we encourage readers to read some other
papers on the topic (<span class="citation" data-cites="P0707R4">[<a href="https://wg21.link/p0707r4" role="doc-biblioref">P0707R4</a>]</span>, <span class="citation" data-cites="P0712R0">[<a href="https://wg21.link/p0712r0" role="doc-biblioref">P0712R0</a>]</span>, <span class="citation" data-cites="P1717R0">[<a href="https://wg21.link/p1717r0" role="doc-biblioref">P1717R0</a>]</span>, <span class="citation" data-cites="P2237R0">[<a href="https://wg21.link/p2237r0" role="doc-biblioref">P2237R0</a>]</span>).</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="a-comparison-of-injection-models"><span class="header-section-number">2</span> A Comparison of Injection
Models<a href="#a-comparison-of-injection-models" class="self-link"></a></h1>
<p>There are a lot of things that make code injection in C++ difficult,
and the most important problem to solve first is: what will the actual
injection mechanism look like? Not its syntax specifically, but what is
the shape of the API that we want to expose to users? We hope in this
section to do a thorough job of comparing the various semantic models
we’re aware of to help explain why we came to the conclusion that we
came to.</p>
<p>If you’re not interested in this journey, you can simply skip to the
<a href="#token-sequences">next section</a>.</p>
<p>Here, we will look at a few interesting examples for injection and
how different models can implement them. The examples aren’t necessarily
intended to be the most compelling examples that exist in the wild.
Instead, they’re hopefully representative enough to cover a wide class
of problems. They are:</p>
<ol type="1">
<li>Implementing the storage for <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code></li>
<li>Implementing <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code>
without resorting to class template specialization</li>
<li>Implementing properties (i.e. given a name like <code class="sourceCode cpp"><span class="st">&quot;author&quot;</span></code>
and a type like
<code class="sourceCode cpp">std<span class="op">::</span>string</code>,
emit a member <code class="sourceCode cpp">std<span class="op">::</span>string m_author</code>,
a getter
<code class="sourceCode cpp">get_author<span class="op">()</span></code>
which returns a <code class="sourceCode cpp">std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span></code>
to that member, and a setter
<code class="sourceCode cpp">set_author<span class="op">()</span></code>
which takes a new value of type <code class="sourceCode cpp">std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span></code>
and assigns the member).</li>
<li>Implement postfix increment in terms of prefix increment.</li>
</ol>
<h2 data-number="2.1" id="the-spec-api"><span class="header-section-number">2.1</span> The Spec API<a href="#the-spec-api" class="self-link"></a></h2>
<p>In P2996, the injection API is based on a function <code class="sourceCode cpp">define_class<span class="op">()</span></code>
which takes a range of <code class="sourceCode cpp">spec</code> objects.
But <code class="sourceCode cpp">define_class<span class="op">()</span></code> is
a really clunky API, because invoking it is an expression - but we want
to do it in contexts that want a declaration. So a simple example of
injecting a single member
<code class="sourceCode cpp"><span class="dt">int</span></code> named
<code class="sourceCode cpp">x</code> is:</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">struct</span> C;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_type<span class="op">(</span>define_class<span class="op">(^</span>C,</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span>data_member_spec<span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;x&quot;</span>, <span class="op">.</span>type<span class="op">=^</span><span class="dt">int</span><span class="op">}})))</span>;</span></code></pre></div>
</blockquote>
</div>
<p>We are already separately proposing
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
blocks <span class="citation" data-cites="P3289R0">[<a href="https://wg21.link/p3289r0" role="doc-biblioref">P3289R0</a>]</span> and we would like to inject
each spec more directly, without having to complete
<code class="sourceCode cpp">C</code> in one ago. As in:</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> C <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>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        inject<span class="op">(</span>data_member_spec<span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;x&quot;</span>, <span class="op">.</span>type<span class="op">=^</span><span class="dt">int</span><span class="op">})</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Here, <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>inject</code>
is a metafunction that takes a spec, which gets injected into the
context begin by the
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
block that our evaluation started in as a side-effect.</p>
<p>We already think of this as an improvement. But let’s go through
several use-cases to expand the API and see how well it holds up.</p>
<h3 data-number="2.1.1" id="stdtuple"><span class="header-section-number">2.1.1</span>
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdtuple" class="self-link"></a></h3>
<p>The tuple use-case was already supported by P2996 directly with <code class="sourceCode cpp">define_class<span class="op">()</span></code>
(even as we think itd be better as a member pack), but it’s worth just
showing what it looks like with a direct injection API instead:</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">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Tuple <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</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>array types<span class="op">{^</span>Ts<span class="op">...}</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> types<span class="op">.</span>size<span class="op">()</span> ;<span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(</span>data_member_spec<span class="op">{.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;_{}&quot;</span>, i<span class="op">)</span>,</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>                                    <span class="op">.</span>type<span class="op">=</span>types<span class="op">[</span>i<span class="op">]})</span>;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.1.2" id="stdenable_if"><span class="header-section-number">2.1.2</span> <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code><a href="#stdenable_if" class="self-link"></a></h3>
<p>Now, <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code> has
already been obsolete technology since C++20. So implementing it,
specifically, is not entirely a motivating example. However, the general
idea of <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code> as
<em>conditionally</em> having a member type is a problem that has no
good solution in C++ today.</p>
<p>The spec API along with injection does allow for a clean solution
here. We would just need to add an
<code class="sourceCode cpp">alias_spec</code> construct to get the job
done:</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="dt">bool</span> B, <span class="kw">class</span> T<span class="op">=</span><span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> enable_if <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>B<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(</span>alias_spec<span class="op">{.</span>name<span class="op">=</span><span class="st">&quot;type&quot;</span>, <span class="op">.</span>type<span class="op">=^</span>T<span class="op">})</span>;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>So far so good.</p>
<h3 data-number="2.1.3" id="properties"><span class="header-section-number">2.1.3</span> Properties<a href="#properties" class="self-link"></a></h3>
<p>Now is when the spec API really goes off the rails. We’ve shown data
members and extended it to member aliases. But how do we support member
functions?</p>
<p>We want to be able to add a
<code class="sourceCode cpp">property</code> with a given
<code class="sourceCode cpp">name</code> and
<code class="sourceCode cpp">type</code> that adds a member of that type
and a getter and setter for it. For instance, we want this 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="kw">struct</span> Book <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(</span><span class="st">&quot;author&quot;</span>, <span class="op">^</span>std<span class="op">::</span>string<span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(</span><span class="st">&quot;title&quot;</span>, <span class="op">^</span>std<span class="op">::</span>string<span class="op">)</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>to emit a class with two members
(<code class="sourceCode cpp">m_author</code> and
<code class="sourceCode cpp">m_title</code>), two getters that each
return a <code class="sourceCode cpp">std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span></code>
(<code class="sourceCode cpp">get_author<span class="op">()</span></code>
and
<code class="sourceCode cpp">get_title<span class="op">()</span></code>)
and two setters that each take a <code class="sourceCode cpp">std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span></code>
(<code class="sourceCode cpp">set_author<span class="op">()</span></code>
and
<code class="sourceCode cpp">set_title<span class="op">()</span></code>).
Fairly basic property.</p>
<p>We start by injecting the member:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>data_member_spec<span class="op">{.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>                            <span class="op">.</span>type<span class="op">=</span>type<span class="op">})</span>;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Now, we need to inject two functions. We’ll need a new kind of
<code class="sourceCode cpp">spec</code> for that case, and then we can
use a lambda for the function body. Let’s start with the getter:</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">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>data_member_spec<span class="op">{.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>                            <span class="op">.</span>type<span class="op">=</span>type<span class="op">})</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=^[](</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> self<span class="op">.</span><span class="co">/* ????? */</span>;</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Okay. Uh. What do we return? For the title property, this needs to be
<code class="sourceCode cpp"><span class="cf">return</span> self<span class="op">.</span>m_title;</code>,
but how do we spell that? We just… can’t. We have our member right there
(the <code class="sourceCode cpp">data_member_spec</code> we’re
injecting), so you might think we could try to capture it:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member <span class="op">=</span> inject<span class="op">(</span>data_member_spec<span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>type<span class="op">=</span>type</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=^[</span>member<span class="op">](</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> self<span class="op">.[:</span>member<span class="op">:]</span>;</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>But that doesn’t work - in order to splice
<code class="sourceCode cpp">member</code>, it needs to be a constant
expression - and it’s not in this context.</p>
<p>Now, the body of the lambda isn’t going to be evaluted in this
constant evaluation, so it’s possible to maybe some up with some
mechanism to pass a context through - such that from the body we
<em>can</em> simply splice <code class="sourceCode cpp">member</code>.
We basically need to come up with a way to defer this instantiation.</p>
<p>For now, let’s try a spelling 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="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member <span class="op">=</span> inject<span class="op">(</span>data_member_spec<span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>type<span class="op">=</span>type</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>member, <span class="op">^[]&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info M<span class="op">&gt;(</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> self<span class="op">.[:</span>M<span class="op">:]</span>;</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>and we can do something similar with the setter:</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">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member <span class="op">=</span> inject<span class="op">(</span>data_member_spec<span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>type<span class="op">=</span>type</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>member, <span class="op">^[]&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info M<span class="op">&gt;(</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> self<span class="op">.[:</span>M<span class="op">:]</span>;</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;set_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>member, <span class="op">^[]&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info M<span class="op">&gt;(</span><span class="kw">auto</span><span class="op">&amp;</span> self, <span class="kw">typename</span> <span class="op">[:</span>type_of<span class="op">(</span>M<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>            self<span class="op">.[:</span>M<span class="op">:]</span> <span class="op">=</span> x;</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Now we run into the next problem: what actual signature is the
compiler going to inject for
<code class="sourceCode cpp">get_author<span class="op">()</span></code>
and
<code class="sourceCode cpp">set_author<span class="op">()</span></code>?
First, we’re introducing this extra non-type template parameter which we
have to know to strip off somehow. Secondly, we’re always taking the
object parameter as a deduced parameter. How does the API know what we
mean by that?</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Book <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// do we mean this</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> get_author<span class="op">(</span><span class="kw">this</span> Book <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>m_author; <span class="op">}</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> set_author<span class="op">(</span><span class="kw">this</span> Book<span class="op">&amp;</span> self, string <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span> self<span class="op">.</span>m_author <span class="op">=</span> x; <span class="op">}</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// or this</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> get_author<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>m_author; <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> set_author<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;</span> self, string <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span> self<span class="op">.</span>m_author <span class="op">=</span> x; <span class="op">}</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>That is: how does the compiler know whether we’re injecting a member
function or a member function template? Our lambda has to be generic
either way. Moreover, even if we actually wanted to inject a function
template, it’s possible that we might want some parameter to be
dependent but <em>not</em> the object parameter.</p>
<p>Well, we could provide another piece of information to
<code class="sourceCode cpp">function_member_spec</code>: the signature
directly:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">using</span> getter_type <span class="op">=</span> <span class="kw">auto</span><span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> T <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb12-2"><a href="#cb12-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">using</span> setter_type <span class="op">=</span> <span class="kw">auto</span><span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;)</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member <span class="op">=</span> inject<span class="op">(</span>data_member_spec<span class="op">{</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>type<span class="op">=</span>type</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>signature<span class="op">=</span>substitute<span class="op">(^</span>getter_type, <span class="op">{^</span>type<span class="op">})</span>,</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>member, <span class="op">^[]&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info M<span class="op">&gt;(</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> self<span class="op">.[:</span>M<span class="op">:]</span>;</span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;set_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>signature<span class="op">=</span>substitute<span class="op">(^</span>setter_type, <span class="op">{^</span>type<span class="op">})</span>,</span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>member, <span class="op">^[]&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info M<span class="op">&gt;(</span><span class="kw">auto</span><span class="op">&amp;</span> self, <span class="kw">typename</span> <span class="op">[:</span>type_of<span class="op">(</span>M<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>            self<span class="op">.[:</span>M<span class="op">:]</span> <span class="op">=</span> x;</span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Which then maybe feels like the correct spelling is actually more
like this, so that we can actually properly infer all the
information:</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">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>string_view name, meta<span class="op">::</span>info type<span class="op">)</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member <span class="op">=</span> inject<span class="op">(</span>data_member_spec<span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;m_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>type<span class="op">=</span>type</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// note that this type is structural</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Context <span class="op">{</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>meta<span class="op">::</span>info type;</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>meta<span class="op">::</span>info member;</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> pctx <span class="op">=</span> Context<span class="op">{</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>      <span class="co">// get the type of the current context that we&#39;re injecting into</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>type<span class="op">=</span>type_of<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>current<span class="op">())</span>,</span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>      <span class="op">.</span>member<span class="op">=</span>member</span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;get_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>context, <span class="op">^[]&lt;</span>Context C<span class="op">&gt;(){</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="op">[](</span><span class="kw">typename</span> <span class="op">[:</span>C<span class="op">.</span>type<span class="op">:]</span> <span class="kw">const</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> self<span class="op">.[:</span>C<span class="op">.</span>member<span class="op">:]</span>;</span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span>;</span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>function_member_spec<span class="op">{</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>name<span class="op">=</span>std<span class="op">::</span>format<span class="op">(</span><span class="st">&quot;set_{}&quot;</span>, name<span class="op">)</span>,</span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>body<span class="op">=</span>defer<span class="op">(</span>context, <span class="op">^[]&lt;</span>Context C<span class="op">&gt;(){</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="op">[](</span><span class="kw">typename</span> <span class="op">[:</span>C<span class="op">.</span>type<span class="op">:]&amp;</span> self, <span class="kw">typename</span> <span class="op">[:</span>type_of<span class="op">(</span>C<span class="op">.</span>member<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>                self<span class="op">.[:</span>C<span class="op">.</span>member<span class="op">:]</span> <span class="op">=</span> x;</span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span>;</span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span></span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>That is, we create a custom context type that we pass in as a
non-type template parameter into a lambda, so that it <em>it</em> can
return a new lambda with all the types and names properly substituted in
when that can actually be made to work.</p>
<p>This solution… might be workable. But it’s already pretty complicated
and the problem we’re trying to solve really isn’t. As a result, we
believe that the spec API is somewhat of a dead end when it comes to
extending injection support.</p>
<h3 data-number="2.1.4" id="disposition"><span class="header-section-number">2.1.4</span> Disposition<a href="#disposition" class="self-link"></a></h3>
<p>It’s hard to view favorably a design for the long-term future of code
injection with which we cannot even figure out how to inject functions.
Even if we could, this design scales poorly with the language: we need a
library for API for many language constructs, and C++ is a language with
a lot of kinds. That makes for a large barrier to entry for
metaprogramming that we would like to avoid.</p>
<p>Nevertheless, the spec API does have one thing going for it: it is
quite simple. At the very least, we think we should extend the spec
model in P2996 in the following ways:</p>
<ul>
<li>extend <code class="sourceCode cpp">data_member_spec</code> to
support all data members (static/constexpr/inline, attributes, access,
and initializer).</li>
<li>add <code class="sourceCode cpp">alias_spec</code> and
<code class="sourceCode cpp">base_class_spec</code></li>
</ul>
<p>These are the simple cases, and we can get a lot done with the simple
cases, even without a full solution.</p>
<h2 data-number="2.2" id="the-codereckons-api"><span class="header-section-number">2.2</span> The CodeReckons API<a href="#the-codereckons-api" class="self-link"></a></h2>
<p>The <a href="https://lists.isocpp.org/sg7/2024/04/0507.php">CodeReckons</a>
approach provides a very different injection mechanism than what is in
P2996 or what has been described in any of the metaprogramming papers.
We can run through these three examples and see what they look like.
Here, we will use the actual syntax as implemented in that compiler.</p>
<h3 data-number="2.2.1" id="stdtuple-1"><span class="header-section-number">2.2.1</span>
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdtuple-1" class="self-link"></a></h3>
<p>The initial CodeReckons article provides <a href="https://cppmeta.codereckons.com/tools/z/j74nc4">an
implementation</a> for adding the data members of a tuple like so:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">%</span> <span class="op">[](</span>class_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>type T <span class="op">:</span> std<span class="op">::</span>meta<span class="op">::</span>type_list<span class="op">{^</span>Ts<span class="op">...})</span> <span class="op">{</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>        append_field<span class="op">(</span>b, cat<span class="op">(</span><span class="st">&quot;m&quot;</span>, k<span class="op">++)</span>, T<span class="op">)</span>;</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This isn’t too different from what we showed in the earlier section
with <code class="sourceCode cpp">data_member_spec</code>. Different
spelling and API, but it’s the same model
(<code class="sourceCode cpp">append_field</code> is equivalent to
injecting a <code class="sourceCode cpp">data_member_spec</code>).</p>
<h3 data-number="2.2.2" id="stdenable_if-1"><span class="header-section-number">2.2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code><a href="#stdenable_if-1" class="self-link"></a></h3>
<p>Likewise, we have just a <a href="https://cppmeta.codereckons.com/tools/z/rh8zef">difference of
spelling</a>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> B, <span class="kw">typename</span> T<span class="op">=</span><span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> enable_if <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">%</span> <span class="op">[](</span>class_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>B<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>            append_alias<span class="op">(</span>b, identifier<span class="op">{</span><span class="st">&quot;type&quot;</span><span class="op">}</span>, <span class="op">^</span>T<span class="op">)</span>;</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}()</span>;</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.2.3" id="properties-1"><span class="header-section-number">2.2.3</span> Properties<a href="#properties-1" class="self-link"></a></h3>
<p>Here is where the CodeReckons approach differs greatly from the
potential spec API, and it’s worth examining how they <a href="https://cppmeta.codereckons.com/tools/z/znjs3f">got it
working</a>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>class_builder<span class="op">&amp;</span> b, type type, std<span class="op">::</span>string name<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> member_name <span class="op">=</span> identifier<span class="op">{(</span><span class="st">&quot;m_&quot;</span> <span class="op">+</span> name<span class="op">).</span>c_str<span class="op">()}</span>;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    append_field<span class="op">(</span>b, member_name, type<span class="op">)</span>;</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// getter</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        method_prototype mp;</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        object_type<span class="op">(</span>mp, make_const<span class="op">(</span>decl_of<span class="op">(</span>b<span class="op">)))</span>;</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        return_type<span class="op">(</span>mp, make_lvalue_reference<span class="op">(</span>make_const<span class="op">(</span>type<span class="op">)))</span>;</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>        append_method<span class="op">(</span>b, identifier<span class="op">{(</span><span class="st">&quot;get_&quot;</span> <span class="op">+</span> name<span class="op">).</span>c_str<span class="op">()}</span>, mp,</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">[</span>member_name<span class="op">](</span>method_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>                append_return<span class="op">(</span>b,</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>                    make_field_expr<span class="op">(</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>                        make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">))</span>,</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>                        member_name<span class="op">))</span>;</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// setter</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>        method_prototype mp;</span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>        append_parameter<span class="op">(</span>mp, <span class="st">&quot;x&quot;</span>, make_lvalue_reference<span class="op">(</span>make_const<span class="op">(</span>type<span class="op">)))</span>;</span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>        object_type<span class="op">(</span>mp, decl_of<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>        return_type<span class="op">(</span>mp, <span class="op">^</span><span class="dt">void</span><span class="op">)</span>;</span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>        append_method<span class="op">(</span>b, identifier<span class="op">{(</span><span class="st">&quot;set_&quot;</span> <span class="op">+</span> name<span class="op">).</span>c_str<span class="op">()}</span>, mp,</span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">[</span>member_name<span class="op">](</span>method_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>                append_expr<span class="op">(</span>b,</span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>                    make_operator_expr<span class="op">(</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>                        operator_kind<span class="op">::</span>assign,</span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>                        make_field_expr<span class="op">(</span>make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">))</span>, member_name<span class="op">)</span>,</span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a>                        make_decl_ref_expr<span class="op">(</span>parameters<span class="op">(</span>decl_of<span class="op">(</span>b<span class="op">))[</span><span class="dv">1</span><span class="op">])</span></span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a>                        <span class="op">))</span>;</span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Book <span class="op">{</span></span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">%</span> property<span class="op">(^</span>std<span class="op">::</span>string, <span class="st">&quot;author&quot;</span><span class="op">)</span>;</span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">%</span> property<span class="op">(^</span>std<span class="op">::</span>string, <span class="st">&quot;title&quot;</span><span class="op">)</span>;</span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>In this model, we have to provide the signature of the two member
functions (via <code class="sourceCode cpp">method_prototype</code>),
and the bodies of the two member functions are provided as lambdas. But
the lambda bodies here are not the C++ code that will be evaluated at
runtime - it’s still part of the AST building process. We have to
define, at the AST level, what these member functions do.</p>
<p>In the spec API, we struggled how to write a function that takes a
<code class="sourceCode cpp">string <span class="kw">const</span><span class="op">&amp;</span></code>
and whose body is <code class="sourceCode cpp">self<span class="op">.{</span>member name<span class="op">}</span> <span class="op">=</span> x;</code>.
Here, because we don’t need to access any of our reflections as constant
expressions, we can make use of them directly.</p>
<p>But the result is… extremely verbose. This is a lot of code, that
doesn’t seem like it would scale very well. The setter alone (which is
just trying to do something like <code class="sourceCode cpp">self<span class="op">.</span>m_author <span class="op">=</span> x;</code>)
is already 14 lines of code and is fairly complicated. We think it’s
important that code injection still look like writing C++ code, not live
at the AST level.</p>
<p>Nevertheless, this API does actually work. Whereas the spec API is
still, at best, just a guess.</p>
<h3 data-number="2.2.4" id="postfix-increment"><span class="header-section-number">2.2.4</span> Postfix Increment<a href="#postfix-increment" class="self-link"></a></h3>
<p>For postfix increment, we want to inject the single function:</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">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> tmp;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We rely on the type to provide the correct prefix increment. With the
CodeReckons API, that looks <a href="https://cppmeta.codereckons.com/tools/z/71To7o">like this</a>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">(</span>class_builder<span class="op">&amp;</span> b<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    method_prototype mp;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    append_parameter<span class="op">(</span>mp, <span class="st">&quot;x&quot;</span>, <span class="op">^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    object_type<span class="op">(</span>mp, decl_of<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    return_type<span class="op">(</span>mp, decl_of<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    append_method<span class="op">(</span>b, operator_kind<span class="op">::</span>post_inc, mp,</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">[](</span>method_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>            <span class="co">// auto tmp = *this;</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> append_var<span class="op">(</span>b, <span class="st">&quot;tmp&quot;</span>, auto_ty,</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>                make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">)))</span>;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ++*this;</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>            append_expr<span class="op">(</span>b,</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>                make_operator_expr<span class="op">(</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>                    operator_kind<span class="op">::</span>pre_inc,</span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>                    make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">))))</span>;</span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>            <span class="co">// return tmp;</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>            append_return<span class="op">(</span>b, make_decl_ref_expr<span class="op">(</span>tmp<span class="op">))</span>;</span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i;</span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">-&gt;</span> C<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>i;</span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">%</span> postfix_increment<span class="op">()</span>;</span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>As with the property example above, having an AST-based API is
extremely verbose. It might be useful to simply compare the statement we
want to generate with the code that we require to write to generate that
statement:</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="co">// auto tmp = *this;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>   <span class="kw">auto</span> tmp <span class="op">=</span> append_var<span class="op">(</span>b, <span class="st">&quot;tmp&quot;</span>, auto_ty, make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">)))</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">// ++*this;</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>   append_expr<span class="op">(</span>b, make_operator_expr<span class="op">(</span>operator_kind<span class="op">::</span>pre_inc, make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">))))</span>;</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="co">// return tmp;</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>   append_return<span class="op">(</span>b, make_decl_ref_expr<span class="op">(</span>tmp<span class="op">))</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.2.5" id="disposition-1"><span class="header-section-number">2.2.5</span> Disposition<a href="#disposition-1" class="self-link"></a></h3>
<p>We believe an important goal for code injection is that the code
being injected looks like C++. This is the best way to ensure both a low
barrier to entry for using the facility as well as easing language
evolution in the future. We do not want to have to have to add a mirror
API to the reflection library for every language facility we add.</p>
<p>The CodeReckons API has the significant and not-to-be-minimized
property that it, unlike the Spec API, works. It is also arguably easy
to <em>read</em> the code in question to figure out what is going on. In
our experiments with simply giving people code snippets to people with
no context and asking them what the snippet does, people were able to
figure it out.</p>
<p>However, in our experience it is pretty difficult to <em>write</em>
the code precisely because it needs to be written at a different layer
than C++ code usually is written in and the abstraction penalty (in
terms of code length) is so large. We will compare this AST-based API to
a few other ideas in the following sections to give a sense of what we
mean here.</p>
<h2 data-number="2.3" id="string-injection"><span class="header-section-number">2.3</span> String Injection<a href="#string-injection" class="self-link"></a></h2>
<p>If we go back all the way to the beginning - we’re trying to inject
code. Perhaps the simplest possible model for how to inject code would
be: just inject strings.</p>
<p>The advantage of strings is clear: everyone already knows how to
build up strings. This makes implementing the three use-cases presented
thus far is pretty straightforward.</p>
<h3 data-number="2.3.1" id="stdtuple-2"><span class="header-section-number">2.3.1</span>
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdtuple-2" class="self-link"></a></h3>
<p>We could just do tuple this way:</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">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Tuple <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>array types<span class="op">{^</span>Ts<span class="op">...}</span>;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> types<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(</span>std<span class="op">::</span>format<span class="op">(</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;[[no_unique_address]] {} _{};&quot;</span>,</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>                qualified_name_of<span class="op">(</span>types<span class="op">[</span>i<span class="op">])</span>,</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>                i<span class="op">))</span>;</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Note that here we even added support for <code class="sourceCode cpp"><span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></code>,
which we haven’t done in either of the previous models. Although we
could come up with a way to add it to either of the two previous APIs,
the fact that with string injection we don’t even have to come up with a
way to do this is a pretty significant upside. Everything just
works.</p>
<p>Now, this would work - we’d have to be careful to use
<code class="sourceCode cpp">qualified_name_of</code> here to avoid any
question of name lookup. But it would be better to simply avoid these
questions altogether by actually being able to splice in the type rather
than referring to it by name.</p>
<p>We can do that by very slightly extending the API to take, as its
first argument, an environment. And then we can reduce it again by
having the API itself be a <code class="sourceCode cpp">format</code>
API:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Tuple <span class="op">{</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>array types<span class="op">{^</span>Ts<span class="op">...}</span>;</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> types<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">{{</span><span class="st">&quot;type&quot;</span>, types<span class="op">[</span>i<span class="op">]}}</span>,</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;[[no_unique_address]] [:type:] _{};&quot;</span>,</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>                i<span class="op">)</span>;</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.3.2" id="stdenable_if-2"><span class="header-section-number">2.3.2</span> <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code><a href="#stdenable_if-2" class="self-link"></a></h3>
<p>This one is even simpler, since we don’t even need to bother with
name lookup questions or splicing:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> B, <span class="kw">class</span> T<span class="op">=</span><span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> enable_if <span class="op">{</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>B<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(</span><span class="st">&quot;using type = T;&quot;</span><span class="op">)</span>;</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.3.3" id="properties-2"><span class="header-section-number">2.3.3</span> Properties<a href="#properties-2" class="self-link"></a></h3>
<p>Unlike with the spec API, implementing a property by way of code is
straightforward. And unlike the CodeReckons API, we can write what looks
like C++ code:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>info type, string_view name<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span>meta<span class="op">::</span>format_with_environment<span class="op">(</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">{{</span><span class="st">&quot;T&quot;</span>, type<span class="op">}}</span>,</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>        <span class="st">R&quot;(</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="st">        private:</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="st">            [:T:] m_{0};</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="st">        public:</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a><span class="st">            auto get_{0}() const -&gt; [:T:] const&amp; {{</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="st">                return m_{0};</span></span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a><span class="st">            }}</span></span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a><span class="st">            auto set_{0}(typename [:T:] const&amp; x) -&gt; void {{</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a><span class="st">                m_{0} = x;</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a><span class="st">            }}</span></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a><span class="st">        )&quot;</span>,</span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>        name<span class="op">))</span>;</span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Book <span class="op">{</span></span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(^</span>string, <span class="st">&quot;author&quot;</span><span class="op">)</span>;</span>
<span id="cb23-23"><a href="#cb23-23" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(^</span>string, <span class="st">&quot;title&quot;</span><span class="op">)</span>;</span>
<span id="cb23-24"><a href="#cb23-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-25"><a href="#cb23-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.3.4" id="postfix-increment-1"><span class="header-section-number">2.3.4</span> Postfix Increment<a href="#postfix-increment-1" class="self-link"></a></h3>
<p>Similarly, the postfix increment implementation just writes itself.
In this case, we can even return
<code class="sourceCode cpp"><span class="kw">auto</span></code> so
don’t even need to bother with how to spell the return type:</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">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(</span><span class="st">R&quot;(</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="st">        auto operator++(int) {</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="st">            auto tmp = *this;</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="st">            ++*this;</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="st">            return tmp;</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="st">        }</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="st">    )&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>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i;</span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">-&gt;</span> C<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>i;</span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span> postfix_increment<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.3.5" id="disposition-2"><span class="header-section-number">2.3.5</span> Disposition<a href="#disposition-2" class="self-link"></a></h3>
<p>Can pretty much guarantee that strings have the lowest possible
barrier to entry of any code injection API. Which is a benefit that is
not to be taken lightly! It is not surprising that D and Jai both have
string-based injection mechanisms.</p>
<p>But string injection is hardly perfect, and several of the issues
with it might be clear already:</p>
<ol type="1">
<li>String injection does let you write what looks like C++ code, but it
wouldn’t let you use any macros - as those don’t affect the contents of
string literals and we can’t run another preprocessing step later.</li>
<li>Our main string formatting mechanism,
<code class="sourceCode cpp">format</code>, uses
<code class="sourceCode cpp"><span class="op">{}</span></code> for
replacement fields, which means actual braces - which show up in C++ a
lot - have to be escaped. It also likely isn’t the most compile-time
efficient API, so driving reflection off of it might be suboptimal.</li>
<li>You don’t get syntax highlighting for injected code strings. They’re
just strings. Perhaps we could introduce a new kind of string literal
that syntax highlighters could recognize, but that seems like
pre-emptively admitting defeat.</li>
<li>Errors happen at the point of <em>injection</em>, not at the point
where you’re writing the code. And the injection could happen very far
away from the code.</li>
</ol>
<p>But string injection offers an extremely significant advantage that’s
not to be underestimated: everyone can deal with strings and strings
already just support everything, for all future evolution, without the
need for a large API.</p>
<p>Can we do better?</p>
<h2 data-number="2.4" id="fragments"><span class="header-section-number">2.4</span> Fragments<a href="#fragments" class="self-link"></a></h2>
<p><span class="citation" data-cites="P1717R0">[<a href="https://wg21.link/p1717r0" role="doc-biblioref">P1717R0</a>]</span> introduced the concept of
fragments. It introduced many different kinds of fragments, under syntax
that changed a bit in <span class="citation" data-cites="P2050R0">[<a href="https://wg21.link/p2050r0" role="doc-biblioref">P2050R0</a>]</span> and <span class="citation" data-cites="P2237R0">[<a href="https://wg21.link/p2237r0" role="doc-biblioref">P2237R0</a>]</span>. We’ll use what the linked
implementation uses, but feel free to change it as you read.</p>
<h3 data-number="2.4.1" id="stdtuple-3"><span class="header-section-number">2.4.1</span>
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdtuple-3" class="self-link"></a></h3>
<p>The initial fragments paper itself led off with an implementation of
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>
storage and the concept of a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
block (now also <span class="citation" data-cites="P3289R0">[<a href="https://wg21.link/p3289r0" role="doc-biblioref">P3289R0</a>]</span>). That <a href="https://godbolt.org/z/E19rezx6T">looks like this</a> (the linked
implementation looks a little different, due to an implementation
bug):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Tuple <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>array types<span class="op">{^</span>Ts<span class="op">...}</span>;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> types<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> <span class="kw">typename</span><span class="op">(%{</span>types<span class="op">[</span>i<span class="op">]})</span> unqualid<span class="op">(</span><span class="st">&quot;_&quot;</span>, <span class="op">%{</span>i<span class="op">})</span>;</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span>;</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Now, the big advantage of fragments is that it’s just C++ code in the
middle there (maybe it feels a bit messy in this example but it will
more shortly). The leading
<code class="sourceCode cpp"><span class="op">-&gt;</span></code> is the
injection operator.</p>
<p>One big problem that fragments need to solve is how to get context
information into them. For instance, how do get the type <code class="sourceCode cpp">types<span class="op">[</span>i<span class="op">]</span></code>
and how do we produce the names <code class="sourceCode cpp">_0</code>,
<code class="sourceCode cpp">_1</code>, …, for all of these members? We
need a way to capture context, and it needs to be interpolated
differently.</p>
<p>In the above example, the design uses the operator
<code class="sourceCode cpp">unqualid</code> (to create an unqualified
id) concatenating the string literal <code class="sourceCode cpp"><span class="st">&quot;_&quot;</span></code> with
the interpolated value <code class="sourceCode cpp"><span class="op">%{</span>i<span class="op">}</span></code>
(a later revision used <code class="sourceCode cpp"><span class="op">|</span><span class="er"># #|</span></code>
instead). We need distinct operators to differentiate between the case
where we want to use a string as an identifier and as an actual
string.</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>std<span class="op">::</span>string name <span class="op">=</span> <span class="st">&quot;hello&quot;</span>;</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// std::string name = &quot;name&quot;;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>string unqualid<span class="op">(%{</span>name<span class="op">})</span> <span class="op">=</span> <span class="op">%{</span>name<span class="op">}</span>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.4.2" id="stdenable_if-3"><span class="header-section-number">2.4.2</span> <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code><a href="#stdenable_if-3" class="self-link"></a></h3>
<p>It is very hard to compete <a href="https://godbolt.org/z/nf8nPnnh4">with this</a>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> B, <span class="kw">class</span> T<span class="op">=</span><span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> enable_if <span class="op">{</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>B<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span> <span class="kw">using</span> type <span class="op">=</span> T; <span class="op">}</span>;</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Sure, you might want to simplify this just having a class scope
<code class="sourceCode cpp"><span class="cf">if</span></code> directly
and then putting the contents of the
<code class="sourceCode cpp">fragment</code> in there. But this is very
nice.</p>
<h3 data-number="2.4.3" id="properties-3"><span class="header-section-number">2.4.3</span> Properties<a href="#properties-3" class="self-link"></a></h3>
<p>The <a href="https://godbolt.org/z/ddbsYWsvr">implementation here</a>
isn’t too different from the <a href="#properties-2">string
implementation</a> (this was back when the reflection operator was
<code class="sourceCode cpp">reflexpr</code>, before it changed to
<code class="sourceCode cpp"><span class="op">^</span></code>):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>meta<span class="op">::</span>info type, <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> name<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>;</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;get_&quot;</span>, <span class="op">%{</span>name<span class="op">})()</span> <span class="op">-&gt;</span> <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>;</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;set_&quot;</span>, <span class="op">%{</span>name<span class="op">})(</span><span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>            unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span> <span class="op">=</span> x;</span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Book <span class="op">{</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(</span>reflexpr<span class="op">(</span>std<span class="op">::</span>string<span class="op">)</span>, <span class="st">&quot;author&quot;</span><span class="op">)</span>;</span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>        property<span class="op">(</span>reflexpr<span class="op">(</span>std<span class="op">::</span>string<span class="op">)</span>, <span class="st">&quot;title&quot;</span><span class="op">)</span>;</span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>It’s a bit busy because nearly everything in properties involves
quoting outside context, so seemingly everything here is quoted.</p>
<p>Now, there’s one very important property of fragments (as designed in
these papers) hold: every fragment must be parsable in its context. A
fragment does not leak its declarations out of its context; only out of
the context where it is injected. Not only that, we get full name lookup
and everything.</p>
<p>On the one hand, this seems like a big advantage: the fragment is
checked at the point of its declaration, not at the point of its use.
With the string model above, that was not the case - you can write
whatever garbage string you want and it’s still a perfectly valid
string, it only becomes invalid C++ code when it’s injected.</p>
<p>On the other, it has some consequences for how we can code using
fragments. In the above implementation, we inject the whole property in
one go. But let’s say we wanted to split it up for whatever reason. We
can’t. This is invalid:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>meta<span class="op">::</span>info type, <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> name<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>;</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;get_&quot;</span>, <span class="op">%{</span>name<span class="op">})()</span> <span class="op">-&gt;</span> <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>; <span class="co">// error</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;set_&quot;</span>, <span class="op">%{</span>name<span class="op">})(</span><span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>            unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span> <span class="op">=</span> x; <span class="co">// error</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>In this second fragment, name lookup for
<code class="sourceCode cpp">m_author</code> fails in both function
bodies. We can’t do that. We We have to teach the fragment how to find
the name, which requires writing this (note the added
<code class="sourceCode cpp"><span class="kw">requires</span></code>
statement):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>meta<span class="op">::</span>info type, <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> name<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>;</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>;</span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;get_&quot;</span>, <span class="op">%{</span>name<span class="op">})()</span> <span class="op">-&gt;</span> <span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span>; <span class="co">// error</span></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> unqualid<span class="op">(</span><span class="st">&quot;set_&quot;</span>, <span class="op">%{</span>name<span class="op">})(</span><span class="kw">typename</span><span class="op">(%{</span>type<span class="op">})</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>            unqualid<span class="op">(</span><span class="st">&quot;m_&quot;</span>, <span class="op">%{</span>name<span class="op">})</span> <span class="op">=</span> x; <span class="co">// error</span></span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="2.4.4" id="postfix-increment-2"><span class="header-section-number">2.4.4</span> Postfix increment<a href="#postfix-increment-2" class="self-link"></a></h3>
<p>One boilerplate annoyance is implementing
<code class="sourceCode cpp">x<span class="op">++</span></code> in terms
of <code class="sourceCode cpp"><span class="op">++</span>x</code>. Can
code injection help us out? Postfix increment ends up being <a href="https://godbolt.org/z/r1v3e43sd">much simpler to implement</a>
with fragments than properties - due to not having to deal with any
quoted names. But it does surface the issue of name lookup in
fragments.</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">()</span> <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> T<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> tmp;</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i;</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">-&gt;</span> C<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>i;</span>
<span id="cb31-18"><a href="#cb31-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-21"><a href="#cb31-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span> postfix_increment<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb31-22"><a href="#cb31-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Now, the rule in the fragments implementation is that the fragments
themselves are checked. This includes name lookup. So any name used in
the body of the fragment has to be found and pre-declared, which is what
we’re doing in the
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause there. The implementation right now appears to have a bug with
respect to operators (if you change the body to calling <code class="sourceCode cpp">inc<span class="op">(*</span><span class="kw">this</span><span class="op">)</span></code>,
it does get flagged), which is why it’s commented out in the link.</p>
<h3 data-number="2.4.5" id="disposition-3"><span class="header-section-number">2.4.5</span> Disposition<a href="#disposition-3" class="self-link"></a></h3>
<p>The fragment model seems substantially easier to program in than the
CodeReckons model. We’re actually writing C++ code. Consider the
difference here between the CodeReckons solution and the Fragments
solution to postfix increment:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><a href="https://cppmeta.codereckons.com/tools/z/71To7o">CodeReckons</a></strong>
</div></th>
<th><div style="text-align:center">
<strong><a href="https://godbolt.org/z/r1v3e43sd">Fragments</a></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">(</span>class_builder<span class="op">&amp;</span> b<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>    method_prototype mp;</span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>    append_parameter<span class="op">(</span>mp, <span class="st">&quot;x&quot;</span>, <span class="op">^</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>    object_type<span class="op">(</span>mp, decl_of<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    return_type<span class="op">(</span>mp, decl_of<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>    append_method<span class="op">(</span>b, operator_kind<span class="op">::</span>post_inc, mp,</span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">[](</span>method_builder<span class="op">&amp;</span> b<span class="op">){</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> append_var<span class="op">(</span>b, <span class="st">&quot;tmp&quot;</span>, auto_ty,</span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>                make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">)))</span>;</span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>            append_expr<span class="op">(</span>b,</span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>                make_operator_expr<span class="op">(</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a>                    operator_kind<span class="op">::</span>pre_inc,</span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>                    make_deref_expr<span class="op">(</span>make_this_expr<span class="op">(</span>b<span class="op">))))</span>;</span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>            append_return<span class="op">(</span>b, make_decl_ref_expr<span class="op">(</span>tmp<span class="op">))</span>;</span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i;</span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">-&gt;</span> C<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>i;</span>
<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">%</span> postfix_increment<span class="op">()</span>;</span>
<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

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

<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">()</span> <span class="op">{</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> T<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> tmp;</span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i;</span>
<span id="cb33-27"><a href="#cb33-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-28"><a href="#cb33-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">-&gt;</span> C<span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb33-29"><a href="#cb33-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>i;</span>
<span id="cb33-30"><a href="#cb33-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb33-31"><a href="#cb33-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-32"><a href="#cb33-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-33"><a href="#cb33-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span> postfix_increment<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb33-34"><a href="#cb33-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>We lined up the fragment implementation to roughly correspond to the
CodeReckons API on the left. With the code written out like this, it’s
easy to understand the CodeReckons API. But it takes no time at all to
understand (or write) the fragments code on the right - it’s just C++
already.</p>
<p>We also think it’s a better idea than the string injection model,
since we want something with structure that isn’t just missing some
parts of the language (the processor) and plays nicely with tools (like
syntax highlighters).</p>
<p>But we think the fragment model still isn’t quite right. By nobly
trying to diagnose errors at the point of fragment declaration, it adds
a complexity to the fragment model in a way that we don’t think carries
its weight. The fragment papers (<span class="citation" data-cites="P1717R0">[<a href="https://wg21.link/p1717r0" role="doc-biblioref">P1717R0</a>]</span> and <span class="citation" data-cites="P2237R0">[<a href="https://wg21.link/p2237r0" role="doc-biblioref">P2237R0</a>]</span>) each go into some detail of
different approaches of how to do name checking at the point of fragment
declaration. They are all complicated.</p>
<p>We basically want something between strings and fragments.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="token-sequences"><span class="header-section-number">3</span> Token
Sequences<a href="#token-sequences" class="self-link"></a></h1>
<p>Generation of code from low-level syntactic elements such as strings
or token sequences may be considered quite unsophisticated. Indeed,
previous proposals for code synthesis in C++ have studiously minimized
using strings or tokens as input but resorting to AST-based APIs,
expansion statements, or code fragments, as shown above. As noted by
Andrew Sutton in <span class="citation" data-cites="P2237R0">[<a href="https://wg21.link/p2237r0" role="doc-biblioref">P2237R0</a>]</span>:</p>
<div class="quote">
<p>synthesizing new code from strings is straightforward, especially
when the language/library has robust tools for compile-time string
manipulation […] the strings or tokens are syntactically and
semantically unanalyzed until they are injected</p>
</div>
<p>whereas the central premise—and purported advantage—of a code
fragment is it</p>
<div class="quote">
<p>should be fully syntactically and semantically validated prior to its
injection</p>
</div>
<p>Due to the lack of consensus for a code synthesis mechanism, some C++
reflection proposals shifted focus to the query side of reflection and
left room for scant code synthesis capabilities.</p>
<p>After extensive study and experimentation (as seen above), we
concluded that some crucially important forms of token synthesis are
necessary for practical code generation, and that insisting upon early
syntactic and semantic validation of generated code is a net liability.
The very nature of code synthesis involves assembling meaningful
constructs out of pieces that have little or no meaning in separation.
Using concatenation and deferring syntax/semantics analysis to offer
said concatenation is by far the simplest, most direct approach to code
synthesis.</p>
<p>Generally, we think that imposing early checking on generated code is
likely to complicate and restrict the ways in which users can use the
facility and also be difficult for implementers, thus hurting everyone
involved.</p>
<p>We therefore acknowledge the notion of token sequence as a core
building block for generating code. Using token sequences allows
flexibility to code that generates other code, while deferring name
lookup and semantic analysis to well-defined points in the compilation
process. Thus we reach the notion of a
<code class="sourceCode cpp"><span class="op">@</span>tokens</code>
literal dedicated to representing unprocessed sequences of tokens.</p>
<h2 data-number="3.1" id="tokens-literal"><span class="header-section-number">3.1</span>
<code class="sourceCode cpp"><span class="op">@</span>tokens</code>
literal<a href="#tokens-literal" class="self-link"></a></h2>
<p>We propose the introduction of a new literal with the following
syntax (the specific introducer can be decided later):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="op">@</span>tokens <span class="op">{</span> <em>balanced-brace-tokens</em> <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>where
<code class="sourceCode cpp"><em>balanced-brace-tokens</em></code> is an
arbitrary sequence of C++ tokens with the sole requirement that the
<code class="sourceCode cpp"><span class="op">{</span></code> and
<code class="sourceCode cpp"><span class="op">}</span></code> pairs are
balanced. Parentheses and square brackets may be unbalanced. The opening
and closing
<code class="sourceCode cpp"><span class="op">{</span></code>/<code class="sourceCode cpp"><span class="op">}</span></code>
are not part of the token sequence. The type of a
<code class="sourceCode cpp"><span class="op">@</span>tokens</code>
literal is <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>.</p>
<p>For example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t1 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> a <span class="op">+</span> b <span class="op">}</span>;      <span class="co">// three tokens</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>t1<span class="op">)</span>, <span class="kw">const</span> std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;)</span>;</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t2 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> a <span class="op">+=</span> <span class="op">(</span> <span class="op">}</span>;     <span class="co">// code does not have to be meaningful</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t3 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> abc <span class="op">{</span> def <span class="op">}</span>;  <span class="co">// Error, unpaired brace</span></span></code></pre></div>
</blockquote>
</div>
<p>Token sequences can be concatenated with the
<code class="sourceCode cpp"><span class="op">+</span></code> operator.
The result is a token sequence consisting of the concatenation of the
operands.</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t1 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> c <span class="op">=</span>  <span class="op">}</span>;</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t2 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> a <span class="op">+</span> b; <span class="op">}</span>;</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t3 <span class="op">=</span> t1 <span class="op">+</span> t2;</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>t3 <span class="op">==</span> <span class="op">@</span>tokens <span class="op">{</span> c <span class="op">=</span> a <span class="op">+</span> b; <span class="op">})</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The concatenation is not textual - two tokens concatenated together
preserve their identity, they are not pasted together into a single
token. For example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t1 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> abc <span class="op">}</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t2 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> def <span class="op">}</span>;</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t3 <span class="op">=</span> t1 <span class="op">+</span> t2;</span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>t3 <span class="op">!=</span> <span class="op">@</span>tokens <span class="op">{</span> abcdef <span class="op">})</span>;</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>t3 <span class="op">==</span> <span class="op">@</span>tokens <span class="op">{</span> abc def <span class="op">})</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Whitespace and comments are treated just like in regular code - they
are not significant beyond their role as token separator. For
example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t1 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> hello  <span class="op">=</span> <span class="co">/* world */</span>   <span class="st">&quot;world&quot;</span> <span class="op">}</span>;</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> t2 <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="co">/* again */</span> hello<span class="op">=</span><span class="st">&quot;world&quot;</span> <span class="op">}</span>;</span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>t1 <span class="op">==</span> t2<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Because tokens are handled after the the initial phase of
preprocessing, macros and string concatenation can apply - but you have
to be careful with macros because they won’t work the way you might
want</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">static_assert</span><span class="op">(</span>tokens { “abc” “def” } ==tokens <span class="op">{</span> <span class="st">&quot;abcdef&quot;</span> <span class="op">})</span>;</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a><span class="co">// this concatenation produces the token sequence &quot;abc&quot; &quot;def&quot;, not &quot;abcdef&quot;</span></span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a><span class="co">// when this token sequence will be injected, that will be ill-formed</span></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>tokens { “abc” } +tokens <span class="op">{</span> <span class="st">&quot;def&quot;</span> <span class="op">}</span> <span class="op">!=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="st">&quot;abcdef&quot;</span> <span class="op">})</span>;</span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define PLUS_ONE</span><span class="op">(</span>x<span class="op">)</span><span class="pp"> </span><span class="op">((</span>x<span class="op">)</span><span class="pp"> </span><span class="op">+</span><span class="pp"> </span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>tokens { PLUS_ONE(x) } ==tokens <span class="op">{</span> <span class="op">((</span>x<span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">)</span> <span class="op">})</span>;</span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a><span class="co">// amusingly this version also still works but not for the reason you think</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a><span class="co">// on the left-hand-side the macro PLUS_ONE is still invoked...</span></span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a><span class="co">// but as PLUS_ONE(x} +@tokens{)</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a><span class="co">// which produces ((x} +@tokens{) + 1)</span></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a><span class="co">// which leads to tokens { ((x } +tokens{) + 1) }</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a><span class="co">// which is @tokens{ ((x) + 1)}</span></span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>tokens { PLUS_ONE(x } +tokens<span class="op">{</span> <span class="op">)</span> <span class="op">}</span> <span class="op">==</span> <span class="op">@</span>tokens <span class="op">{</span> PLUS_ONE<span class="op">(</span>x<span class="op">)</span> <span class="op">})</span>;</span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a><span class="co">// But this one finally fails, because the macro isn&#39;t actually invoked</span></span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> tok2 <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb39-20"><a href="#cb39-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> t <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> PLUS_ONE<span class="op">(</span>x <span class="op">}</span>;</span>
<span id="cb39-21"><a href="#cb39-21" aria-hidden="true" tabindex="-1"></a>    constexpr_print_str<span class="op">(</span><span class="st">&quot;Logging...</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">)</span>;</span>
<span id="cb39-22"><a href="#cb39-22" aria-hidden="true" tabindex="-1"></a>    t <span class="op">+=</span> <span class="op">@</span>tokens<span class="op">{</span> <span class="op">)</span> <span class="op">}</span></span>
<span id="cb39-23"><a href="#cb39-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> t;</span>
<span id="cb39-24"><a href="#cb39-24" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span>;</span>
<span id="cb39-25"><a href="#cb39-25" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>tok2 <span class="op">!=</span> <span class="op">@</span>tokens <span class="op">{</span> PLUS_ONE<span class="op">(</span>x<span class="op">)</span> <span class="op">})</span>;</span></code></pre></div>
</blockquote>
</div>
<p>A token sequence has no meaning by itself, until injected. But
because (hopefully) users will write valid C++ code, the resulting
injection actually does look like C++ code.</p>
<h2 data-number="3.2" id="quoting-into-a-token-sequence"><span class="header-section-number">3.2</span> Quoting into a token sequence<a href="#quoting-into-a-token-sequence" class="self-link"></a></h2>
<p>There’s still the issue that you need to access outside context from
within a token sequence. For that we introduce dedicated capture syntax
using the interpolators
<code class="sourceCode cpp"><span class="er">$</span>eval</code> and
<code class="sourceCode cpp"><span class="er">$</span>id</code>.</p>
<p>The implementation model for this is that we collect the tokens
within a <code class="sourceCode cpp"><span class="op">@</span>token <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code>
literal, but every time we run into a capture, we parse and evaluate the
expression within and replace it with the value as described below:</p>
<ul>
<li><code class="sourceCode cpp"><span class="er">$</span>eval<span class="op">(</span>e<span class="op">)</span></code>
for <code class="sourceCode cpp">e</code> of type
<code class="sourceCode cpp">meta<span class="op">::</span>info</code>
is replaced by a pseudo-literal token holding the
<code class="sourceCode cpp">info</code> value. If
<code class="sourceCode cpp">e</code> is itself a token sequence, the
contents of that token sequence are concatenated in place.</li>
<li><code class="sourceCode cpp"><span class="er">$</span>id<span class="op">(</span>e<span class="op">)</span></code>
for <code class="sourceCode cpp">e</code> being string-like or integral
is replaced with that value. <code class="sourceCode cpp"><span class="er">$</span>id<span class="op">(</span>e<span class="op">...)</span></code>
can concatenate multiple string-like or integral values into a single
identifier.</li>
</ul>
<p>These need to be distinct because a given string could be intended to
be injected as a <em>string</em>, like <code class="sourceCode cpp"><span class="st">&quot;var&quot;</span></code>,
or as an <em>identifier</em>, like
<code class="sourceCode cpp">var</code>. There’s no way to determine
which one is indented, so they have to be spelled differently.</p>
<p>With that in mind, we can start going through our examples.</p>
<h2 data-number="3.3" id="examples"><span class="header-section-number">3.3</span> Examples<a href="#examples" class="self-link"></a></h2>
<p>Now, the
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>
and <code class="sourceCode cpp">std<span class="op">::</span>enable_if</code>
cases would look identical to their corresponding implementations with
<a href="#fragments">fragments</a>. In both cases, we are injecting
complete code fragments that require no other name lookup, so there is
not really any difference between a token sequence and a proper
fragment. You can see the use of both kinds of interpolator on the
left:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">std<span class="op">::</span>tuple</code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code class="sourceCode cpp">std<span class="op">::</span>enable_if</code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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">class</span><span class="op">...</span> Ts<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> Tuple <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>array types<span class="op">{^</span>Ts<span class="op">...}</span>;</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> types<span class="op">.</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>types<span class="op">[</span>i<span class="op">])</span> <span class="op">:]</span> <span class="er">$</span>id<span class="op">(</span><span class="st">&quot;_&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

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

<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> B, <span class="kw">class</span> T<span class="op">=</span><span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> enable_if <span class="op">{</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>B<span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(@</span>tokens <span class="op">{</span> <span class="kw">using</span> type <span class="op">=</span> T; <span class="op">})</span>;</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The property example likewise could be identical, but we do not run
into any name lookup issues, so we can write it any way we want - either
as injecting one token sequence or even injecting three. Both work fine
without needing any additional declarations:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Single Token Sequence</strong>
</div></th>
<th><div style="text-align:center">
<strong>Three Token Sequences</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>meta<span class="op">::</span>info type, std<span class="op">::</span>string name<span class="op">)</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>string member_name <span class="op">=</span> <span class="st">&quot;m_&quot;</span> <span class="op">+</span> name;</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span>;</span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="er">$</span>id<span class="op">(</span><span class="st">&quot;get_&quot;</span>, name<span class="op">)()</span> <span class="op">-&gt;</span> <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span>;</span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="er">$</span>id<span class="op">(</span><span class="st">&quot;set_&quot;</span>, name<span class="op">)(</span><span class="kw">typename</span> <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a>            <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span> <span class="op">=</span> x;</span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> property<span class="op">(</span>meta<span class="op">::</span>info type, std<span class="op">::</span>string name<span class="op">)</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="dt">void</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>string member_name <span class="op">=</span> <span class="st">&quot;m_&quot;</span> <span class="op">+</span> name;</span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span>;</span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="er">$</span>id<span class="op">(</span><span class="st">&quot;get_&quot;</span>, name<span class="op">)()</span> <span class="op">-&gt;</span> <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="op">{</span></span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span>;</span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb43-14"><a href="#cb43-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb43-15"><a href="#cb43-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-16"><a href="#cb43-16" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb43-17"><a href="#cb43-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="er">$</span>id<span class="op">(</span><span class="st">&quot;set_&quot;</span>, name<span class="op">)(</span><span class="kw">typename</span> <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>type<span class="op">):]</span> <span class="kw">const</span><span class="op">&amp;</span> x<span class="op">)</span></span>
<span id="cb43-18"><a href="#cb43-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb43-19"><a href="#cb43-19" aria-hidden="true" tabindex="-1"></a>            <span class="er">$</span>id<span class="op">(</span>member_name<span class="op">)</span> <span class="op">=</span> x;</span>
<span id="cb43-20"><a href="#cb43-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb43-21"><a href="#cb43-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb43-22"><a href="#cb43-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>With the postfix increment example, we see some more interesting
difference. We are not proposing any special-case syntax for getting at
the type that we are injecting into, so it would have to be pulled out
from the context (we’ll name it <code class="sourceCode cpp">T</code> in
both places for consistency):</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Fragment</strong>
</div></th>
<th><div style="text-align:center">
<strong>Token Sequence</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> fragment <span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> T<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> tmp;</span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> postfix_increment<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> T <span class="op">=</span> type_of<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>current<span class="op">())</span>;</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>    inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="op">[:</span><span class="er">$</span>eval<span class="op">(</span>T<span class="op">):]</span> <span class="op">{</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> tmp;</span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">})</span>;</span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The syntax here is, unsurprisingly, largely the same. We’re mostly
writing C++ code. The difference is that we no longer need to
pre-declare the functions we’re using and the feature set is smaller.
While declaring <code class="sourceCode cpp">T</code> as part of the
fragment is certainly convenient, we’re shooting for a smaller
feature.</p>
<h2 data-number="3.4" id="logging-vector-cloning-a-type"><span class="header-section-number">3.4</span> Logging Vector: Cloning a
Type<a href="#logging-vector-cloning-a-type" class="self-link"></a></h2>
<p>The goal here is we want to implement a type <code class="sourceCode cpp">LoggingVector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
which behaves like <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
in all respects except that it prints the function being called.</p>
<p>We start with this:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> LoggingVector <span class="op">{</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> impl;</span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>    LoggingVector<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">:</span> impl<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun <span class="op">:</span> <span class="co">/* public, non-special member functions */</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>                declare <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span> <span class="op">:]</span> <span class="op">{</span></span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// ...</span></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb46-14"><a href="#cb46-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb46-15"><a href="#cb46-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb46-16"><a href="#cb46-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-17"><a href="#cb46-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>We want to clone every member function, which requires copying the
declaration. We don’t want to actually have to spell out the declaration
in the token sequence that we inject - that would be a tremendous amount
of work given the complexity of C++ declarations. So instead we
introduce a new kind of splice: a declaration splice. We already have
<code class="sourceCode cpp"><span class="kw">typename</span> <span class="op">[:</span> e <span class="op">:]</span></code>
and <code class="sourceCode cpp"><span class="kw">template</span> <span class="op">[:</span> e <span class="op">:]</span></code>
in other contexts, so <code class="sourceCode cpp">declare <span class="op">[:</span> e <span class="op">:]</span></code>
at least fits within the family of splicers.</p>
<p>Now, we have two problems to solve in the body (as well as a few more
problems we’ll get to later).</p>
<p>First, we need to print the name of the function we’re calling. This
is easy, since we have the function and can just ask for its name.</p>
<p>Second, we need to actually forward the parameters of the function
into our member <code class="sourceCode cpp">impl</code>. This is,
seemingly, very hard:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun <span class="op">:</span> <span class="co">/* public, non-special member functions */</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>        inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a>            declare <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span> <span class="op">:]</span> <span class="op">{</span></span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a>                std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="er">$</span>eval<span class="op">(</span>name_of<span class="op">(</span>fun<span class="op">)))</span>;</span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> impl<span class="op">.[:</span> <span class="er">$</span>eval<span class="op">(</span>fun<span class="op">)</span> <span class="op">:](</span><span class="co">/* ???? */</span><span class="op">)</span>;</span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb47-8"><a href="#cb47-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb47-9"><a href="#cb47-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb47-10"><a href="#cb47-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This is where the ability of token sequences to be concatenated from
purely sequences of tokens really gives us a lot of value. How do we
forward the parameters along? We don’t even have the parameter names
here - the declaration that we’re cloning might not even <em>have</em>
parameter names.</p>
<p>So there are two approaches that we can use here:</p>
<h3 data-number="3.4.1" id="reflections-of-parameters"><span class="header-section-number">3.4.1</span> Reflections of Parameters<a href="#reflections-of-parameters" class="self-link"></a></h3>
<p>We need the ability to just ask for the parameters themselves (which
<span class="citation" data-cites="P3096R0">[<a href="https://wg21.link/p3096r0" role="doc-biblioref">P3096R0</a>]</span> should provide). And then the
goal here is to inject the tokens for the call:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> impl<span class="op">.[:</span>fun<span class="op">:]([:</span>p<sub>0</sub><span class="op">:]</span>, <span class="op">[:</span>p<sub>1</sub><span class="op">:]</span>, <span class="op">...</span>, <span class="op">[:</span>p<sub>n</sub><span class="op">:])</span></span></code></pre></div>
</blockquote>
</div>
<p>But the tricky part is that we can’t ask for the parameters of the
function we’re cloning (i.e. <code class="sourceCode cpp">fun</code> in
the loop above - which is a reflection of a non-static member function
of <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>),
we have to ask for the parameters of the function that we’re
<em>currently</em> defining. Which we haven’t defined yet so we can’t
reflect on it.</p>
<p>But we could split this in pieces and ask
<code class="sourceCode cpp">inject</code> to give us back a reflection
of what it injected, since <code class="sourceCode cpp">inject</code>
must operate on full token boundaries.</p>
<p>So that might be:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> LoggingVector <span class="op">{</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> impl;</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>    LoggingVector<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">:</span> impl<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun <span class="op">:</span> <span class="co">/* public, non-special member functions */</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a>            <span class="co">// note that this one doesn&#39;t even require a token sequence</span></span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> log_fun <span class="op">=</span> inject<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span>;</span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> argument_list <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb49-14"><a href="#cb49-14" aria-hidden="true" tabindex="-1"></a>            <span class="dt">bool</span> first <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb49-15"><a href="#cb49-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> param <span class="op">:</span> parameters_of<span class="op">(</span>log_fun<span class="op">))</span> <span class="op">{</span> <span class="co">// &lt;== NB, not fun</span></span>
<span id="cb49-16"><a href="#cb49-16" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-17"><a href="#cb49-17" aria-hidden="true" tabindex="-1"></a>                    argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span> , <span class="op">}</span>;</span>
<span id="cb49-18"><a href="#cb49-18" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb49-19"><a href="#cb49-19" aria-hidden="true" tabindex="-1"></a>                first <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb49-20"><a href="#cb49-20" aria-hidden="true" tabindex="-1"></a>                argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb49-21"><a href="#cb49-21" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">static_cast</span><span class="op">&lt;[:</span><span class="er">$</span>eval<span class="op">(</span>type_of<span class="op">(</span>param<span class="op">)):]&amp;&amp;&gt;([:</span> <span class="er">$</span>eval<span class="op">(</span>param<span class="op">)</span> <span class="op">:])</span></span>
<span id="cb49-22"><a href="#cb49-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span>;</span>
<span id="cb49-23"><a href="#cb49-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb49-24"><a href="#cb49-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-25"><a href="#cb49-25" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb49-26"><a href="#cb49-26" aria-hidden="true" tabindex="-1"></a>                declare <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span> <span class="op">:]</span> <span class="op">{</span></span>
<span id="cb49-27"><a href="#cb49-27" aria-hidden="true" tabindex="-1"></a>                    std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="er">$</span>eval<span class="op">(</span>name_of<span class="op">(</span>fun<span class="op">)))</span>;</span>
<span id="cb49-28"><a href="#cb49-28" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> impl<span class="op">.[:</span> <span class="er">$</span>eval<span class="op">(</span>fun<span class="op">)</span> <span class="op">:](</span> <span class="er">$</span>eval<span class="op">(</span>argument_list<span class="op">)</span> <span class="op">)</span>;</span>
<span id="cb49-29"><a href="#cb49-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb49-30"><a href="#cb49-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb49-31"><a href="#cb49-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb49-32"><a href="#cb49-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb49-33"><a href="#cb49-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The <code class="sourceCode cpp">argument_list</code> is simply
building up the token sequence <code class="sourceCode cpp"><span class="op">[:</span> p<sub>0</sub> <span class="op">:]</span>, <span class="op">[:</span> p<sub>1</sub> <span class="op">:]</span>, <span class="op">...</span>, <span class="op">[:</span> p<sub>N</sub> <span class="op">:]</span></code>
for each parameter (except forwarded). There is no name lookup going on,
no checking of fragment correctness. Just building up the right
tokens.</p>
<p>Once we have those tokens, we can concatenate this token sequence
using the same <code class="sourceCode cpp"><span class="er">$</span>eval<span class="op">()</span></code>
quoting operator that we’ve used for other problems and we’re done.
Token sequences are just a sequence of tokens - so we simply need to be
able to produce that sequence.</p>
<p>Note that we didn’t actually have to implement it using a separate
<code class="sourceCode cpp">argument_list</code> local variable - we
could’ve concatenated the entire token sequence piecewise. But this
structure allows factoring out parameter-forwarding into its own
function:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> forward_parameters<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> argument_list <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> first <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> param <span class="op">:</span> parameters_of<span class="op">(</span>fun<span class="op">))</span> <span class="op">{</span></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a>            argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span> , <span class="op">}</span>;</span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a>        first <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb50-9"><a href="#cb50-9" aria-hidden="true" tabindex="-1"></a>        argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb50-10"><a href="#cb50-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">static_cast</span><span class="op">&lt;[:</span><span class="er">$</span>eval<span class="op">(</span>type_of<span class="op">(</span>param<span class="op">)):]&amp;&amp;&gt;([:</span> <span class="er">$</span>eval<span class="op">(</span>param<span class="op">)</span> <span class="op">:])</span></span>
<span id="cb50-11"><a href="#cb50-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>;</span>
<span id="cb50-12"><a href="#cb50-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb50-13"><a href="#cb50-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> argument_list;</span>
<span id="cb50-14"><a href="#cb50-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>And then:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun <span class="op">:</span> <span class="co">/* public, non-special member functions */</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> log_fun <span class="op">=</span> inject<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span>;</span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>        inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>            declare <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>decl_of<span class="op">(</span>fun<span class="op">))</span> <span class="op">:]</span> <span class="op">{</span></span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>                std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="er">$</span>eval<span class="op">(</span>name_of<span class="op">(</span>fun<span class="op">)))</span>;</span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> impl<span class="op">.[:</span> <span class="er">$</span>eval<span class="op">(</span>fun<span class="op">)</span> <span class="op">:](</span> <span class="er">$</span>eval<span class="op">(</span>forward_parameters<span class="op">(</span>log_fun<span class="op">))</span> <span class="op">)</span>;</span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb51-10"><a href="#cb51-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">})</span>;</span>
<span id="cb51-11"><a href="#cb51-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb51-12"><a href="#cb51-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h3 data-number="3.4.2" id="introducing-parameter-names"><span class="header-section-number">3.4.2</span> Introducing Parameter Names<a href="#introducing-parameter-names" class="self-link"></a></h3>
<p>We said we have the problem that the functions we’re cloning might
not have parameter names. So what? We’re creating a new function, we can
pick our names!</p>
<p>Perhaps that looks like an extra argument to
<code class="sourceCode cpp">decl_of</code> that gives us a prefix for
each parameter name. So <code class="sourceCode cpp">decl_of<span class="op">(</span>fun, <span class="st">&quot;p&quot;</span><span class="op">)</span></code>
would give us parameter names of <code class="sourceCode cpp">p0</code>,
<code class="sourceCode cpp">p1</code>, and so forth. That gives us a
similar looking solution, but now we never need the reflection of the
new function - just the old one:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> LoggingVector <span class="op">{</span></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> impl;</span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>    LoggingVector<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">:</span> impl<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb52-9"><a href="#cb52-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info fun <span class="op">:</span> <span class="co">/* public, non-special member functions */</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-10"><a href="#cb52-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> argument_list <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb52-11"><a href="#cb52-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">!=</span> parameters_of<span class="op">(</span>fun<span class="op">).</span>size<span class="op">()</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-12"><a href="#cb52-12" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>i <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-13"><a href="#cb52-13" aria-hidden="true" tabindex="-1"></a>                    argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span> , <span class="op">}</span>;</span>
<span id="cb52-14"><a href="#cb52-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb52-15"><a href="#cb52-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-16"><a href="#cb52-16" aria-hidden="true" tabindex="-1"></a>                argument_list <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb52-17"><a href="#cb52-17" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// we could get the nth parameter&#39;s type (we can&#39;t splice</span></span>
<span id="cb52-18"><a href="#cb52-18" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// the other function&#39;s parameters but we CAN query them)</span></span>
<span id="cb52-19"><a href="#cb52-19" aria-hidden="true" tabindex="-1"></a>                    <span class="co">// or we could just write decltype(p0)</span></span>
<span id="cb52-20"><a href="#cb52-20" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><span class="er">$</span>id<span class="op">(</span><span class="st">&quot;p&quot;</span>, i<span class="op">))&amp;&amp;&gt;(</span><span class="er">$</span>id<span class="op">(</span><span class="st">&quot;p&quot;</span>, i<span class="op">))</span></span>
<span id="cb52-21"><a href="#cb52-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span>;</span>
<span id="cb52-22"><a href="#cb52-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb52-23"><a href="#cb52-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-24"><a href="#cb52-24" aria-hidden="true" tabindex="-1"></a>            inject<span class="op">(@</span>tokens <span class="op">{</span></span>
<span id="cb52-25"><a href="#cb52-25" aria-hidden="true" tabindex="-1"></a>                declare <span class="op">[:</span> <span class="er">$</span>eval<span class="op">(</span>decl_of<span class="op">(</span>fun, <span class="st">&quot;p&quot;</span><span class="op">))</span> <span class="op">:]</span> <span class="op">{</span></span>
<span id="cb52-26"><a href="#cb52-26" aria-hidden="true" tabindex="-1"></a>                    std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="er">$</span>eval<span class="op">(</span>name_of<span class="op">(</span>fun<span class="op">)))</span>;</span>
<span id="cb52-27"><a href="#cb52-27" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> impl<span class="op">.[:</span> <span class="er">$</span>eval<span class="op">(</span>fun<span class="op">)</span> <span class="op">:](</span> <span class="er">$</span>eval<span class="op">(</span>argument_list<span class="op">)</span> <span class="op">)</span>;</span>
<span id="cb52-28"><a href="#cb52-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb52-29"><a href="#cb52-29" aria-hidden="true" tabindex="-1"></a>            <span class="op">})</span>;</span>
<span id="cb52-30"><a href="#cb52-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-31"><a href="#cb52-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb52-32"><a href="#cb52-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This approach is arguably simpler.</p>
<h2 data-number="3.5" id="logging-vector-ii-cloning-with-modifications"><span class="header-section-number">3.5</span> Logging Vector II: Cloning with
Modifications<a href="#logging-vector-ii-cloning-with-modifications" class="self-link"></a></h2>
<p>However, we’ve still got some work to do. The above implementation
already gets us a great deal of functionality, and should create code
that looks something like this:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> LoggingVector <span class="op">{</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> impl;</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>    LoggingVector<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> v<span class="op">)</span> <span class="op">:</span> impl<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> clear<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="st">&quot;clear&quot;</span><span class="op">)</span>;</span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> impl<span class="op">.</span>clear<span class="op">()</span>;</span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb53-12"><a href="#cb53-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-13"><a href="#cb53-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> push_back<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> value<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb53-14"><a href="#cb53-14" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="st">&quot;push_back&quot;</span><span class="op">)</span>;</span>
<span id="cb53-15"><a href="#cb53-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> impl<span class="op">.</span>push_back<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T <span class="kw">const</span><span class="op">&amp;&gt;(</span>value<span class="op">))</span>;</span>
<span id="cb53-16"><a href="#cb53-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb53-17"><a href="#cb53-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-18"><a href="#cb53-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> push_back<span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb53-19"><a href="#cb53-19" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="st">&quot;push_back&quot;</span><span class="op">)</span>;</span>
<span id="cb53-20"><a href="#cb53-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> impl<span class="op">.</span>push_back<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">&amp;&amp;&gt;(</span>value<span class="op">))</span>;</span>
<span id="cb53-21"><a href="#cb53-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb53-22"><a href="#cb53-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-23"><a href="#cb53-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb53-24"><a href="#cb53-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>For a lot of <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="ch">&#39;</span></code>s
member functions, we’re done. But some need some more work. One of the
functions we’re emitting is member
<code class="sourceCode cpp">swap</code>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> LoggingVector <span class="op">{</span></span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span> impl;</span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> swap<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> other<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><span class="co">/* ... */</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb54-9"><a href="#cb54-9" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="st">&quot;swap&quot;</span><span class="op">)</span>;</span>
<span id="cb54-10"><a href="#cb54-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> impl<span class="op">.</span>swap<span class="op">(</span>other<span class="op">)</span>; <span class="co">// &lt;== omitting the cast here for readability</span></span>
<span id="cb54-11"><a href="#cb54-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb54-12"><a href="#cb54-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-13"><a href="#cb54-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb54-14"><a href="#cb54-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But this… isn’t right. Or rather, it could potentially be right in
some design, but it’s not what we want to do. We don’t want <code class="sourceCode cpp">LoggingVector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
to be swappable with <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>…
we want it to be swappable with itself. What we actually want to do is
emit this:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> swap<span class="op">(</span>LoggingVector<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> other<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><span class="co">/* ... */</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;Calling {}&quot;</span>, <span class="st">&quot;swap&quot;</span><span class="op">)</span>;</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> impl<span class="op">.</span>swap<span class="op">(</span>other<span class="op">.</span>impl<span class="op">)</span>;</span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Two changes here: the parameter needs to change from <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span></code>
to <code class="sourceCode cpp">LoggingVector<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span></code>,
and then in the call-forwarding we need to forward not
<code class="sourceCode cpp">other</code> (which is now the wrong type)
but rather
<code class="sourceCode cpp">other<span class="op">.</span>impl</code>.
How can we do that? We don’t quite have a good answer yet. But this is
much farther than we’ve come with any other design.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="hygienic-macros"><span class="header-section-number">4</span>
Hygienic Macros<a href="#hygienic-macros" class="self-link"></a></h1>
<p>C macros have a (well-deserved) bad reputation in the C++ community.
This is because they have some intractable problems:</p>
<ul>
<li>C macros don’t follow any scoping rules, and can change any code,
anywhere. This is why they do not leak into or out of C++ modules.</li>
<li>The C preprocessor is a language unto itself, that doesn’t
understand C++ syntax, with limited functionality that is very tedious
to program in.</li>
</ul>
<p>We think that C++ does need a code manipulation mechanism, and that
token sequences can provide a much better solution than C macros.</p>
<h2 data-number="4.1" id="forwarding"><span class="header-section-number">4.1</span> Forwarding<a href="#forwarding" class="self-link"></a></h2>
<p>Consider the problem of forwarding. Forwarding an argument in C++, in
the vast majority of uses, looks like <code class="sourceCode cpp">std<span class="op">::</span>forward<span class="op">&lt;</span>T<span class="op">&gt;(</span>t<span class="op">)</span></code>,
where <code class="sourceCode cpp">T</code> is actually the type <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>t<span class="op">)</span></code>.
This is annoying to have to write, the operation is simply forwarding an
argument but we need to provide two names anyway, and also has the
downside of having to instantiate a function template (although
compilers are moving towards making that a builtin).</p>
<p>Barry at some point proposed a specific language feature for this
use-case (<span class="citation" data-cites="P0644R1">[<a href="https://wg21.link/p0644r1" role="doc-biblioref">P0644R1</a>]</span>). Later, there was a proposal
for a hygienic macro system <span class="citation" data-cites="P1221R1">[<a href="https://wg21.link/p1221r1" role="doc-biblioref">P1221R1</a>]</span> in which forwarding would be
implemented like this:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> fwd<span class="op">(</span><span class="kw">using</span> <span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">)&amp;&amp;&gt;(</span>x<span class="op">)</span>;</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> old_f <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{</span> <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">)&gt;(</span>x<span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> new_f <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> fwd<span class="op">(</span>x<span class="op">)</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>With token sequences, we can achieve similar syntax:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> fwd2<span class="op">(@</span>tokens x<span class="op">)</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span><span class="er">$</span>eval<span class="op">(</span>x<span class="op">))&amp;&amp;&gt;(</span><span class="er">$</span>eval<span class="op">(</span>x<span class="op">))</span>;</span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> new_f2 <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> fwd2<span class="op">!(</span>x<span class="op">)</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The logic here is that <code class="sourceCode cpp">fwd2<span class="op">!(</span>x<span class="op">)</span></code>
is syntactic sugar for <code class="sourceCode cpp">inject<span class="op">(</span>fwd2<span class="op">(@</span>tokens <span class="op">{</span> x <span class="op">}))</span></code>.
We’re taking a page out of Rust’s book and suggesting that invoking a
“macro” with an exclamation point does the injection. Seems nice to both
have convenient syntax for token manipulation and a syntactic marker for
it on the call-site.</p>
<p>We would have to figure out what we would want <code class="sourceCode cpp">fwd2<span class="op">!(</span>std<span class="op">::</span>pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">})</span></code>
to do. One of the issues of C macros is not understand C++ token syntax,
so this argument would have to be parenthesized. But if we want to
operate on the token level, this seems like a given.</p>
<p>Of course, <code class="sourceCode cpp">fwd2</code> is a regular C++
function. You have to invoke it through the usual C++ scoping rules, so
it does not suffer that problem from C macros. And then the body is a
regular C++ function too, so writing complex token manipulation is just
a matter of writing complex C++ code - which is a lot easier than
writing complex C preprocessor code.</p>
<h2 data-number="4.2" id="assertion"><span class="header-section-number">4.2</span> Assertion<a href="#assertion" class="self-link"></a></h2>
<p>Consider a different example (borrowed from <a href="https://www.forrestthewoods.com/blog/learning-jai-via-advent-of-code/">here</a>):</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> assert_eq<span class="op">(@</span>tokens a,</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a>                         <span class="op">@</span>tokens b<span class="op">)</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">do</span> <span class="op">{</span></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> sa <span class="op">=</span> <span class="er">$</span>eval<span class="op">(</span>stringify<span class="op">(</span>a<span class="op">))</span>;</span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> va <span class="op">=</span> <span class="er">$</span>eval<span class="op">(</span>a<span class="op">)</span>;</span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> sb <span class="op">=</span> <span class="er">$</span>eval<span class="op">(</span>stringify<span class="op">(</span>b<span class="op">))</span>;</span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a>            <span class="kw">auto</span> vb <span class="op">=</span> <span class="er">$</span>eval<span class="op">(</span>b<span class="op">)</span>;</span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> <span class="op">(</span>va <span class="op">==</span> vb<span class="op">))</span> <span class="op">{</span></span>
<span id="cb58-12"><a href="#cb58-12" aria-hidden="true" tabindex="-1"></a>                std<span class="op">::</span>println<span class="op">(</span></span>
<span id="cb58-13"><a href="#cb58-13" aria-hidden="true" tabindex="-1"></a>                    stderr,</span>
<span id="cb58-14"><a href="#cb58-14" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;{} ({}) == {} ({}) failed at {}&quot;</span>,</span>
<span id="cb58-15"><a href="#cb58-15" aria-hidden="true" tabindex="-1"></a>                    sa, va,</span>
<span id="cb58-16"><a href="#cb58-16" aria-hidden="true" tabindex="-1"></a>                    sb, vb,</span>
<span id="cb58-17"><a href="#cb58-17" aria-hidden="true" tabindex="-1"></a>                    <span class="er">$</span>eval<span class="op">(</span>source_location_of<span class="op">(</span>a<span class="op">)))</span>;</span>
<span id="cb58-18"><a href="#cb58-18" aria-hidden="true" tabindex="-1"></a>                std<span class="op">::</span>abort<span class="op">()</span>;</span>
<span id="cb58-19"><a href="#cb58-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb58-20"><a href="#cb58-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">while</span> <span class="op">(</span><span class="kw">false</span><span class="op">)</span>;</span>
<span id="cb58-21"><a href="#cb58-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb58-22"><a href="#cb58-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>With the expectation that:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Written Code</strong>
</div></th>
<th><div style="text-align:center">
<strong>Injected Code</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a>assert_eq<span class="op">!(</span><span class="dv">42</span>, factorial<span class="op">(</span><span class="dv">3</span><span class="op">))</span>;</span></code></pre></div>

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

<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> sa <span class="op">=</span> <span class="st">&quot;42&quot;</span>;</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> va <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> sb <span class="op">=</span> <span class="st">&quot;factorial(3)&quot;</span>;</span>
<span id="cb60-6"><a href="#cb60-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> vb <span class="op">=</span> factorial<span class="op">(</span><span class="dv">3</span><span class="op">)</span>;</span>
<span id="cb60-7"><a href="#cb60-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb60-8"><a href="#cb60-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> <span class="op">(</span>va <span class="op">==</span> vb<span class="op">))</span> <span class="op">{</span></span>
<span id="cb60-9"><a href="#cb60-9" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>println<span class="op">(</span></span>
<span id="cb60-10"><a href="#cb60-10" aria-hidden="true" tabindex="-1"></a>            stderr,</span>
<span id="cb60-11"><a href="#cb60-11" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;{} ({}) == {} ({}) failed at {}&quot;</span>,</span>
<span id="cb60-12"><a href="#cb60-12" aria-hidden="true" tabindex="-1"></a>            sa, va,</span>
<span id="cb60-13"><a href="#cb60-13" aria-hidden="true" tabindex="-1"></a>            sb, vb,</span>
<span id="cb60-14"><a href="#cb60-14" aria-hidden="true" tabindex="-1"></a>            <span class="co">/* some source location */</span><span class="op">)</span>;</span>
<span id="cb60-15"><a href="#cb60-15" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>abort<span class="op">()</span>;</span>
<span id="cb60-16"><a href="#cb60-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb60-17"><a href="#cb60-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">while</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>You can write this as a regular C macro today, but we bet it’s a
little nicer to read using this language facility.</p>
<p>Note that this still suffers from at least one C macro problem:
naming. If instead of <code class="sourceCode cpp">assert_eq<span class="op">!(</span><span class="dv">42</span>, factorial<span class="op">(</span><span class="dv">3</span><span class="op">))</span></code>
we wrote <code class="sourceCode cpp">assert_eq<span class="op">!(</span><span class="dv">42</span>, sa <span class="op">*</span> <span class="dv">2</span><span class="op">)</span></code>,
then this would not compile - because name lookup in the
<code class="sourceCode cpp"><span class="cf">do</span></code>-<code class="sourceCode cpp"><span class="cf">while</span></code>
loop would end up finding the local variable
<code class="sourceCode cpp">sa</code> declared by the macro. So care
would have to be taken in all of these cases (otherwise we would have to
come up with a way to introduce unique names).</p>
<h2 data-number="4.3" id="string-interpolation"><span class="header-section-number">4.3</span> String Interpolation<a href="#string-interpolation" class="self-link"></a></h2>
<p>Many programming languages support string interpolation. The ability
to write something like <code class="sourceCode cpp">format<span class="op">!(</span><span class="st">&quot;x={x}&quot;</span><span class="op">)</span></code>
instead of <code class="sourceCode cpp">format<span class="op">(</span><span class="st">&quot;x={}&quot;</span>, x<span class="op">)</span></code>.
It’s a pretty significant feature when it comes to the ergonomics of
formatting.</p>
<p>We can write it as a library:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a><span class="co">// the actual parsing isn&#39;t interesting here.</span></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a><span class="co">// the goal is to take a string like &quot;x={this-&gt;x:02} y={this-&gt;y:02}&quot;</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="co">// and return {.format_str=&quot;x={:02} y={:02}&quot;, .args={&quot;this-&gt;x&quot;, &quot;this-&gt;y&quot;}}</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FormatParts <span class="op">{</span></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>    string_view format_str;</span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>    vector<span class="op">&lt;</span>string_view<span class="op">&gt;</span> args;</span>
<span id="cb61-8"><a href="#cb61-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb61-9"><a href="#cb61-9" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> parse_format_string<span class="op">(</span>string_view<span class="op">)</span> <span class="op">-&gt;</span> FormatParts;</span>
<span id="cb61-10"><a href="#cb61-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-11"><a href="#cb61-11" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> format<span class="op">(</span>string_view str<span class="op">)</span> <span class="op">-&gt;</span> meta<span class="op">::</span>info <span class="op">{</span></span>
<span id="cb61-12"><a href="#cb61-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> parts <span class="op">=</span> parse_format_string<span class="op">(</span>str<span class="op">)</span>;</span>
<span id="cb61-13"><a href="#cb61-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-14"><a href="#cb61-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> tok <span class="op">=</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb61-15"><a href="#cb61-15" aria-hidden="true" tabindex="-1"></a>        <span class="co">// NB: there&#39;s no close paren yet</span></span>
<span id="cb61-16"><a href="#cb61-16" aria-hidden="true" tabindex="-1"></a>        <span class="co">// we&#39;re allowed to build up a partial fragment like this</span></span>
<span id="cb61-17"><a href="#cb61-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">::</span>std<span class="op">::</span>format<span class="op">(</span><span class="er">$</span>eval<span class="op">(</span>parts<span class="op">.</span>format_str<span class="op">)</span></span>
<span id="cb61-18"><a href="#cb61-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb61-19"><a href="#cb61-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-20"><a href="#cb61-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>string_view arg <span class="op">:</span> parts<span class="op">.</span>args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb61-21"><a href="#cb61-21" aria-hidden="true" tabindex="-1"></a>        tok <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span> , <span class="er">$</span>eval<span class="op">(</span>tokenize<span class="op">(</span>arg<span class="op">))</span> <span class="op">}</span>;</span>
<span id="cb61-22"><a href="#cb61-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb61-23"><a href="#cb61-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-24"><a href="#cb61-24" aria-hidden="true" tabindex="-1"></a>    tok <span class="op">+=</span> <span class="op">@</span>tokens <span class="op">{</span> <span class="op">)</span> <span class="op">}</span>;</span>
<span id="cb61-25"><a href="#cb61-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> tok;</span>
<span id="cb61-26"><a href="#cb61-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>In the previous example, we demonstrated the need for a way to
convert a token sequence to a string. In this example, we need a way to
convert a string to a token sequence. This doesn’t involve parsing or
any semantic analysis. It’s <em>just</em> lexing.</p>
<p>Of course, this approach has limitations. We cannot fully faithfully
parse the format string because at this layer we don’t have types - we
can’t stop and look up what type <code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;</span>x</code>
was, instantiate the appropriate <code class="sourceCode cpp">std<span class="op">::</span>formatter<span class="op">&lt;</span>X<span class="op">&gt;</span></code>
and use it tell us where the end of its formatter is. We can just count
balanced <code class="sourceCode cpp"><span class="op">{}</span></code>s
and hope for the best.</p>
<p>Similarly, something like <code class="sourceCode cpp">format<span class="op">!(</span><span class="st">&quot;{SOME_MACRO(x)}&quot;</span><span class="op">)</span></code>
can’t work since we’re not going to rerun the preprocessor during
tokenization. But I doubt anybody would even expect that to work.</p>
<p>But realistically, this would handily cover the 90%, if not the 99%
case. Not to mention could easily adopt other nice features of string
interpolation that show up in other languages (like Python’s
<code class="sourceCode cpp">f<span class="st">&quot;{x =}</span></code>
which formats as <code class="sourceCode cpp"><span class="st">&quot;x = 42&quot;</span></code>)
as library features. And, importantly, this isn’t a language feature
tied to
<code class="sourceCode cpp">std<span class="op">::</span>format</code>.
It could easily be made into a library to be used by any logging
framework.</p>
<h2 data-number="4.4" id="control-flow-operator"><span class="header-section-number">4.4</span> Control Flow Operator<a href="#control-flow-operator" class="self-link"></a></h2>
<p>A simpler example would be the control flow operator <span class="citation" data-cites="P2561R2">[<a href="https://wg21.link/p2561r2" role="doc-biblioref">P2561R2</a>]</span>. Many people already use a
macro for this. A hygienic macro would be that much better:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> try_<span class="op">(@</span>tokens expr<span class="op">)</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">@</span>tokens <span class="op">{</span></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">do</span> <span class="op">{</span></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> _f <span class="op">=</span> <span class="er">$</span>eval<span class="op">(</span>expr<span class="op">)</span>;</span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">using</span> _R <span class="op">=</span> <span class="op">[:</span>return_type<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>current_function<span class="op">()):]</span>;</span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a>            <span class="kw">using</span> _TraitsR <span class="op">=</span> try_traits<span class="op">&lt;</span>_R<span class="op">&gt;</span>;</span>
<span id="cb62-8"><a href="#cb62-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">using</span> _TraitsF <span class="op">=</span> try_traits<span class="op">&lt;[:</span>type_remove_cvref<span class="op">(</span>type_of<span class="op">(^</span>_f<span class="op">)):]&gt;</span>;</span>
<span id="cb62-9"><a href="#cb62-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-10"><a href="#cb62-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> _TraitsF<span class="op">::</span>should_continue<span class="op">(</span>_f<span class="op">))</span> <span class="op">{</span></span>
<span id="cb62-11"><a href="#cb62-11" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> _TraitsR<span class="op">::</span>from_break<span class="op">(</span>_TraitsF<span class="op">::</span>extract_break<span class="op">(</span>forward<span class="op">!(</span>_f<span class="op">)))</span>;</span>
<span id="cb62-12"><a href="#cb62-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb62-13"><a href="#cb62-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-14"><a href="#cb62-14" aria-hidden="true" tabindex="-1"></a>            <span class="kw">do_return</span> _TraitsF<span class="op">::</span>extract_continue<span class="op">(</span>forward<span class="op">!(</span>_f<span class="op">))</span>;</span>
<span id="cb62-15"><a href="#cb62-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>;</span>
<span id="cb62-16"><a href="#cb62-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb62-17"><a href="#cb62-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This relies on
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions <span class="citation" data-cites="P2806R2">[<a href="https://wg21.link/p2806r2" role="doc-biblioref">P2806R2</a>]</span> to give us something to
inject.</p>
<h2 data-number="4.5" id="alternate-syntax"><span class="header-section-number">4.5</span> Alternate Syntax<a href="#alternate-syntax" class="self-link"></a></h2>
<p>We have two forms of injection in this paper:</p>
<ul>
<li>a metafunction <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>inject</code>
that takes an <code class="sourceCode cpp">info</code> (and maybe also
returns an <code class="sourceCode cpp">info</code>), used through <a href="#token-sequences">token sequences</a>.</li>
<li>a trailing
<code class="sourceCode cpp"><span class="op">!</span></code> used
throughout <a href="#hygienic-macros">hygienic macros</a>.</li>
</ul>
<p>But these really are the exact same thing - both are requests to take
an <code class="sourceCode cpp">info</code> and inject it in the current
context. The bigger token sequence injection doesn’t really have any
particular reason to require terse syntax. Prior papers did use some
punctuation marks
(e.g. <code class="sourceCode cpp"><span class="op">-&gt;</span></code>,
<code class="sourceCode cpp"><span class="op">&lt;&lt;</span></code>),
but a named function seems better. But the macros <em>really</em> do
want to have terse invocation syntax. Having to write <code class="sourceCode cpp">inject<span class="op">(</span>forward<span class="op">(</span>x<span class="op">))</span></code>
somewhat defeats the purpose and nobody would write it.</p>
<p>Using one of the arrows for the macro use-case is weird, so one
option might be prefix
<code class="sourceCode cpp"><span class="op">@</span></code>. As in
<code class="sourceCode cpp"><span class="op">@</span>forward<span class="op">(</span>x<span class="op">)</span></code>,
<code class="sourceCode cpp"><span class="op">@</span>assert_eq<span class="op">(</span>a, b<span class="op">)</span></code>,
and <code class="sourceCode cpp"><span class="op">@</span>format<span class="op">(</span><span class="st">&quot;x={this-&gt;x}&quot;</span><span class="op">)</span></code>.
This would mean that <code class="sourceCode cpp"><span class="op">@</span>tokens <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></code>
would need a different spelling, perhaps simply <code class="sourceCode cpp"><span class="op">^{</span> <span class="op">...</span> <span class="op">}</span></code>.</p>
<p>Or we could stick with two syntaxes - the longer one for the bigger
reflection cases where terseness is arguably bad, and the short one for
the macro use case where terseness is essential.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">5</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>We propose a code injection mechanism using token sequences.</p>
<p>The fragment model initially introduced in <span class="citation" data-cites="P1717R0">[<a href="https://wg21.link/p1717r0" role="doc-biblioref">P1717R0</a>]</span> is great for allowing writing
code-to-be-injected to actually look like regular C++ code, which has
the benefit of being both familiar and being already recognizable to
tools like syntax highlighters. But the early checking adds complexity
to the model and the implementation which makes it harder to use and
limits its usefulness. Hence, we propose raw token sequences that are
unparsed until the point of injection.</p>
<p>This proposal consists of several pieces:</p>
<ul>
<li>a mechanism to introduce a token sequence (in this paper <code class="sourceCode cpp"><span class="op">@</span>tokens <span class="op">{</span> <em>balanced-brace-tokens</em> <span class="op">}</span></code>)</li>
<li>two interpolators to add outside context to a token sequence, one
for identifiers
(<code class="sourceCode cpp"><span class="er">$</span>id</code>) and
one for values
(<code class="sourceCode cpp"><span class="er">$</span>eval</code>)</li>
<li>a new disambiguator for splicing a declaration (<code class="sourceCode cpp">declare <span class="op">[:</span> fun <span class="op">:]</span></code>)</li>
<li>a new metafunction to inject a token sequence (<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>inject</code>)</li>
<li>new metaprogramming facilities for dealing with token sequences:
<ul>
<li>concatenation</li>
<li>converting a string to a token sequence and a token sequence to a
string</li>
<li>splitting a token sequence into a range of tokens</li>
</ul></li>
<li>hygienic macros would benefit syntactically from:
<ul>
<li>a mechanism to accept a tokens sequence as a function parameter</li>
<li>a mechanism to inject a token sequence directly as returned by a
function (trailing
<code class="sourceCode cpp"><span class="op">!</span></code>)</li>
</ul></li>
</ul>
<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-P0644R1" class="csl-entry" role="doc-biblioentry">
[P0644R1] Barry Revzin. 2017-10-08. Forward without forward. <a href="https://wg21.link/p0644r1"><div class="csl-block">https://wg21.link/p0644r1</div></a>
</div>
<div id="ref-P0707R4" class="csl-entry" role="doc-biblioentry">
[P0707R4] Herb Sutter. 2019-06-17. Metaclasses: Generative C++. <a href="https://wg21.link/p0707r4"><div class="csl-block">https://wg21.link/p0707r4</div></a>
</div>
<div id="ref-P0712R0" class="csl-entry" role="doc-biblioentry">
[P0712R0] Andrew Sutton, Herb Sutter. 2017-06-18. Implementing language
support for compile-time programming. <a href="https://wg21.link/p0712r0"><div class="csl-block">https://wg21.link/p0712r0</div></a>
</div>
<div id="ref-P1221R1" class="csl-entry" role="doc-biblioentry">
[P1221R1] Jason Rice. 2018-10-03. Parametric Expressions. <a href="https://wg21.link/p1221r1"><div class="csl-block">https://wg21.link/p1221r1</div></a>
</div>
<div id="ref-P1717R0" class="csl-entry" role="doc-biblioentry">
[P1717R0] Andrew Sutton, Wyatt Childers. 2019-06-17. Compile-time
Metaprogramming in C++. <a href="https://wg21.link/p1717r0"><div class="csl-block">https://wg21.link/p1717r0</div></a>
</div>
<div id="ref-P2050R0" class="csl-entry" role="doc-biblioentry">
[P2050R0] Andrew Sutton, Wyatt Childers. 2020-01-13. Tweaks to the
design of source code fragments. <a href="https://wg21.link/p2050r0"><div class="csl-block">https://wg21.link/p2050r0</div></a>
</div>
<div id="ref-P2237R0" class="csl-entry" role="doc-biblioentry">
[P2237R0] Andrew Sutton. 2020-10-15. Metaprogramming. <a href="https://wg21.link/p2237r0"><div class="csl-block">https://wg21.link/p2237r0</div></a>
</div>
<div id="ref-P2561R2" class="csl-entry" role="doc-biblioentry">
[P2561R2] Barry Revzin. 2023-05-18. A control flow operator. <a href="https://wg21.link/p2561r2"><div class="csl-block">https://wg21.link/p2561r2</div></a>
</div>
<div id="ref-P2806R2" class="csl-entry" role="doc-biblioentry">
[P2806R2] Barry Revzin, Bruno Cardoso Lopez, Zach Laine, Michael Park.
2023-11-16. do expressions. <a href="https://wg21.link/p2806r2"><div class="csl-block">https://wg21.link/p2806r2</div></a>
</div>
<div id="ref-P2996R3" class="csl-entry" role="doc-biblioentry">
[P2996R3] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, and Dan Katz. 2024-05-16. Reflection
for C++26. <a href="https://wg21.link/p2996r3"><div class="csl-block">https://wg21.link/p2996r3</div></a>
</div>
<div id="ref-P3096R0" class="csl-entry" role="doc-biblioentry">
[P3096R0] Adam Lach, Walter Genovese. 2024-02-14. Function Parameter
Reflection in Reflection for C++26. <a href="https://wg21.link/p3096r0"><div class="csl-block">https://wg21.link/p3096r0</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>
</div>
</div>
</body>
</html>
