<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-12-04" />
  <title>Extending support for class types as non-type template
parameters</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit;
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none;
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #C9FBC9;
--diff-strongins: #acf2bd;
--diff-del: #FFC8EB;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
div.std blockquote { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
div.std.ins blockquote {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.ins > div.example {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.std div.sourceCode { background-color: inherit; margin-left: 1em; }
div.std blockquote del { text-decoration: line-through;
color: #000000; background-color: var(--diff-del);
border: none; }
code del { border: 1px solid #ECB3C7; }
span.orange {
background-color: #ffa500;
}
span.yellow {
background-color: #ffff00;
}</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />

  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Extending support for class
types as non-type template parameters</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3380R1 <a href="https://wg21.link/P3380">[Latest]</a> <a href="https://wg21.link/P3380/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-12-04</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="/cdn-cgi/l/email-protection#f5979487878cdb8790838f9c9bb59298949c99db969a98" class="email"><span class="__cf_email__" data-cfemail="d5b7b4a7a7acfba7b0a3afbcbb95b2b8b4bcb9fbb6bab8">[email&#160;protected]</span></a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">1</span> Revision
History<span></span></a></li>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">2</span> Introduction<span></span></a>
<ul>
<li><a href="#serialization" id="toc-serialization"><span class="toc-section-number">2.1</span>
Serialization<span></span></a></li>
<li><a href="#normalization" id="toc-normalization"><span class="toc-section-number">2.2</span> Normalization<span></span></a>
<ul>
<li><a href="#string-literals" id="toc-string-literals"><span class="toc-section-number">2.2.1</span> String
Literals<span></span></a></li>
</ul></li>
<li><a href="#deserialization" id="toc-deserialization"><span class="toc-section-number">2.3</span>
Deserialization<span></span></a></li>
<li><a href="#soundness" id="toc-soundness"><span class="toc-section-number">2.4</span> Soundness<span></span></a></li>
<li><a href="#original-design" id="toc-original-design"><span class="toc-section-number">2.5</span> Original
Design<span></span></a></li>
<li><a href="#a-note-on-spelling" id="toc-a-note-on-spelling"><span class="toc-section-number">2.6</span> A Note on
Spelling<span></span></a></li>
</ul></li>
<li><a href="#reflection-will-fix-it" id="toc-reflection-will-fix-it"><span class="toc-section-number">3</span> Reflection Will Fix
It<span></span></a>
<ul>
<li><a href="#proposed-usage-examples" id="toc-proposed-usage-examples"><span class="toc-section-number">3.1</span> Proposed Usage
Examples<span></span></a></li>
<li><a href="#template-argument-equivalence" id="toc-template-argument-equivalence"><span class="toc-section-number">3.2</span> Template-Argument
Equivalence<span></span></a></li>
<li><a href="#normalization-1" id="toc-normalization-1"><span class="toc-section-number">3.3</span>
Normalization<span></span></a></li>
<li><a href="#allowing-templates" id="toc-allowing-templates"><span class="toc-section-number">3.4</span> Allowing
Templates<span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">4</span> Proposal<span></span></a>
<ul>
<li><a href="#language" id="toc-language"><span class="toc-section-number">4.1</span> Language<span></span></a>
<ul>
<li><a href="#template-serialization-and-deserialization-functions" id="toc-template-serialization-and-deserialization-functions"><span class="toc-section-number">4.1.1</span> Template Serialization and
Deserialization Functions<span></span></a></li>
<li><a href="#extend-the-definition-of-structural" id="toc-extend-the-definition-of-structural"><span class="toc-section-number">4.1.2</span> Extend the definition of
structural<span></span></a></li>
<li><a href="#template-argument-normalization" id="toc-template-argument-normalization"><span class="toc-section-number">4.1.3</span> Template Argument
Normalization<span></span></a></li>
<li><a href="#update-stdmetareflect_value" id="toc-update-stdmetareflect_value"><span class="toc-section-number">4.1.4</span> Update <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">()</span></code><span></span></a></li>
<li><a href="#template-argument-equivalence-1" id="toc-template-argument-equivalence-1"><span class="toc-section-number">4.1.5</span>
Template-Argument-Equivalence<span></span></a></li>
</ul></li>
<li><a href="#library" id="toc-library"><span class="toc-section-number">4.2</span> Library<span></span></a></li>
</ul></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">5</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span>
Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>Since <span class="citation" data-cites="P3380R0">[<a href="https://wg21.link/p3380r0" role="doc-biblioref">P3380R0</a>]</span>:</p>
<ul>
<li>extended section on <a href="#normalization">normalization</a> to
talk about string literals and proposing properly handling string
literals</li>
<li>renamed the customization point from <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span></code>
to <code class="sourceCode cpp">to_meta_representation</code> and
<code class="sourceCode cpp">from_meta_representation</code></li>
<li>changed the design from returning a range of
<code class="sourceCode cpp">info</code> to accepting (de)serializer
parameters.</li>
</ul>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">2</span>
Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This paper is conceptually a follow-up to <span class="citation" data-cites="P2484R0">[<a href="https://wg21.link/p2484r0" role="doc-biblioref">P2484R0</a>]</span>, except that it’s largely a new
design, and I haven’t heard back from Richard Smith and didn’t want to
put his name on ideas I’m not sure he agrees with, despite everything in
this paper being derived from his insights.</p>
<p>Recommended reading in advance:</p>
<ul>
<li><span class="citation" data-cites="P0732R2">[<a href="https://wg21.link/p0732r2" role="doc-biblioref">P0732R2</a>]</span> first introduced class types as
non-type template parameters, based on defaulted
<code class="sourceCode cpp"><span class="op">&lt;=&gt;</span></code>.
This got later changed to be based on defaulted
<code class="sourceCode cpp"><span class="op">==</span></code>.</li>
<li><span class="citation" data-cites="P1907R0">[<a href="https://wg21.link/p1907r0" role="doc-biblioref">P1907R0</a>]</span> pointed out issues and
limitations in this approach</li>
<li><span class="citation" data-cites="P1907R1">[<a href="https://wg21.link/p1907r1" role="doc-biblioref">P1907R1</a>]</span> was a revised design based on
the concept of structural types, not equality, and was what was adopted
for C++20.</li>
<li>Davis Herring has a great StackOverflow answer <a href="https://stackoverflow.com/questions/63694879/floating-point-types-as-template-parameter-in-c20/63714924#63714924">here</a>
detailing a lot of these issues.</li>
<li><span class="citation" data-cites="P2484R0">[<a href="https://wg21.link/p2484r0" role="doc-biblioref">P2484R0</a>]</span> was an idea for C++23 to extend
support for class types as non-type template parameters to handle many
of the remaining easy cases.</li>
<li>A <a href="https://brevzin.github.io/c++/2024/08/15/cnttp/">blog
post</a> I wrote on this topic</li>
</ul>
<p>The status quo right now is that class types that have all of their
subobjects public and structural can be used as non-type template
parameters. This was an extremely useful addition to C++20, but leaves a
lot to be desired. The goal of this paper is to provide a design that
will allow all types to be usable as non-type template parameters,
provided the correct opt-in. In order to do so, I have to first
introduce three concepts: serialization, normalization, and
deserialization.</p>
<h2 data-number="2.1" id="serialization"><span class="header-section-number">2.1</span> Serialization<a href="#serialization" class="self-link"></a></h2>
<p>All the work at this point has established pretty clearly that
template argument equivalence is a serialization problem. What the
defaulted-<code class="sourceCode cpp"><span class="op">&lt;=&gt;</span></code>
design established, and then the
defaulted-<code class="sourceCode cpp"><span class="op">==</span></code>
design and the structural type design preserved, was that we need to
treat a class type as being comprised of a bunch of scalar types and
having equivalence be based on those scalars.</p>
<p>However we generalize the non-type template parameter problem to more
interesting class types is going to require a mechanism for the user to
tell the compiler how their class decomposes. Put differently: how can
the compiler serialize your class.</p>
<p>More formally, serialization takes a value
<code class="sourceCode cpp">v</code> and explodes it into some tuple of
structural types:</p>
<p><img src="data:image/png;base64,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" alt /></p>
<p>Since the resulting types have to themselves be structural, that
means they themselves can be (recursively) serialized. Regardless of
what mechanism we could use to specify serialization, the compiler can
do the recursive part itself without any user input. So in real life it
might look more like this (where the values in the right-most column are
those scalar/pointer/reference types that cannot further decompose):</p>
<p><img src="data:image/png;base64,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" alt /></p>
<p>There are many types for which default subobject-wise serialization
is actually sufficient — types like <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>string_view</code>,
<code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
etc. For such types, the problem reduces to simply coming up with the
right syntax to express that opt-in.</p>
<p>But for other types, simply serializing all the subobjects is
insufficient. We have to do a little bit more.</p>
<h2 data-number="2.2" id="normalization"><span class="header-section-number">2.2</span> Normalization<a href="#normalization" class="self-link"></a></h2>
<p>One of the examples that got brought up frequently during discussion
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> Fraction <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> num;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> denom;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Should <code class="sourceCode cpp">Fraction<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span></code>
be able to be template-argument-equivalent to <code class="sourceCode cpp">Fraction<span class="op">{</span><span class="dv">2</span>, <span class="dv">4</span><span class="op">}</span></code>?
That is, should the serialization process be allowed to also do
normalization? Maybe you want to minimize your template
instantiations?</p>
<p>I find this particular example difficult to reason about whether it
matters, but there is another that I think is more compelling (courtesy
of Richard Smith). Consider:</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">class</span> SmallString <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> data<span class="op">[</span><span class="dv">32</span><span class="op">]</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> length <span class="op">=</span> <span class="dv">0</span>; <span class="co">// always &lt;= 32</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// the usual string API here, including</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    SmallString<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> data<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> data;</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> push_back<span class="op">(</span><span class="dt">char</span> c<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="ot">assert</span><span class="op">(</span>length <span class="op">&lt;</span> <span class="dv">31</span><span class="op">)</span>;</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        data<span class="op">[</span>length<span class="op">]</span> <span class="op">=</span> c;</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>length;</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> pop_back<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>        <span class="ot">assert</span><span class="op">(</span>length <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">--</span>length;</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And add a few functions:</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>SmallString S<span class="op">&gt;</span> <span class="kw">struct</span> C <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> f<span class="op">()</span> <span class="op">-&gt;</span> SmallString <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> s <span class="op">=</span> SmallString<span class="op">()</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>push_back<span class="op">(</span><span class="ch">&#39;x&#39;</span><span class="op">)</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> s;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> g<span class="op">()</span> <span class="op">-&gt;</span> SmallString <span class="op">{</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> s <span class="op">=</span> f<span class="op">()</span>;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>push_back<span class="op">(</span><span class="ch">&#39;y&#39;</span><span class="op">)</span>;</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>pop_back<span class="op">()</span>;</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> s;</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>Now, we might consider the values returned by
<code class="sourceCode cpp">f<span class="op">()</span></code> and
<code class="sourceCode cpp">g<span class="op">()</span></code> to be
equal — they’re both strings of length 1 whose single character is
<code class="sourceCode cpp">x</code>. But they have different contents
of their <code class="sourceCode cpp">data</code> arrays. So if we do
default subobject-wise equivalence (i.e. the C++20 rule), then <code class="sourceCode cpp">C<span class="op">&lt;</span>f<span class="op">()&gt;</span></code>
and <code class="sourceCode cpp">C<span class="op">&lt;</span>g<span class="op">()&gt;</span></code>
would be different types. This is unlikely to be the desired effect.</p>
<p>If instead of subobject-wise equivalence, we instead did custom
serialization — if we only serialized the contents of <code class="sourceCode cpp">data<span class="op">[:</span>length<span class="op">]</span></code>
(such that
<code class="sourceCode cpp">f<span class="op">()</span></code> and
<code class="sourceCode cpp">g<span class="op">()</span></code>
serialize identically), then we have a different problem. Consider:</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>SmallString S<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> bad<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>S<span class="op">.</span>data<span class="op">()[</span><span class="dv">1</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;y&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">1</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>What do <code class="sourceCode cpp">bad<span class="op">&lt;</span>f<span class="op">()&gt;()</span></code>
and <code class="sourceCode cpp">bad<span class="op">&lt;</span>g<span class="op">()&gt;()</span></code>
evaluate to,
<code class="sourceCode cpp"><span class="dv">0</span></code> or
<code class="sourceCode cpp"><span class="dv">1</span></code>? Or both?
This is an ODR violation, and would be a very bad outcome that we (at
least Richard and I) desperately want to avoid.</p>
<p>So far then we have two options for
<code class="sourceCode cpp">SmallString</code>:</p>
<ol type="1">
<li>Opt-in to member-wise equivalence, which leads to two equal values
being non-equivalent.</li>
<li>Custom serialization, which can lead to ODR violations.</li>
</ol>
<p>Instead, we can do something else. Prior to serialization, we can
optionally perform an extra normalization step. In this case, first we
would normalize the representation (by setting <code class="sourceCode cpp">data<span class="op">[</span>length<span class="op">:</span><span class="dv">32</span><span class="op">]</span></code>
to <code class="sourceCode cpp"><span class="dv">0</span></code>) and
then we would serialize.</p>
<p>Visually:</p>
<p><img src="data:image/png;base64,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" alt /></p>
<p>Which would naturally recurse:</p>
<p><img src="data:image/png;base64,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IiJSJApo4rHy6uYEGDZsGACTJ0++YTWJiIi4ggKaeKxrTRRw6NmzJ3Xq1OHkyZPMmjXrRpYmIiJSJApo4rEcj3zavXt3ruPQAJ555hnA3oqWnp5+w2oTEREpCgU08WitW7cGrt3N2alTJ8LCwjh37hxff/31jSxNRESk0BTQxKNdr5sTYMSIEQBMmzaNxMTEG1KXiIhIUSigiUe73kQBxz7t27fHYrEwadKkG1WaiIhIoSmgiUdr1qwZAHv27OH8+fPX3O+ll14CYM6cORw6dOiG1CYiIlJYCmji8dq2bQvkvh6aQ+3atenXrx8AH3300Q2pS0REpLAU0MTj5aebE2D48OH4+/uzevVqtm/ffiNKExERKRQFNPF4joD2xx9/5Llf+fLlefTRRwF4//33i70uERGRwlJAE48XHh6OyWRi3759JCQk5LnvoEGDKFeuHDExMfz88883qEIREZGCUUATr9CmTRvg+t2cJpOJZ599FoAPPviACxcuFHttIiIiBaWAJl4hv+PQAPr27UuDBg1ISkrSczpFRKREUkATr3DbbbcBsHHjxnzt//rrrwMwY8YMjhw5Umx1iYiIFIYCmniFevXqUaZMGY4fP86xY8euu394eDi9e/cGYNy4ccVdnoiISIEooInXaNeuHXD92ZwOzz//PEFBQWzcuJGVK1cWZ2kiIiIFooAmXsPRzZnfgFauXDmGDh0KwPjx44utLhERkYJSQBOvUdCABjBgwABq1KjBiRMn+Oyzz4qrNBERkQJRQBOvUb16dapWrcqZM2c4cOBAvo976623APjiiy+Ii4srrvJERETyTQFNvErr1q0B2LRpU76PadmypfM5naNHjy6WukRERApCAU28SmG6OQFeeOEFypcvT0xMDLNmzSqO0kRERPJNAU28imPB2vyuh+ZgNpsZOXIkAB9//DEnT550eW0iIiL5pYAmXqVixYrUrVuXtLQ0du/eXaBj7777bjp06EB6ejpjxowppgpFRESuTwFNvE5huzkB3nzzTUwmExs2bGDBggWuLk1ERCRfFNDE6zgCWkEmCjhUqFDB2dX57rvvcuLECZfWJiIikh8KaOJ1WrZsCcDWrVsLdXzv3r3p2LEjFovF+cxOERGRG0kBTbxO2bJladSoERkZGWzbtq1Q5xg1ahShoaHs2LGDqVOnurhCERGRvCmgiVdydHNu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" alt /></p>
<p>With such a normalization step, we can get
<code class="sourceCode cpp">f<span class="op">()</span></code> and
<code class="sourceCode cpp">g<span class="op">()</span></code> to be
template-argument-equivalent in a way that avoids any ODR issues, since
now their representations are actually identical.</p>
<h3 data-number="2.2.1" id="string-literals"><span class="header-section-number">2.2.1</span> String Literals<a href="#string-literals" class="self-link"></a></h3>
<p>Another highly motivating use-case for normalization is actually
string literals. Currently, string literals are not usable as non-type
template parameters. <span class="citation" data-cites="P0424R2">[<a href="https://wg21.link/p0424r2" role="doc-biblioref">P0424R2</a>]</span> tried to address this issue,
but was dropped in favor of <span class="citation" data-cites="P0732R2">[<a href="https://wg21.link/p0732r2" role="doc-biblioref">P0732R2</a>]</span>. The latter, while a highly
useful addition to the language, technically did not solve the former
problem though.</p>
<p>The problem with string literals is that template-argument
equivalence for pointers is defined as two pointers having the same
pointer value. Which isn’t necessarily true for string literals in
different translation units.</p>
<p>But this is precisely a use-case for normalization! And the model
<span class="citation" data-cites="P0424R2">[<a href="https://wg21.link/p0424r2" role="doc-biblioref">P0424R2</a>]</span> implies basically gets us
there, it just needs to be formalized. Basically: if
<code class="sourceCode cpp">p</code> points to a string literal, or a
subobject thereof, we can first normalize it by having it instead point
to an external linkage array that is mangled with the contents of the
string. That is, this:</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">template</span> <span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span> <span class="kw">struct</span> C <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Wrapper <span class="op">{</span> <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> p; <span class="op">}</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>C<span class="op">&lt;</span><span class="st">&quot;hello&quot;</span><span class="op">&gt;</span> c1;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>C<span class="op">&lt;</span>Wrapper<span class="op">{.</span>p<span class="op">=</span><span class="st">&quot;hello&quot;</span><span class="op">}&gt;</span> c2;</span></code></pre></div>
</blockquote>
</div>
<p>Can normalize (recursively) into:</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">template</span> <span class="op">&lt;</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> V<span class="op">&gt;</span> <span class="kw">struct</span> C <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">char</span> __hello<span class="op">[]</span> <span class="op">=</span> <span class="st">&quot;hello&quot;</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>C<span class="op">&lt;</span>__hello<span class="op">&gt;</span> c1;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>C<span class="op">&lt;</span>Wrapper<span class="op">{.</span>p<span class="op">=</span>__hello<span class="op">}&gt;</span> c2;</span></code></pre></div>
</blockquote>
</div>
<p>As long as we ensure that the backing array has external storage such
that the same contents lead to the same variable (which <span class="citation" data-cites="P3491R0">[<a href="https://wg21.link/p3491r0" role="doc-biblioref">P3491R0</a>]</span> demonstrates a library
implementation of), this will actually do the right thing. We end up
with exactly what users expect, in the way that <span class="citation" data-cites="P0424R2">[<a href="https://wg21.link/p0424r2" role="doc-biblioref">P0424R2</a>]</span> hoped to achieve.</p>
<p>However, this still isn’t sufficient…</p>
<h2 data-number="2.3" id="deserialization"><span class="header-section-number">2.3</span> Deserialization<a href="#deserialization" class="self-link"></a></h2>
<p>Consider <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.
One possible representation of this is:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> vector <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    T<span class="op">*</span> begin_;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size_;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> capacity_;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>For our purposes it doesn’t matter if
<code class="sourceCode cpp"><span class="dt">size_t</span></code> and
<code class="sourceCode cpp">capacity_</code> are themselves
<code class="sourceCode cpp"><span class="dt">size_t</span></code> or
<code class="sourceCode cpp">T<span class="op">*</span></code>, so I’m
picking the simpler one to reason about.</p>
<p>The template-argument-equivalence rule for pointers is that two
pointers are equivalent if they have the same pointer value. That’s not
what we want for comparing two <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>s
though, we want to compare the contents. In order for the default,
subobject-wise equivalence to work in this case, we’d have to normalize
the pointers to be <em>identical</em>. For <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
specifically, this is potentially feasible using a <code class="sourceCode cpp">std<span class="op">::</span>define_static_array</code>
function (<span class="citation" data-cites="P3491R0">[<a href="https://wg21.link/p3491r0" role="doc-biblioref">P3491R0</a>]</span>). But that’s not going to help
us with
<code class="sourceCode cpp">std<span class="op">::</span>map</code>,
<code class="sourceCode cpp">std<span class="op">::</span>list</code>,
or any other container.</p>
<p>For <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
we really need to serialize a variable-length sequence of
<code class="sourceCode cpp">T</code>s.</p>
<p>As we already saw in the previous section, custom serialization (by
which I mean serialization that isn’t simply serializing every
subobject) can lead to ODR violations if two different objects serialize
the same.</p>
<p>This is where deserialization comes in. We say that the template
argument value that the user sees in code is the result of first
serializing the value, and then passing that serialized state back into
the class to construct a new value. Whatever the resulting value that we
get out of deserialization, that is <em>reliably</em> the value of the
template argument for all values of the original type that compare
template-argument-equivalent to each other. We don’t have to worry about
which of a bunch of possible specializations is chosen by the
compiler/linker.</p>
<p>Deserialization actually implicitly does normalization — the
roundtrip of a value through (de)serialization is normalized. But while
ODR problems can be avoided by careful use of normalization, ODR
problems are avoided entirely by construction if we require
deserialization. That’s pretty appealing. And the process can have some
added checks too! The compiler can perform one extra serialization step
to ensure that:</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>serialize<span class="op">(</span>deserialize<span class="op">(</span>serialize<span class="op">(</span>v<span class="op">)))</span> <span class="op">===</span> serialize<span class="op">(</span>v<span class="op">)</span></span></code></pre></div>
</blockquote>
</div>
<p>This check ensures that the round-trip is sound by construction.</p>
<p>In the same way that serialization converts a value into a tuple of
structural types, deserialization starts with that tuple of structural
types and produces a possibly-new value of the original type:</p>
<p><img src="data:image/png;base64,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" alt /></p>
<p>And in the same way that serialization works recursively in a way
that the compiler can take care of for you, deserialization could too.
And it’s important that it work like this for the same reason. So a more
complex diagram might be:</p>
<p><img src="data:image/png;base64,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kfpbvtw6+uPVKW4+N6UCl6ZVAgMDSU9Px2azmY4kIiJSJwUF0KkT2O1QVmY6jef45AhH+/btiYuL4/z582zevNl0HBERkTpzj26MGWM2h6f5ZOGAS9Mq6937wIqIiPigplI4fHJKBaC4uJjExETA2nm0VatWhhOJiIj8MCUl0KaNdV5WZk2r+CufHeFwOBz0798fgIyMDMNpREREfjj3VubDh/t32QAfLhwAI769u80q924pIiIiPqSpTKeAD0+pAJw/f57ExERcLhcrV64kNDTUdCQREZFaKS+HG26wjl99BddfbzqRZ/n0CEdgYGDVKMdK97iUiIiID1i50iobQ4f6f9kAHy8cAKNGjQI0rSIiIr5lyRLr+PDDZnM0Fp8vHL169SI8PJwzZ87oDrIiIuITSkouLRj1591Fq/P5wgEw5tvVNhrlEBERX7BsmXUcMaJpTKeAnxQO9zqODRs2UFJSYjiNiIjI1blv1vbTn5rN0Zj8onBcf/31JCQkALB27VrDaURERK7s7Flwf1Q1hcth3fyicMClxaMffPCB4SQiIiJXlpZmHZOSoHVrs1kak98UjoEDB9KxY0dyc3PZvn276TgiIiLf6913rWNTmk4BPyocAD/99t/e4sWLDScRERH5rtxcyMqCVq1g9GjTaRqXXxWOBx54AJvNxqZNmzh+/LjpOCIiIjW88451HDcObDazWRqbXxWO4OBg7r//fgDedy8BFhER8RJz51rHxx4zm8MEvyocAOPHjwdg+fLluFwuw2lEREQsmzbByZMQEQF33206TePzu8Jx8803079/f1wuFytWrDAdR0REBIAFC6zjL35hNocpflc4AMaNGwfAokWLDCcREREBlwuWLrXOH3/cbBZT/LJw3HXXXURERFBQUMAy9/6xIiIihnzwAZSWQmIi3HST6TRm+GXhAHjqqacAmOteoSMiImKI+6Po1782m8Mkvy0cgwYNokePHpw5c4Y097ZuIiIijWz3bti8GTp2hLFjTacxx28LB0BycjIA8+bNM5xERESaqr/9zTp+O/DeZPl14YiPj68a5VjqXq0jIiLSSL76Ct56yzp/8kmzWUzz68IBMGnSJADeeustysrKDKcREZGm5M03reOECdCundkspvl94RgwYAAxMTGcOXOG119/3XQcERFpQmbPto5PP202hzfw+8IB8Mc//hGAtLQ09u3bZziNiIg0BfPmwfHj0L8/xMWZTmNekygct9xyCykpKQC88MILhtOIiEhTMGOGdZw502wOb9EkCgfA448/TpcuXcjLy2POnDmm44iIiB+bOxfy8qBvX2uzL4FmlZWVlaZDNBan01l1c7f333+frl27Gk4kIiL+qFMnKCiArCwYONB0Gu/QpAoHwOzZs1mwYAE9evTg3XffNR1HRKTJyHi/kGNO77haMCbewe2Dr/fI754zB1JSrJGNjz/2yEv4pCZXOACSkpLIy8sjKSmJ3//+96bjiIg0CavfzKdTt2A6htuN5ji8qxibDfqPuMEjv989urFtmzWlIpYWpgOY8Je//IUJEyawfPlyOnfuXDXNIiIinhVgv46gNmY/eloGNgcqPPK7Z8ywysa996psXK7JLBqtLiIigldffRWA1157jczMTMOJRETE1+XkQGqqda5tn76rSRYOgDvvvJM//OEPAEyZMoXPPvvMcCIREfFlEyZYx9RUiIw0m8UbNdnCATBq1Ch+/vOfAzB58mTy8vIMJxIREV/0979bazYiI+HbvSblMk26cAA8+eSTDB48mJKSEiZNmkRRUZHpSCIi4kNOnYIpU6zzhQvNZvFmTb5wAMyaNYvevXtTUFDAo48+itPpNB1JRER8RFISnDtnXQrbr5/pNN5LheNbc+bM4cc//jEnT55k/PjxpKWlmY4kIiJe7mc/g+xsiImBV14xnca7qXB8y26388orrzB58mQAXn75ZaZNm0Z5ebnhZCIi4o1mzYL33oP27WHdOrCb3V7E66lwXObRRx/ljTfewOFwkJ6eziOPPEJubq7pWCIi4kU+/BCmTbPO166FkBCzeXyBCsf3iIuL47333iMqKoq8vDzGjh3Lyy+/TGFhoeloIiJeo0+fPsTHx/OPf/yDkpKSBvu9e/bsIC/v6Hce37w5g+Liqy/s37t3F8eOefYvicuWwciR1nlaGvTp49GX8xsqHFfQsWNHFi1axPPPP0+HDh1IS0tj+PDhKh4iItWUl5ezYMEChg8fzty5cxukeCxZMp9Vq5bWeMzlcjFz5lT27999xed98UUOU6b8ii++yKl3hit56SV48EHrfPHiS+dybSoc1/DAAw/w0Ucf8eyzz+JwOKqKx4svvsi2bdtMxxMRMe7ChQuUl5czf/78ehePyspKDhz4jA0bPuTixYtVj7uLxuHD338VYVHRWV544Zk6vWZtlJbCE0/A889DmzaQmQkPP+yxl/NLKhy1NH78eNasWcMzzzxD69atWbZsGSkpKQwYMIDf/va3LFu2DKfTSWlpqemoIiJGNETxOH36FOXlZZSXl+F07qt6fNu2fwHUeKz6686cOYUzZxp+9DkvD557DkJDYd4865idDQkJDf5Sfq9J3rytrmw2GxMmTCApKYn09HSys7PZunUrWVlZZGVlVf1cmzZtCAsLo1OnTtx88820bdsWh8NBmzZtcDgcVec33OCZOxWKiJh04cIFLly4wPz581m4cCETJkxg3LhxtXru0aNHqs63bMkgOjqWyspKsrLWA/D553upqKigefNLf19+441X2bdvNw89NJGlS9+uV/aCAjhwAJxOWL8eVqywHrfZ4Kmn4IUXoEOHer1Ek6XCUQfBwcGMHj2a0aNHA7B37162b9/OsWPHOHHiBCdPnmT//v3s37+/Vr/PbrcTGBhIy5YtCQwMJCAgoOqrRQv9KxIR33R58Zj66NJrPic311p/0avXj8jIWMsTTzzLkSOHKCo6S1RUNE7nPvLzTxAaGgbA6tUfsGbN/zJp0n/RpUv3WheOpUtherV9M1wuq2QUF9f8ubZt4emnYfJk6/JXqTt9mjWAmJgYYmJivvN4Xl4eBQUFnDp1itOnT1NYWFjjePr0acBadKX9PkTEX1VWVtb6/3GHDzux24N46KHHSE39DQcP7mf37u0ATJw4ienTUzhy5CChoWHs2bOD2bP/zH33jWHMmIfZu3dXrTMdPw7VBqax26FHD+jZs+ZXjx4/6K3KVahweFBYWBhhYWGmY4iIeESfa1wP2qJFCy5evEhiYiIpKSnsXHPt35mTc4Du3Xty++39sNuD+OSTjezevZ1+/eLp2fNHgFVKunWLIjX1OQDCw7uxZs0yjh+3LqXdtWsrt93WF4ej7RVf57nn4IP0Wr5RaRAqHCIi0qAuLxo33XQTADvJv+rzysrKyM8/wV13JRAQEEBCwrCqKZKpU2dgs9kIDb0Fp3Mf3bpFAWC3B7FgwRwAysvLAFi3bhVJSY9ctXBI41PhEBGRBnGlolFb+fnHAWvEAmDgwKGsXWut2uzbdwAAUVHRpKd/xEsv/Q8DBw6p8fy9e3cxZcqvmD79RSIiutX37UgD02WxIiJSL+7F7YmJiaxatYo//elPP7hsAJw4cQyA8PCuAMTE3IHdHkS/fvG0bt0GgC5dugNw8mReQ0SXRqQRDhERqZe6jmhczj3CERYWAVhFZujQ+4mKiq76mS5dIgHIzT1MWFh4jee7L5WtfsmseI9mlZWVlaZDiIiI/1v9Zj6dezsIjQyq9XNKS8/RsqW1TUBDOZB9luuaVdB/hPZCakwa4RAREa/VqlWw6QjSQDTuJCIiIh6nwiEiIiIep8IhIiIiHqfCISIiIh6nwiEiIiIep8IhIiIiHqfCISIiIh6nwiEiIiIep42/RESkUTRrBp9+eIrrWjYzmuPi+Qqi73YYzdAUaWtzERFpFK7SCi5eqDAdA4AAW3MCbBrkb0wqHCIiIuJxqnciIiLicSocIiIi4nEqHCIiIuJxKhwiIiLicSocIiIi4nEqHCIiIuJxKhwiIiLicSocIiIi4nEqHCIiIuJxKhwiIiLicSocIiIi4nH/D4tlrOVpR8hbAAAAAElFTkSuQmCC" alt /></p>
<p>Note that the serialization logic produces <code>M2</code> but the
deserialization logic only sees <code>M2′</code>, without the class
author having to worry about how to produce it.</p>
<h2 data-number="2.4" id="soundness"><span class="header-section-number">2.4</span> Soundness<a href="#soundness" class="self-link"></a></h2>
<p>There are three approaches that are sound — that is, they avoid ODR
issues.</p>
<ol type="1">
<li>Subobject-wise serialization.</li>
<li>Subobject-wise serialization with an initial normalization
step.</li>
<li>Custom serialization with custom deserialization.</li>
</ol>
<p>Subobject-wise serialization alone (1) already gives us a tremendous
amount of value (since this gives us
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>,
<code class="sourceCode cpp">std<span class="op">::</span>optional</code>,
<code class="sourceCode cpp">std<span class="op">::</span>expected</code>,
<code class="sourceCode cpp">std<span class="op">::</span>variant</code>,
<code class="sourceCode cpp">std<span class="op">::</span>span</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>,
among many other types) while still being sound, but we really need
custom serialization/deserialization (3) to get the rest of the types
(the containers). Allowing normalization (2) helps a small number of
types avoid doing all the work that (3) would necessitate.</p>
<h2 data-number="2.5" id="original-design"><span class="header-section-number">2.5</span> Original Design<a href="#original-design" class="self-link"></a></h2>
<p>The <span class="citation" data-cites="P2484R0">[<a href="https://wg21.link/p2484r0" role="doc-biblioref">P2484R0</a>]</span> design was a custom
serialization/deserialization design. Given a class type
<code class="sourceCode cpp">C</code>:</p>
<ul>
<li>serialization was done by way of an <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span><span class="op">()</span></code>
which had to return type <code class="sourceCode cpp">R</code>, which
had to be structural.</li>
<li>deserialization was done by way of a constructor from
<code class="sourceCode cpp">R</code>.</li>
</ul>
<p>This approach does satisfy the overall goal of avoiding ODR issues
(although the paper does not mention this at all), but the design had
some issues.</p>
<p>For one, it doesn’t cleanly support the case where we just want
member-wise template argument equivalence but our members happen to be
<code class="sourceCode cpp"><span class="kw">private</span></code> (the
<code class="sourceCode cpp">tuple</code>/<code class="sourceCode cpp">optional</code>/<code class="sourceCode cpp">variant</code>
cases). The paper tried to address this by allowing you to declare <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span><span class="op">()</span></code>
as <em>defaulted</em>, which doesn’t really seem semantically equivalent
to the non-defaulted case. A defaulted copy constructor or comparison
operator <em>can</em> be written by hand, if tediously, but a defaulted
<code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span></code>
would require you duplicating the whole type just to copy it?</p>
<p>Another problem it doesn’t clearly support variable-length data. How
do we serialize <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>?
<code class="sourceCode cpp">std<span class="op">::</span>string</code>?
The <code class="sourceCode cpp">SmallString</code> class from earlier?
The paper kind of punted on this question, suggesting that maybe we just
make <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
a structural type by fiat since the language can just know what it
means. That’s not actually all that unreasonable, but it is a bit
unsatisfying.</p>
<p>But it’s at least not a bad start. There’s a lot to like about this
approach:</p>
<ul>
<li>it’s actually a fairly straightforward way to handle serialization
and deserialization, so it does get at the most desirable model for how
to extend support for class types as non-type template parameters</li>
<li>it can properly handle reference members — which must have their
template argument equivalence defined as the identity of the object
referred to, not its value</li>
<li>it prevents attempting to do the wrong thing with pointer
members.</li>
</ul>
<p>What I mean by the last point is: how do you define template argument
equivalence for <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>?
There’s really only one way to do it: as if it were a <code class="sourceCode cpp">std<span class="op">::</span>pair<span class="op">&lt;</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span>, <span class="dt">size_t</span><span class="op">&gt;</span></code>.
If you try to do it the other way (comparing the contents), you’ll run
into problems on the deserialization side:</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">class</span> string_view <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// let&#39;s just simplify and ignore the template parameters</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> ptr_;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> len_;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// incorrect approach to serialization</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Repr <span class="op">{</span> std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> v; <span class="op">}</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> <span class="kw">operator</span> <span class="kw">template</span><span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> Repr <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Repr<span class="op">{.</span>v<span class="op">=</span>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;(</span>ptr_, ptr_ <span class="op">+</span> len_<span class="op">)}</span>;</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// the only possible thing deserialization could do?</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> string_view<span class="op">(</span>Repr r<span class="op">)</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> ptr_<span class="op">(</span>r<span class="op">.</span>data<span class="op">())</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        , len_<span class="op">(</span>r<span class="op">.</span>size<span class="op">())</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="op">}</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>If we serialize the <code class="sourceCode cpp">string_view</code>
as a <code class="sourceCode cpp">vector<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span></code>,
the only way to deserialize would be to refer to the contents of that
<code class="sourceCode cpp">vector</code>. Which immediately goes out
of scope, and the compiler can detect that.
<code class="sourceCode cpp">ptr_</code> has to be a permitted result of
a constant expression — basically that it has to point to something with
static storage duration. And the transient
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
allocation <em>is not</em> that. This error can be detected at compile
time.</p>
<p>And that will push you to having the <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span></code>
implementation for <code class="sourceCode cpp">string_view</code> be
just be defaulted — the correct implementation.</p>
<h2 data-number="2.6" id="a-note-on-spelling"><span class="header-section-number">2.6</span> A Note on Spelling<a href="#a-note-on-spelling" class="self-link"></a></h2>
<p>The original design used an <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">template</span></code>
function with a constructor. The original revision of this paper (<span class="citation" data-cites="P3380R0">[<a href="https://wg21.link/p3380r0" role="doc-biblioref">P3380R0</a>]</span>) continued the same thing, with
a tagged constructor instead. Because the constructor will basically
always have to be tagged, and should only ever be invoked by the
compiler anyway, this proposal now suggests using
<code class="sourceCode cpp">to_meta_representation</code> and a
<code class="sourceCode cpp"><span class="kw">static</span></code>
<code class="sourceCode cpp">from_meta_representation</code>.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="reflection-will-fix-it"><span class="header-section-number">3</span>
Reflection Will Fix It<a href="#reflection-will-fix-it" class="self-link"></a></h1>
<p>One of the issues with the serialization problem that we had to deal
with was: how exactly do you serialize? What representation do you
return? And then how do you deserialize again? This was where we got
stuck with types like
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
(which needs variable-length representation) and even
<code class="sourceCode cpp">std<span class="op">::</span>tuple</code>
(which has a simple answer for serialization but you don’t want to just
create a whole new tuple type for this). Faisal Vali had the insight
that reflection provides a very easy answer for this question: you
serialize into (and then deserialize from) a range of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>!</p>
<p>At least, that’s what <span class="citation" data-cites="P3380R0">[<a href="https://wg21.link/p3380r0" role="doc-biblioref">P3380R0</a>]</span> did. A refinement of this is,
rather than having the serialization function return a range of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>,
we can accept a <code class="sourceCode cpp">Serializer</code> that can
push a
<code class="sourceCode cpp">meta<span class="op">::</span>info</code> a
<code class="sourceCode cpp">Deserializer</code> which can pop one. The
proposed API for these types is:</p>
<table>
<tr>
<th>
Serialize
</th>
<th>
Deserialize
</th>
</tr>
<tr>
<td>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> serializer <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    vector<span class="op">&lt;</span>info<span class="op">&gt;</span> <em>output</em>; <span class="co">// exposition-only</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> push<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>        <em>output</em><span class="op">.</span>push_back<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">size_t</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> <em>output</em><span class="op">.</span>size<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>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> push_value<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="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>        push<span class="op">(</span>reflect_value<span class="op">(</span>value<span class="op">))</span>;</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> push_object<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> object<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>        push<span class="op">(</span>reflect_object<span class="op">(</span>object<span class="op">))</span>;</span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> push_subobjects<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> obj<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> M <span class="op">:</span> subobjects_of<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>is_reference_type<span class="op">(</span>type_of<span class="op">(</span>M<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>                push_object<span class="op">(</span>obj<span class="op">.[:</span>M<span class="op">:])</span>;</span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>                push_value<span class="op">(</span>obj<span class="op">.[:</span>M<span class="op">:])</span>;</span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span>ranges<span class="op">::</span>input_range R<span class="op">&gt;</span></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> push_range<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> elem <span class="op">:</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>            push_value<span class="op">(</span>elem<span class="op">)</span>;</span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
<td>
<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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> deserializer <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    vector<span class="op">&lt;</span>info<span class="op">&gt;</span> <em>input</em>; <span class="co">// exposition-only</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="kw">public</span><span class="op">:</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">consteval</span> deserializer<span class="op">(</span>serializer <span class="kw">const</span><span class="op">&amp;</span> s<span class="op">)</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> <em>input</em><span class="op">(</span>s<span class="op">.</span><em>output</em><span class="op">)</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> pop<span class="op">()</span> <span class="op">-&gt;</span> info <span class="op">{</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> r <span class="op">=</span> <em>input</em><span class="op">.</span>back<span class="op">()</span>;</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>        <em>input</em><span class="op">.</span>pop_back<span class="op">()</span>;</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> r;</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">size_t</span> <span class="op">{</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <em>input</em><span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> pop_value<span class="op">()</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>pop<span class="op">())</span>;</span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> pop_from_subobjects<span class="op">()</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>vector<span class="op">&lt;</span>info<span class="op">&gt;</span> rs;</span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>info _ <span class="op">:</span> subobjects_of<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>            rs<span class="op">.</span>push_back<span class="op">(</span>pop<span class="op">())</span>;</span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>        <span class="co">// proposed in this paper</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> structural_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>rs<span class="op">)</span>;</span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Equivalent to:</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      views::generate_n([this]{ return pop_value&lt;T&gt;(); }, size())</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>    <span class="co">// except that we don&#39;t have a views::generate_n yet.</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>    <span class="co">// But the point is to be an input-only range of T.</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> into_range<span class="op">()</span> <span class="op">-&gt;</span> <em>unspecified</em>;</span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
</tr>
</table>
<p>Strictly speaking, the only <em>necessary</em> functions are the
<code class="sourceCode cpp">push</code> that takes a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
and the <code class="sourceCode cpp">pop</code> that returns one. But
the added convenience functions are a big ergonomic benefit, as I’ll
show.</p>
<p>With that in mind, let’s start with
<code class="sourceCode cpp">SmallString</code> again. We wanted to
serialize just the objects in <code class="sourceCode cpp">data<span class="op">[</span><span class="dv">0</span><span class="op">:</span>length<span class="op">]</span></code>,
which is just matter of
<code class="sourceCode cpp">push<span class="op">()</span></code>-ing
those elements. Then, when we deserialize, we extract those values back,
knowing that they are all
<code class="sourceCode cpp"><span class="dt">char</span></code>s.</p>
<p>Using the bare minimum
<code class="sourceCode cpp">push<span class="op">()</span></code> and
<code class="sourceCode cpp">pop<span class="op">()</span></code> API,
that looks like this:</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">class</span> SmallString <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> data<span class="op">[</span><span class="dv">32</span><span class="op">]</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> length;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> length; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>            s<span class="op">.</span>push<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">(</span>data<span class="op">[</span>i<span class="op">]))</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> SmallString</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> str <span class="op">=</span> SmallString<span class="op">()</span>;</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>        str<span class="op">.</span>length <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>fill<span class="op">(</span>str<span class="op">.</span>data, <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span>; <span class="co">// ensure we zero the data first</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> length; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>            str<span class="op">.</span>data<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> extract<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;(</span>ds<span class="op">.</span>pop<span class="op">())</span>;</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> str;</span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Which if we used the typed APIs
(<code class="sourceCode cpp">push_value</code> and
<code class="sourceCode cpp">pop_value</code>) directly, it’s a little
simpler:</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">class</span> SmallString <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> data<span class="op">[</span><span class="dv">32</span><span class="op">]</span>;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> length;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> length; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>            s<span class="op">.</span>push_value<span class="op">(</span>data<span class="op">[</span>i<span class="op">])</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> SmallString</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> str <span class="op">=</span> SmallString<span class="op">()</span>;</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>        str<span class="op">.</span>length <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>fill<span class="op">(</span>str<span class="op">.</span>data, <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span>; <span class="co">// ensure we zero the data first</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> length; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>            str<span class="op">.</span>data<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> ds<span class="op">.</span>pop_value<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;()</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> str;</span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And lastly the range-based API becomes simpler still:</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">class</span> SmallString <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> data<span class="op">[</span><span class="dv">32</span><span class="op">]</span>;</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> length;</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_range<span class="op">(*</span><span class="kw">this</span><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>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> SmallString</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> str <span class="op">=</span> SmallString<span class="op">()</span>;</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>        str<span class="op">.</span>length <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>fill<span class="op">(</span>str<span class="op">.</span>data, <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span>; <span class="co">// ensure we zero the data first</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>copy<span class="op">(</span>ds<span class="op">.</span>into_range<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;()</span>, str<span class="op">.</span>data<span class="op">)</span>;</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> str;</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And this pattern works just as well for <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
which truly requires variable length contents. I’ll just skip straight
to the range-based API:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> vector <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    T<span class="op">*</span> begin_;</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size_;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> capacity_;</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_range<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> vector</span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>        vector v;</span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>begin_ <span class="op">=</span> std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;::</span>allocate<span class="op">(</span>ds<span class="op">.</span>size<span class="op">())</span>;</span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>capacity_ <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>uninitialized_copy<span class="op">(</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>            ds<span class="op">.</span>into_range<span class="op">&lt;</span>T<span class="op">&gt;()</span>,</span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>            v<span class="op">.</span>begin_<span class="op">)</span>;</span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>size_ <span class="op">=</span> v<span class="op">.</span>capacity_;</span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> v;</span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>One additional point of interest here is that, while this didn’t
matter for <code class="sourceCode cpp">SmalString</code>, in the <code class="sourceCode cpp">vector<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
example we are round-tripping through
<code class="sourceCode cpp">reflect_value</code> and
<code class="sourceCode cpp">extract</code> for arbitrary (structural)
<code class="sourceCode cpp">T</code>. This round-trip also needs to do
the custom serialization and deserialization for
<code class="sourceCode cpp">T</code> if that’s what the user wants, and
will happen automatically without the class author having to do
anything.</p>
<p>This approach seems particularly nice in that it handles these
disparate cases, without having to special-case
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>.</p>
<p>Let’s go through some of the other types we mentioned. For
<code class="sourceCode cpp">Optional</code> we could conditionally
serialize the value:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Optional <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span> T value; <span class="op">}</span>;</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> engaged;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>engaged<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>            s<span class="op">.</span>push_value<span class="op">(</span>value<span class="op">)</span>;</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Optional</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>ds<span class="op">.</span>size<span class="op">())</span> <span class="op">{</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Optional<span class="op">(</span>ds<span class="op">.</span>pop_value<span class="op">&lt;</span>T<span class="op">&gt;())</span>;</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Optional<span class="op">()</span>;</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But having to manually serialize and deserialize all the elements of
a <code class="sourceCode cpp">Tuple</code> is pretty tedious:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Tuple <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// let&#39;s assume this syntax works (because the details are not important here)</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> mem <span class="op">:</span> nonstatic_data_members_of<span class="op">(^^</span>Tuple<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>            <span class="co">// references and pointers have different rules for</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>            <span class="co">// template-argument-equivalence, and thus we need to</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>            <span class="co">// capture those differences... differently</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>is_reference_type<span class="op">(</span>type_of<span class="op">(</span>mem<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>                s<span class="op">.</span>push_object<span class="op">(</span><span class="kw">this</span><span class="op">-&gt;[:</span>mem<span class="op">:])</span>;</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>                s<span class="op">.</span>push_value<span class="op">(</span><span class="kw">this</span><span class="op">-&gt;[:</span>mem<span class="op">:])</span>;</span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Tuple</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Tuple<span class="op">(</span>std<span class="op">::</span>make_index_sequence<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)&gt;()</span>, ds<span class="op">)</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span><span class="op">...</span> Is, <span class="kw">class</span> D<span class="op">&gt;</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> Tuple<span class="op">(</span>index_sequence<span class="op">&lt;</span>Is<span class="op">...&gt;</span>,</span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a>                    std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">:</span> elems<span class="op">(</span>ds<span class="op">.</span>pop_value<span class="op">&lt;</span>Ts<span class="op">&gt;())...</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="op">}</span></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Cool. This is… a lot. Not only is it a lot of decidedly non-trivial
code to write, it’s a lot of code that doesn’t really do all that much.
We’re <em>just</em> doing the default member-wise equivalence here. On
the one hand, it’s good that we <em>can</em> do this. But it’s not
really great that we <em>have to</em>.</p>
<p>To aid in this endeavor, on the
<code class="sourceCode cpp">push<span class="op">()</span></code> side
it’s easy to provide a
<code class="sourceCode cpp">push_subobjects</code> convenience
functions that just does the right thing with all of the subobjects. But
on the <code class="sourceCode cpp">pop<span class="op">()</span></code>
side you’d want the same thing. There’s no such equivalent facility on
the deserialization side, since we’d need to be able to directly
construct an object of type <code class="sourceCode cpp">T</code> from
reflections of values or objects of suitable type. Even if there may not
be such a constructor available! To solve this problem, let’s add a new
function for this specific case. This is the <code class="sourceCode cpp">structural_cast<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
that I showed above in the implementation of
<code class="sourceCode cpp">pop_from_subobjects</code>.</p>
<p>That allows this <em>much</em> simpler implementation for
<code class="sourceCode cpp">Optional</code> and
<code class="sourceCode cpp">Tuple</code>:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Optional <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span> T value; <span class="op">}</span>;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> engaged;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_subobjects<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Optional</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> ds<span class="op">.</span>pop_from_subobjects<span class="op">&lt;</span>Optional<span class="op">&gt;()</span>;</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Tuple <span class="op">{</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_subobjects<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></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">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Tuple</span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> ds<span class="op">.</span>pop_from_subobjects<span class="op">&lt;</span>Tuple<span class="op">&gt;()</span>;</span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But… doing subobject-wise serialization is the default, right? So
maybe we should just be able to say that explicitly:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Optional <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span> T value; <span class="op">}</span>;</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> engaged;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Tuple <span class="op">{</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<h2 data-number="3.1" id="proposed-usage-examples"><span class="header-section-number">3.1</span> Proposed Usage Examples<a href="#proposed-usage-examples" class="self-link"></a></h2>
<p>Putting everything together, here is the proposed usage of this
facility for opting <code class="sourceCode cpp">Optional</code>,
<code class="sourceCode cpp">Tuple</code>,
<code class="sourceCode cpp">SmallString</code>, and
<code class="sourceCode cpp">Vector</code> to be structural types:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Optional <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span> T value; <span class="op">}</span>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> engaged;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Tuple <span class="op">{</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> SmallString <span class="op">{</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> data<span class="op">[</span><span class="dv">32</span><span class="op">]</span>;</span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> length;</span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_range<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> SmallString</span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> str <span class="op">=</span> SmallString<span class="op">()</span>;</span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a>        str<span class="op">.</span>length <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>fill<span class="op">(</span>str<span class="op">.</span>data, <span class="ch">&#39;</span><span class="sc">\0</span><span class="ch">&#39;</span><span class="op">)</span>;</span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>copy<span class="op">(</span>ds<span class="op">.</span>into_range<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;()</span>, str<span class="op">.</span>data<span class="op">)</span>;</span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> str;</span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vector <span class="op">{</span></span>
<span id="cb20-39"><a href="#cb20-39" aria-hidden="true" tabindex="-1"></a>    T<span class="op">*</span> begin_;</span>
<span id="cb20-40"><a href="#cb20-40" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size_;</span>
<span id="cb20-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> capacity_;</span>
<span id="cb20-42"><a href="#cb20-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-43"><a href="#cb20-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb20-44"><a href="#cb20-44" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_range<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb20-45"><a href="#cb20-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-46"><a href="#cb20-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-47"><a href="#cb20-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span></span>
<span id="cb20-48"><a href="#cb20-48" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Vector</span>
<span id="cb20-49"><a href="#cb20-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb20-50"><a href="#cb20-50" aria-hidden="true" tabindex="-1"></a>        Vector v;</span>
<span id="cb20-51"><a href="#cb20-51" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>begin_ <span class="op">=</span> std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;::</span>allocate<span class="op">(</span>ds<span class="op">.</span>size<span class="op">())</span>;</span>
<span id="cb20-52"><a href="#cb20-52" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>capacity_ <span class="op">=</span> ds<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb20-53"><a href="#cb20-53" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>ranges<span class="op">::</span>uninitialized_copy<span class="op">(</span></span>
<span id="cb20-54"><a href="#cb20-54" aria-hidden="true" tabindex="-1"></a>            ds<span class="op">.</span>into_range<span class="op">&lt;</span>T<span class="op">&gt;()</span>,</span>
<span id="cb20-55"><a href="#cb20-55" aria-hidden="true" tabindex="-1"></a>            v<span class="op">.</span>begin_<span class="op">)</span>;</span>
<span id="cb20-56"><a href="#cb20-56" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span>size_ <span class="op">=</span> v<span class="op">.</span>capacity_;</span>
<span id="cb20-57"><a href="#cb20-57" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> v;</span>
<span id="cb20-58"><a href="#cb20-58" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-59"><a href="#cb20-59" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>That seems pretty clean. All of these implementations are about as
minimal as you could get. <code class="sourceCode cpp">Optional</code>
and <code class="sourceCode cpp">Tuple</code> simply have to default two
functions. <code class="sourceCode cpp">Vector</code> and
<code class="sourceCode cpp">SmallString</code> have a single-line
serializer and a fairly short deserializer.</p>
<h2 data-number="3.2" id="template-argument-equivalence"><span class="header-section-number">3.2</span> Template-Argument Equivalence<a href="#template-argument-equivalence" class="self-link"></a></h2>
<p>For template-argument equivalence, we can say that two values of
class type <code class="sourceCode cpp">C</code> that has a direct
<code class="sourceCode cpp">to_meta_representation</code> member are
template-argument-equivalent if:</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">consteval</span> <span class="kw">auto</span> template_argument_equivalent<span class="op">(</span>C <span class="kw">const</span><span class="op">&amp;</span> a, C <span class="kw">const</span><span class="op">&amp;</span> b<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>meta<span class="op">::</span>serializer sa, sb;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    a<span class="op">.</span>to_meta_representation<span class="op">(</span>sa<span class="op">)</span>;</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    b<span class="op">.</span>to_meta_representation<span class="op">(</span>sb<span class="op">)</span>;</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> sa<span class="op">.</span><em>output</em> <span class="op">==</span> sb<span class="op">.</span><em>output</em>;</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>That is, two values are template-argument-equivalent if they
serialize equal reflections (which would recursively check
template-argument-equivalence, as necessary).</p>
<h2 data-number="3.3" id="normalization-1"><span class="header-section-number">3.3</span> Normalization<a href="#normalization-1" class="self-link"></a></h2>
<p>The current rule for constructing the template parameter object is
that we just initialize a new object of type
<code class="sourceCode cpp"><span class="kw">const</span> C</code>. But
if a class type provides a direct
<code class="sourceCode cpp">to_meta_represention</code>, then instead
of performing the equivalent of:</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">const</span> C <em>object</em> <span class="op">=</span> C<span class="op">(</span><em>init</em><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>We would do a round-trip:</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">const</span> C <em>object</em> <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> c <span class="op">=</span> C<span class="op">(</span><em>init</em><span class="op">)</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> s <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">()</span>;</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>to_meta_representation<span class="op">(</span>s<span class="op">)</span>;</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> ds <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">(</span>s<span class="op">)</span>;</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> C<span class="op">::</span>from_meta_representation<span class="op">(</span>ds<span class="op">)</span>;</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Note that, as a sanity check, the implementation could do a
<em>second</em> serialization round after the round-trip, do ensure that
both the original and new values produce the same serialization.</p>
<p>We will also have to adjust <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">()</span></code>
to also do this normalization. Which means:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Fraction <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numerator;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> denominator;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">operator</span><span class="op">==(</span>Fraction <span class="kw">const</span><span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// serialize in lowest terms</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> g <span class="op">=</span> std<span class="op">::</span>gcd<span class="op">(</span>numerator, denominator<span class="op">)</span>;</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_back<span class="op">(</span>numerator <span class="op">/</span> g<span class="op">)</span>;</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span>push_back<span class="op">(</span>denominator <span class="op">/</span> g<span class="op">)</span>;</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></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="co">// defaulted from_meta_representation does the right thing</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// (even though our to_meta_representation is custom)</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</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="co">// round-tripping through reflect_value and extract normalizes</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>extract<span class="op">&lt;</span>Fraction<span class="op">&gt;(</span>reflect_value<span class="op">(</span>Fraction<span class="op">{</span><span class="dv">2</span>, <span class="dv">4</span><span class="op">}))</span> <span class="op">==</span> Fraction<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">})</span>;</span></code></pre></div>
</blockquote>
</div>
<h2 data-number="3.4" id="allowing-templates"><span class="header-section-number">3.4</span> Allowing Templates<a href="#allowing-templates" class="self-link"></a></h2>
<p>The examples here all show regular functions for the template
serialization and deserialization functions:</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">typename</span> T<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vector <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="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">-&gt;</span> Vector;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But it’s nice to also allow these to be declared as templates.
Especially in the context of defaulting:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Tuple <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    Ts<span class="op">...</span> elems;</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_meta_representation<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The reason for this is that it allows library code that doesn’t
otherwise do any reflection stuff to avoid having to <code class="sourceCode cpp"><span class="pp">#include </span><span class="im">&lt;meta&gt;</span></code>.
The implementation can figure it out.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">4</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>This proposal extends class types as non-type parameters as follows.
This isn’t exactly Core wording, but does contain something akin to
wording because I think that might be a clearer way to express the
idea.</p>
<h2 data-number="4.1" id="language"><span class="header-section-number">4.1</span> Language<a href="#language" class="self-link"></a></h2>
<p>The language proposal is divided into several parts.</p>
<h3 data-number="4.1.1" id="template-serialization-and-deserialization-functions"><span class="header-section-number">4.1.1</span> Template Serialization and
Deserialization Functions<a href="#template-serialization-and-deserialization-functions" class="self-link"></a></h3>
<p>A class type <code class="sourceCode cpp">T</code> can provide a
template serialization function,
<code class="sourceCode cpp">to_meta_representation</code>, that must be
of the forms:</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="co">// non-static const member function</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="co">// non-static const member function template</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> to_meta_representation<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">void</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This function can also be declared as defaulted, in which case every
base class and non-static data member shall have structural type. The
default implementation is:</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> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">const</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>    s<span class="op">.</span>push_subobjects<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>If a class type <code class="sourceCode cpp">T</code> provides a
template serialization function
<code class="sourceCode cpp">to_meta_representation</code>, it must also
then provide a template deserialization function
<code class="sourceCode cpp">from_meta_representation</code>, that must
be of the forms:</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="co">// static member function</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">-&gt;</span> T;</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="co">// static member function template</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;)</span> <span class="op">-&gt;</span> T;</span></code></pre></div>
</blockquote>
</div>
<p>This function can also be declared as defaulted. The default
implementation is:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;</span> ds<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="ot">assert</span><span class="op">(</span>ds<span class="op">.</span>size<span class="op">()</span> <span class="op">==</span> subobjects_of<span class="op">(^^</span>T<span class="op">).</span>size<span class="op">())</span>;</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> ds<span class="op">.</span>pop_from_subobjects<span class="op">&lt;</span>T<span class="op">&gt;()</span>;</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>We’ll say that <code class="sourceCode cpp">T</code> has an eligible
template serialization function if it provides
<code class="sourceCode cpp">to_meta_representation</code> as a direct
member of the allowed forms (possibly-defaulted), and that
<code class="sourceCode cpp">T</code> has an eligible template
deserialization function if it provides
<code class="sourceCode cpp">from_meta_representation</code> as a direct
static member of the allowed forms (possibly-defaulted).</p>
<h3 data-number="4.1.2" id="extend-the-definition-of-structural"><span class="header-section-number">4.1.2</span> Extend the definition of
structural<a href="#extend-the-definition-of-structural" class="self-link"></a></h3>
<p>We extend the definition of structural (here it’s either the first
bullet or both of the next two — the additional rules on template
registration functions will be covered in their own section):</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">a</a></span>
A class type <code class="sourceCode cpp">C</code> is an <em>explicitly
structural class type</em> if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">(a.1)</a></span>
<code class="sourceCode cpp">C</code> has an eligible template
serialization function,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(a.2)</a></span>
<code class="sourceCode cpp">C</code> has an eligible template
deserialization function, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">(a.3)</a></span>
no direct or indirect non-static data member of
<code class="sourceCode cpp">C</code> is mutable.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">b</a></span>
A class type <code class="sourceCode cpp">C</code> is an <em>implicitly
structural class type</em> if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(b.1)</a></span>
all base classes and non-static data member of
<code class="sourceCode cpp">C</code> are public and non-mutable,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(b.2)</a></span>
the types of all base classes and non-static data members of
<code class="sourceCode cpp">C</code> are structural types (see
below),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">(b.3)</a></span>
<code class="sourceCode cpp">C</code> does not have an eligible template
serialization function, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(b.4)</a></span>
<code class="sourceCode cpp">C</code> does not have an eligible template
deserialization function.</li>
</ul>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">7</a></span>
A <em>structural type</em> is one of the following:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(7.1)</a></span>
a scalar type, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">(7.2)</a></span>
an lvalue reference type, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">(7.2b)</a></span>
<span class="addu">an array type whose element type is structural,
or</span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(7.3)</a></span>
a literal class type <span class="rm" style="color: #bf0303"><del>with
the following properties:</del></span> <span class="addu">that is either
an explicitly structural class type or an implicitly structural class
type.</span>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(7.3.1)</a></span>
<span class="rm" style="color: #bf0303"><del>all base classes and
non-static data members are public and non-mutable and</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(7.3.2)</a></span>
<span class="rm" style="color: #bf0303"><del>the types of all bases
classes and non-static data members are structural types or (possibly
multidimensional) array thereof.</del></span></li>
</ul></li>
</ul>
</blockquote>
</div>
<h3 data-number="4.1.3" id="template-argument-normalization"><span class="header-section-number">4.1.3</span> Template Argument
Normalization<a href="#template-argument-normalization" class="self-link"></a></h3>
<p>We introduce the concept of template argument normalization (status
quo so far is that <em>template-argument-normalization</em> is a no-op
for all types) and allow string literal template arguments:</p>
<div class="std">
<blockquote>
<div class="addu">
<p>A value <code class="sourceCode cpp">v</code> of structural type
<code class="sourceCode cpp">T</code> is
<em>template-argument-normalized</em> as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">1</a></span>
If <code class="sourceCode cpp">v</code> is a pointer (or reference) to
a string literal or subobject thereof, then let
<code class="sourceCode cpp">v</code> be
<code class="sourceCode cpp">S <span class="op">+</span> O</code> (or
<code class="sourceCode cpp">S<span class="op">[</span>O<span class="op">]</span></code>,
for a reference), where <code class="sourceCode cpp">S</code> is that
string literal and <code class="sourceCode cpp">O</code> is some
non-negative offset. Then <code class="sourceCode cpp">v</code> is
normalized to <code class="sourceCode cpp">define_static_string<span class="op">(</span>S<span class="op">)</span> <span class="op">+</span> O</code>
(or <code class="sourceCode cpp">define_static_string<span class="op">(</span>S<span class="op">)[</span>O<span class="op">]</span></code>,
for a reference). See <span class="citation" data-cites="P3491R0">[<a href="https://wg21.link/p3491r0" role="doc-biblioref">P3491R0</a>]</span>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">2</a></span>
Otherwise, if <code class="sourceCode cpp">T</code> is a scalar type or
an lvalue reference type, nothing is done.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">3</a></span>
Otherwise, if <code class="sourceCode cpp">T</code> is an array type,
every element of the array is template-argument-normalized.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">4</a></span>
Otherwise (if <code class="sourceCode cpp">T</code> is a class type),
then
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">(4.1)</a></span>
If <code class="sourceCode cpp">T</code> is an explicitly structural
class type, then <code class="sourceCode cpp">v</code> is normalized
via:</p>
<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> <em>NORMALIZE</em><span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> v<span class="op">)</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <em>s</em> <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">()</span>;</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>    v<span class="op">.</span>to_meta_representation<span class="op">(</span><em>s</em><span class="op">)</span>;</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <em>ds</em> <span class="op">=</span> std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">(</span><em>s</em><span class="op">)</span>;</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> T<span class="op">::</span>from_meta_representation<span class="op">(</span><em>ds</em><span class="op">)</span>;</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">(4.2)</a></span>
Otherwise (if <code class="sourceCode cpp">T</code> is an implicitly
structural class type), every subobject of
<code class="sourceCode cpp">v</code> is
template-argument-normalized.</p></li>
</ul></li>
</ul>
</div>
</blockquote>
</div>
<p>and <span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>/6.2:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_23" id="pnum_23">6</a></span>
For a non-type template-parameter of reference or pointer type, or for
each non-static data member of reference or pointer type in a non-type
template-parameter of class type or subobject thereof, the reference or
pointer value shall not refer or point to (respectively):</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">(6.1)</a></span>
a temporary object ([class.temporary]),</li>
</ul>
<div class="rm" style="color: #bf0303">

<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">(6.2)</a></span>
a string literal object ([lex.string]),</li>
</ul>

</div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">(6.3)</a></span>
the result of a
<code class="sourceCode cpp"><span class="kw">typeid</span></code>
expression ([expr.typeid]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">(6.4)</a></span>
a predefined
<code class="sourceCode cpp"><span class="ot">__func__</span></code>
variable ([dcl.fct.def.general]), or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">(6.5)</a></span>
a subobject ([intro.object]) of one of the above.</li>
</ul>
</blockquote>
</div>
<p>Ensure that when initializing a non-type template parameter that we
perform template-argument-normalization. That’s in <span>13.4.3 <a href="https://wg21.link/temp.arg.nontype">[temp.arg.nontype]</a></span>:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_29" id="pnum_29">4</a></span>
If <code class="sourceCode cpp">T</code> is a class type, a template
parameter object ([temp.param]) exists that is constructed so as to be
template-argument-equivalent to <code class="sourceCode cpp">v</code>
<span class="addu">after it is template-argument-normalized</span>; P
denotes that template parameter object. […]</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_30" id="pnum_30">5</a></span>
Otherwise, the value of <code class="sourceCode cpp">P</code> is that of
<code class="sourceCode cpp">v</code> <span class="addu">after it is
template-argument-normalized</span>.</p>
</blockquote>
</div>
<h3 data-number="4.1.4" id="update-stdmetareflect_value"><span class="header-section-number">4.1.4</span> Update <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">()</span></code><a href="#update-stdmetareflect_value" class="self-link"></a></h3>
<p>Third, we change the meaning of <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>reflect_value</code>
in <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> to perform
template-argument-normalization on its argument:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info reflect_value<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> expr<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_31" id="pnum_31">3</a></span>
<em>Returns</em>: A reflection of the value computed by an
lvalue-to-rvalue conversion applied to
<code class="sourceCode cpp">expr</code> <span class="addu">after being
template-argument-normalized</span>. The type of the represented value
is the cv-unqualified version of
<code class="sourceCode cpp">T</code>.</p>
</blockquote>
</div>
<h3 data-number="4.1.5" id="template-argument-equivalence-1"><span class="header-section-number">4.1.5</span>
Template-Argument-Equivalence<a href="#template-argument-equivalence-1" class="self-link"></a></h3>
<p>Note that two values of type <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>info</code>
that represent values compare equal if those values are
template-argument-equivalent, so this definition is properly recursive.
Also note that normalization will have already happened. This is in
<span>13.6 <a href="https://wg21.link/temp.type">[temp.type]</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_32" id="pnum_32">2</a></span>
Two values are <em>template-argument-equivalent</em> if they are of the
same type and […]</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_33" id="pnum_33">(2.11)</a></span>
they are of class type <span class="addu"><code class="sourceCode cpp">T</code></span> and</p>
<div class="addu">
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_34" id="pnum_34">(2.11.1)</a></span>
If <code class="sourceCode cpp">T</code> is an explicitly structural
class type, then the values <code class="sourceCode cpp">v1</code> and
<code class="sourceCode cpp">v2</code> are template-argument-equivalent
if <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>equal<span class="op">(</span>s1<span class="op">.</span><em>output</em>, s2<span class="op">.</span><em>output</em><span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
with <code class="sourceCode cpp">s1</code> and
<code class="sourceCode cpp">s2</code> populated as follows:</p>
<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>std<span class="op">::</span>meta<span class="op">::</span>serializer s1, s2;</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>v1<span class="op">.</span>to_meta_representation<span class="op">(</span>s1<span class="op">)</span>;</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>v2<span class="op">.</span>to_meta_representation<span class="op">(</span>s2<span class="op">)</span>;</span></code></pre></div></li>
</ul>
</div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_35" id="pnum_35">(2.11.2)</a></span>
<span class="addu">Otherwise (if <code class="sourceCode cpp">T</code>
is an implicitly structural class type), if</span> their corresponding
direct subobjects and reference members are
template-argument-equivalent.</li>
</ul></li>
</ul>
</blockquote>
</div>
<h2 data-number="4.2" id="library"><span class="header-section-number">4.2</span> Library<a href="#library" class="self-link"></a></h2>
<p>Add a new type trait for <code class="sourceCode cpp">std<span class="op">::</span>is_structural</code>,
which we will need to provide constrained template registration
functions (a real use, as <span class="citation" data-cites="LWG3354">[<a href="https://wg21.link/lwg3354" role="doc-biblioref">LWG3354</a>]</span> requested).</p>
<p>Add a defaulted
<code class="sourceCode cpp">to_meta_representation</code> and
<code class="sourceCode cpp">from_meta_representation</code> (that is,
the default subobject-wise serialization with no normalization):</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="dt">void</span> to_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>serializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">auto</span> from_meta_representation<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>deserializer<span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span></code></pre></div>
</blockquote>
</div>
<p>to all of the following library types, suitably constrained:</p>
<ul>
<li><code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>variant<span class="op">&lt;</span>Ts<span class="op">...&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>basic_string_view<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span>T, Extent<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>chrono<span class="op">::</span>duration<span class="op">&lt;</span>Rep, Period<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>chrono<span class="op">::</span>time_point<span class="op">&lt;</span>Clock, Duration<span class="op">&gt;</span></code></li>
</ul>
<p>There may need to be some wording similar to what we have for in <a href="http://eel.is/c++draft/pairs.pair#4">[pairs.pair]/4</a> right
now:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_36" id="pnum_36">4</a></span>
<code class="sourceCode cpp">pair<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code>
is a structural type ([temp.param]) if
<code class="sourceCode cpp">T</code> and
<code class="sourceCode cpp">U</code> are both structural types. Two
values <code class="sourceCode cpp">p1</code> and
<code class="sourceCode cpp">p2</code> of type <code class="sourceCode cpp">pair<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code>
are template-argument-equivalent ([temp.type]) if and only if
<code class="sourceCode cpp">p1<span class="op">.</span>first</code> and
<code class="sourceCode cpp">p2<span class="op">.</span>first</code> are
template-argument-equivalent and
<code class="sourceCode cpp">p1<span class="op">.</span>second</code>
and
<code class="sourceCode cpp">p2<span class="op">.</span>second</code>
are template-argument-equivalent.</p>
</blockquote>
</div>
<p>Introduce the new reflection function <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>structural_cast<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
that produces a new value of type <code class="sourceCode cpp">T</code>
given reflections of all the subobjects:</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">template</span><span class="op">&lt;</span>reflection_range R <span class="op">=</span> initializer_list<span class="op">&lt;</span>info<span class="op">&gt;&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> T structural_cast<span class="op">(</span>R<span class="op">&amp;&amp;)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And introduce the serializer and deserializer types:</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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> serializer</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>        vector<span class="op">&lt;</span>info<span class="op">&gt;</span> <em>output</em>; <span class="co">// exposition-only</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> push<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a>            <em>output</em><span class="op">.</span>push_back<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">size_t</span> <span class="op">{</span></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <em>output</em><span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> push_value<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="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a>            push<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_value<span class="op">(</span>value<span class="op">))</span>;</span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> push_object<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> object<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a>            push<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>reflect_object<span class="op">(</span>object<span class="op">))</span>;</span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-25"><a href="#cb36-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> push_subobjects<span class="op">(</span>T <span class="kw">const</span><span class="op">&amp;</span> obj<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb36-26"><a href="#cb36-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">template</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">constexpr</span> <span class="kw">auto</span> M <span class="op">:</span> subobjects_of<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb36-27"><a href="#cb36-27" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>is_reference_type<span class="op">(</span>type_of<span class="op">(</span>M<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb36-28"><a href="#cb36-28" aria-hidden="true" tabindex="-1"></a>                    push_object<span class="op">(</span>obj<span class="op">.[:</span>M<span class="op">:])</span>;</span>
<span id="cb36-29"><a href="#cb36-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb36-30"><a href="#cb36-30" aria-hidden="true" tabindex="-1"></a>                    push_value<span class="op">(</span>obj<span class="op">.[:</span>M<span class="op">:])</span>;</span>
<span id="cb36-31"><a href="#cb36-31" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb36-32"><a href="#cb36-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb36-33"><a href="#cb36-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-34"><a href="#cb36-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-35"><a href="#cb36-35" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>ranges<span class="op">::</span>input_range R<span class="op">&gt;</span></span>
<span id="cb36-36"><a href="#cb36-36" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> push_range<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb36-37"><a href="#cb36-37" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> elem <span class="op">:</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-38"><a href="#cb36-38" aria-hidden="true" tabindex="-1"></a>                push_value<span class="op">(</span>elem<span class="op">)</span>;</span>
<span id="cb36-39"><a href="#cb36-39" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb36-40"><a href="#cb36-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-41"><a href="#cb36-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb36-42"><a href="#cb36-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-43"><a href="#cb36-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> deserializer</span>
<span id="cb36-44"><a href="#cb36-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb36-45"><a href="#cb36-45" aria-hidden="true" tabindex="-1"></a>        vector<span class="op">&lt;</span>info<span class="op">&gt;</span> <em>input</em>; <span class="co">// exposition-only</span></span>
<span id="cb36-46"><a href="#cb36-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-47"><a href="#cb36-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb36-48"><a href="#cb36-48" aria-hidden="true" tabindex="-1"></a>        <span class="kw">explicit</span> <span class="kw">consteval</span> deserializer<span class="op">(</span><span class="kw">const</span> serializer<span class="op">&amp;</span> s<span class="op">)</span></span>
<span id="cb36-49"><a href="#cb36-49" aria-hidden="true" tabindex="-1"></a>            <span class="op">:</span> <em>input</em><span class="op">(</span>s<span class="op">.</span><em>output</em><span class="op">)</span></span>
<span id="cb36-50"><a href="#cb36-50" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="op">}</span></span>
<span id="cb36-51"><a href="#cb36-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-52"><a href="#cb36-52" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> pop<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="cb36-53"><a href="#cb36-53" aria-hidden="true" tabindex="-1"></a>            info r <span class="op">=</span> <em>input</em><span class="op">.</span>back<span class="op">()</span>;</span>
<span id="cb36-54"><a href="#cb36-54" aria-hidden="true" tabindex="-1"></a>            <em>input</em><span class="op">.</span>pop_back<span class="op">()</span>;</span>
<span id="cb36-55"><a href="#cb36-55" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> r;</span>
<span id="cb36-56"><a href="#cb36-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-57"><a href="#cb36-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-58"><a href="#cb36-58" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">size_t</span> <span class="op">{</span></span>
<span id="cb36-59"><a href="#cb36-59" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <em>input</em><span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb36-60"><a href="#cb36-60" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-61"><a href="#cb36-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-62"><a href="#cb36-62" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-63"><a href="#cb36-63" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> pop_value<span class="op">()</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb36-64"><a href="#cb36-64" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> extract<span class="op">&lt;</span>T<span class="op">&gt;(</span>pop<span class="op">())</span>;</span>
<span id="cb36-65"><a href="#cb36-65" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-66"><a href="#cb36-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-67"><a href="#cb36-67" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-68"><a href="#cb36-68" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> pop_from_subobjects<span class="op">()</span> <span class="op">-&gt;</span> T <span class="op">{</span></span>
<span id="cb36-69"><a href="#cb36-69" aria-hidden="true" tabindex="-1"></a>            std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>meta<span class="op">::</span>info<span class="op">&gt;</span> rs;</span>
<span id="cb36-70"><a href="#cb36-70" 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 _ <span class="op">:</span> subobjects_of<span class="op">(^^</span>T<span class="op">))</span> <span class="op">{</span></span>
<span id="cb36-71"><a href="#cb36-71" aria-hidden="true" tabindex="-1"></a>                rs<span class="op">.</span>push_back<span class="op">(</span>pop<span class="op">())</span>;</span>
<span id="cb36-72"><a href="#cb36-72" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb36-73"><a href="#cb36-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-74"><a href="#cb36-74" aria-hidden="true" tabindex="-1"></a>            <span class="co">// proposed in this paper</span></span>
<span id="cb36-75"><a href="#cb36-75" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> std<span class="op">::</span>meta<span class="op">::</span>structural_cast<span class="op">&lt;</span>T<span class="op">&gt;(</span>rs<span class="op">)</span>;</span>
<span id="cb36-76"><a href="#cb36-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-77"><a href="#cb36-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-78"><a href="#cb36-78" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Equivalent to:</span></span>
<span id="cb36-79"><a href="#cb36-79" aria-hidden="true" tabindex="-1"></a>        <span class="co">//      views::generate_n([this]{ return pop_value&lt;T&gt;(); }, size())</span></span>
<span id="cb36-80"><a href="#cb36-80" aria-hidden="true" tabindex="-1"></a>        <span class="co">// except that we don&#39;t have a views::generate_n yet.</span></span>
<span id="cb36-81"><a href="#cb36-81" aria-hidden="true" tabindex="-1"></a>        <span class="co">// But the point is to be an input-only range of T</span></span>
<span id="cb36-82"><a href="#cb36-82" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb36-83"><a href="#cb36-83" aria-hidden="true" tabindex="-1"></a>        <span class="kw">consteval</span> <span class="kw">auto</span> into_range<span class="op">()</span> <span class="op">-&gt;</span> <em>unspecified</em>;</span>
<span id="cb36-84"><a href="#cb36-84" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb36-85"><a href="#cb36-85" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="acknowledgements"><span class="header-section-number">5</span>
Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Thanks to Richard Smith and Davis Herring for all the work in this
space. Thanks to Jeff Snyder for originally seeing how to solve this
problem (even if we didn’t end up using his original solution). Thanks
to Faisal Vali, Daveed Vandevoorde, and Peter Dimov for working through
a solution.</p>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">6</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-LWG3354" class="csl-entry" role="doc-biblioentry">
[LWG3354] Daniel Krügler. has_strong_structural_equality has a
meaningless definition. <a href="https://wg21.link/lwg3354"><div class="csl-block">https://wg21.link/lwg3354</div></a>
</div>
<div id="ref-P0424R2" class="csl-entry" role="doc-biblioentry">
[P0424R2] Louis Dionne, Hana Dusíková. 2017-11-14. String literals as
non-type template parameters. <a href="https://wg21.link/p0424r2"><div class="csl-block">https://wg21.link/p0424r2</div></a>
</div>
<div id="ref-P0732R2" class="csl-entry" role="doc-biblioentry">
[P0732R2] Jeff Snyder, Louis Dionne. 2018-06-06. Class Types in Non-Type
Template Parameters. <a href="https://wg21.link/p0732r2"><div class="csl-block">https://wg21.link/p0732r2</div></a>
</div>
<div id="ref-P1907R0" class="csl-entry" role="doc-biblioentry">
[P1907R0] Jens Maurer. 2019-10-07. Inconsistencies with non-type
template parameters. <a href="https://wg21.link/p1907r0"><div class="csl-block">https://wg21.link/p1907r0</div></a>
</div>
<div id="ref-P1907R1" class="csl-entry" role="doc-biblioentry">
[P1907R1] Jens Maurer. 2019-11-08. Inconsistencies with non-type
template parameters. <a href="https://wg21.link/p1907r1"><div class="csl-block">https://wg21.link/p1907r1</div></a>
</div>
<div id="ref-P2484R0" class="csl-entry" role="doc-biblioentry">
[P2484R0] Richard Smith. 2021-11-17. Extending class types as non-type
template parameters. <a href="https://wg21.link/p2484r0"><div class="csl-block">https://wg21.link/p2484r0</div></a>
</div>
<div id="ref-P2996R7" class="csl-entry" role="doc-biblioentry">
[P2996R7] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-10-13. Reflection for
C++26. <a href="https://wg21.link/p2996r7"><div class="csl-block">https://wg21.link/p2996r7</div></a>
</div>
<div id="ref-P3380R0" class="csl-entry" role="doc-biblioentry">
[P3380R0] Barry Revzin. 2024-09-10. Extending support for class types as
non-type template parameters. <a href="https://wg21.link/p3380r0"><div class="csl-block">https://wg21.link/p3380r0</div></a>
</div>
<div id="ref-P3491R0" class="csl-entry" role="doc-biblioentry">
[P3491R0] Peter Dimov, Dan Katz, Barry Revzin, and Daveed Vandevoorde.
2024-11-03. <code class="sourceCode cpp">define_static_string</code> and
<code class="sourceCode cpp">define_static_array</code>. <a href="https://wg21.link/p3491r0"><div class="csl-block">https://wg21.link/p3491r0</div></a>
</div>
</div>
</div>
</div>
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script></body>
</html>
