<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2025-05-17" />
  <title>Designated-initializers for Base Classes</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;
}
td > div > 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.addu td pre { background-color: inherit; }
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.rm li {
text-decoration: line-through;
color: #000000;
}
div.std blockquote del, div.rm {
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">Designated-initializers for
Base Classes</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2287R5 <a href="https://wg21.link/P2287">[Latest]</a> <a href="https://wg21.link/P2287/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-05-17</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>
      CWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
    </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="#design-space" id="toc-design-space"><span class="toc-section-number">2.1</span> Design Space<span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">3</span> Proposal<span></span></a>
<ul>
<li><a href="#naming-the-base-classes" id="toc-naming-the-base-classes"><span class="toc-section-number">3.1</span> Naming the base
classes<span></span></a></li>
<li><a href="#naming-all-the-subobjects" id="toc-naming-all-the-subobjects"><span class="toc-section-number">3.2</span> Naming all the
subobjects<span></span></a></li>
<li><a href="#impact-on-existing-code" id="toc-impact-on-existing-code"><span class="toc-section-number">3.3</span> Impact on Existing
Code<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">3.4</span> Implementation
Experience<span></span></a></li>
</ul></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">4</span> Wording<span></span></a>
<ul>
<li><a href="#strategy" id="toc-strategy"><span class="toc-section-number">4.1</span> Strategy<span></span></a></li>
<li><a href="#actual-wording" id="toc-actual-wording"><span class="toc-section-number">4.2</span> Actual
Wording<span></span></a></li>
<li><a href="#feature-test-macro" id="toc-feature-test-macro"><span class="toc-section-number">4.3</span> Feature-test
Macro<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="P2287R4"><a href="https://wg21.link/p2287r4" role="doc-biblioref">[P2287R4]</a></span>, wording improvements.</p>
<p>Since <span class="citation" data-cites="P2287R3"><a href="https://wg21.link/p2287r3" role="doc-biblioref">[P2287R3]</a></span>, clarify that the design
allows you to initialize the first base class from a non-designated
initializer but the second base class’s members indirectly. Simplified
wording as a result.</p>
<p><span class="citation" data-cites="P2287R2"><a href="https://wg21.link/p2287r2" role="doc-biblioref">[P2287R2]</a></span> proposed only allowing
indirectly initializing members using the designated syntax. R3
additionally allows directly initializing base class subobjects
<em>without</em> a designator. Also adds an implementation.</p>
<p><span class="citation" data-cites="P2287R1"><a href="https://wg21.link/p2287r1" role="doc-biblioref">[P2287R1]</a></span> proposed a novel way of naming
base classes, as well as a way for naming indirect non-static data
members. This revision <em>only</em> supports naming direct or indirect
non-static data members, with no mechanism to name base classes.
Basically only what Matthias suggested.</p>
<p><span class="citation" data-cites="P2287R0"><a href="https://wg21.link/p2287r0" role="doc-biblioref">[P2287R0]</a></span> proposed a single syntax for a
<em>designated-initializer</em> that identifies a base class. Based on a
reflector suggestion from Matthias Stearn, this revision extends the
syntax to allow the brace-elision version of
<em>designated-initializer</em>: allow naming indirect non-static data
members as well. Also actually correctly targeting EWG this time.</p>
<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><span class="citation" data-cites="P0017R1"><a href="https://wg21.link/p0017r1" role="doc-biblioref">[P0017R1]</a></span> extended aggregates to allow
an aggregate to have a base class. <span class="citation" data-cites="P0329R4"><a href="https://wg21.link/p0329r4" role="doc-biblioref">[P0329R4]</a></span> gave us designated
initializers, which allow for much more expressive and functional
initialization of aggregates. However, the two do not mix: a designated
initializer can currently only refer to a direct non-static data
members. This means that if I have a type like:</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> A <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> a;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> b;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>While I can initialize an <code class="sourceCode cpp">A</code> like
<code class="sourceCode cpp">A<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span></code>,
I cannot designated-initialize <code class="sourceCode cpp">B</code>. An
attempt like <code class="sourceCode cpp">B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>
runs afoul of the rule that the initializers must either be all
designated or none designated. But there is currently no way to
designate the base class here.</p>
<p>Which means that my only options for initializing a
<code class="sourceCode cpp">B</code> are to fall-back to regular
aggregate initialization and write either <code class="sourceCode cpp">B<span class="op">{{</span><span class="dv">1</span><span class="op">}</span>, <span class="dv">2</span><span class="op">}</span></code>
or <code class="sourceCode cpp">B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span></code>.
Neither are especially satisfactory.</p>
<h2 data-number="2.1" id="design-space"><span class="header-section-number">2.1</span> Design Space<a href="#design-space" class="self-link"></a></h2>
<p>There are basically three potential approaches for being able to
designated-initialize <code class="sourceCode cpp">B</code>:</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="co">// provide a way to name the base class</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> b1 <span class="op">=</span> B<span class="op">{.</span>A<span class="op">={.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co">// allow mixing designated and non-designated</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> b2 <span class="op">=</span> B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">3</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="co">// allow directly initializing indirect members</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> b3 <span class="op">=</span> B<span class="op">{.</span>a<span class="op">=</span><span class="dv">5</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">6</span><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>A previous revision of this paper proposed allowing only
<code class="sourceCode cpp">b1</code> — coming up with a way to name
the base class. This is much more complicated than naming an aggregate
member because base classes aren’t just
<code class="sourceCode cpp"><em>identifier</em></code>s, they can
include template parameters. This revision eschews that approach
entirely.</p>
<p>This leaves the other two options. When this paper was discussed in
<a href="https://wiki.edg.com/bin/view/Wg21varna/NotesEWGP2287">Varna</a>,
there was some desire expressed for having braces around the base class
subobject (as in <code class="sourceCode cpp">b2</code> above). While
allowing for optional braces is straightforward enough (and is simply a
matter of refining the restriction on mixing designated and
non-designated initializers), I would be strongly opposed to mandating
braces.</p>
<p>Designated-initialization mirrors assignment. The goal is to do this
substitution:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Assignment</strong>
</div></th>
<th><div style="text-align:center">
<strong>Initialization</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="op">[&amp;]{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    B b;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    b<span class="op">.</span>a <span class="op">=</span> <span class="dv">5</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    b<span class="op">.</span>b <span class="op">=</span> <span class="dv">6</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> b;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}()</span>;</span></code></pre></div>

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

<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>B<span class="op">{.</span>a<span class="op">=</span><span class="dv">5</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">6</span><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>We can directly assign into <code class="sourceCode cpp">a</code>, so
we should be able to directly initialize into it. Of course, in C the
two forms are identical (assuming C had lambdas) while in C++ they
aren’t necessarily due to the existence of constructors. This makes
designated initialization in C a much simpler problem. Plus C doesn’t
have base classes. But the essence should be the same — mandating braces
breaks that.</p>
<p>Additionally, in many cases, the point of inheritance of aggregates
is not because we actually need an “is-a” relationship but rather to
compose aggregate members. I don’t need
<code class="sourceCode cpp">B</code> to be an
<code class="sourceCode cpp">A</code>, I need
<code class="sourceCode cpp">B</code> to have the same members as
<code class="sourceCode cpp">A</code> with the same convenient access
syntax — as opposed to having a member of type
<code class="sourceCode cpp">A</code> and needing an extra accessor in
the chain. Forcing the user to initialize
<code class="sourceCode cpp">B</code> with braces forces the user to be
aware of what is basically an implementation detail. It’s frustrating
enough to deal with the requirement that initializers be in-order,
additionally requiring braces is too much.</p>
<p>Lastly, aggregate initialize <em>already</em> allows for brace
elision. <code class="sourceCode cpp">B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span></code>
is well-formed today, despite the
<code class="sourceCode cpp"><span class="dv">1</span></code>
initializing a base class subobject and
<code class="sourceCode cpp"><span class="dv">2</span></code>
initializing a direct member. So it strikes me as especially contrary to
the design to suddenly mandate braces here.</p>
<p>But <em>allowing</em> (not mandating) braces? That seems totally
fine. Also, notably, gcc in <code class="sourceCode cpp"><span class="op">-</span>std<span class="op">=</span>c<span class="op">++</span><span class="dv">17</span></code>
mode — still to this day on trunk — supports <code class="sourceCode cpp">B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>.
We actually had some code break while upgrading to C++20 that
initialized aggregates in this way. While I think <code class="sourceCode cpp">B<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>
is the clearest way to initialize this type, <code class="sourceCode cpp">B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>
is still great — and both are substantial improvements over the best you
can do in valid C++20 today, which would be either <code class="sourceCode cpp">B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="dv">2</span><span class="op">}</span></code>
or simply <code class="sourceCode cpp">B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span></code>.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>This paper proposes extending designated initialization syntax
to:</p>
<ol type="1">
<li>allow directly initializing base class aggregate elements, and</li>
<li>allow mixing designated and non-designated initializers, if all of
the non-designated initializers are at the beginning of the
<em>initializer-list</em> and are used to initialize base class
subobjects.</li>
</ol>
<p>In short, based on the above declarations of
<code class="sourceCode cpp">A</code> and
<code class="sourceCode cpp">B</code>, this proposal allows all of the
following declarations:</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>B<span class="op">{{</span><span class="dv">1</span><span class="op">}</span>, <span class="dv">2</span><span class="op">}</span>         <span class="co">// already valid in C++17</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>B<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span>           <span class="co">// already valid in C++17</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>B<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>     <span class="co">// proposed</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>B<span class="op">{{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>   <span class="co">// proposed</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>B<span class="op">{.</span>a<span class="op">{</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">{</span><span class="dv">2</span><span class="op">}}</span>   <span class="co">// proposed</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>B<span class="op">{.</span>b<span class="op">=</span><span class="dv">2</span>, <span class="op">.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>     <span class="co">// still ill-formed</span></span></code></pre></div>
</blockquote>
</div>
<h2 data-number="3.1" id="naming-the-base-classes"><span class="header-section-number">3.1</span> Naming the base classes<a href="#naming-the-base-classes" class="self-link"></a></h2>
<p>The original revisions of this paper dealt with how to name the
<code class="sourceCode cpp">A</code> base class of
<code class="sourceCode cpp">B</code>, and what this means for more
complicated base classes (such at those with template parameters). This
revision eschews that approach entirely: it’s simpler to just stick with
naming members, direct and indirect. After all, that’s how these
aggregates will be interacted with.</p>
<p>What this means is that while this paper proposes that this
works:</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">struct</span> A <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> b; <span class="op">}</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> b <span class="op">=</span> B<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>And in a type that has a base class that is not an aggregate, you can
use the mix-and-match form if the non-designated initializers initialize
base classes</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">struct</span> C <span class="op">:</span> std<span class="op">::</span>string <span class="op">{</span> <span class="dt">int</span> c1, c2; <span class="op">}</span>;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> c1 <span class="op">=</span> C<span class="op">{</span><span class="st">&quot;hello&quot;</span>, <span class="op">.</span>c1<span class="op">=</span><span class="dv">3</span>, <span class="op">.</span>c2<span class="op">=</span><span class="dv">4</span><span class="op">}</span>;    <span class="co">// ok</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> c2 <span class="op">=</span> C<span class="op">{{</span><span class="st">&quot;hello&quot;</span><span class="op">}</span>, <span class="op">.</span>c1<span class="op">=</span><span class="dv">3</span>, <span class="op">.</span>c2<span class="op">=</span><span class="dv">4</span><span class="op">}</span>;  <span class="co">// ok</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> c3 <span class="op">=</span> C<span class="op">{</span><span class="st">&quot;nope&quot;</span>, <span class="dv">3</span>, <span class="op">.</span>c2<span class="op">=</span><span class="dv">4</span><span class="op">}</span>;         <span class="co">// ill-formed: all the non-designated initializers</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>                                       <span class="co">// have to initialize a base class</span></span></code></pre></div>
</blockquote>
</div>
<p>If you have a hierarchy with repeated members, you’ll likewise have
to use the mix-and-match form:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> D <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> E <span class="op">:</span> D <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> e1 <span class="op">=</span> E<span class="op">{.</span>x<span class="op">=</span><span class="dv">1</span><span class="op">}</span>;         <span class="co">// ok: initializes D::x to {} and E::x to 1</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> e2 <span class="op">=</span> E<span class="op">{{.</span>x<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>x<span class="op">=</span><span class="dv">2</span><span class="op">}</span>; <span class="co">// ok: initializes D::x to 1 and E::x to 2</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> e3 <span class="op">=</span> E<span class="op">{</span>D<span class="op">{</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>x<span class="op">=</span><span class="dv">2</span><span class="op">}</span>;   <span class="co">// ok: initializes D to D{1} and E::x to 2</span></span></code></pre></div>
</blockquote>
</div>
<p>If you have two base classes, they do not need to look the same. It’s
just that all the non-designated initializers have to be at the
front:</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">struct</span> F <span class="op">{</span> <span class="dt">int</span> f; <span class="op">}</span>;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> G <span class="op">{</span> <span class="dt">int</span> g; <span class="op">}</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> H <span class="op">:</span> F, G <span class="op">{</span> <span class="dt">int</span> h; <span class="op">}</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> h1 <span class="op">=</span> H<span class="op">{{.</span>f<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">{.</span>g<span class="op">=</span><span class="dv">2</span><span class="op">}</span>, <span class="op">.</span>h<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;      <span class="co">// ok</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> h2 <span class="op">=</span> H<span class="op">{{.</span>f<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, <span class="op">.</span>g<span class="op">=</span><span class="dv">2</span>, <span class="op">.</span>h<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;        <span class="co">// ok, not all bases have to be the same</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> h3 <span class="op">=</span> H<span class="op">{{.</span>f<span class="op">=</span><span class="dv">1</span><span class="op">}</span>, G<span class="op">{</span><span class="dv">2</span><span class="op">}</span>, <span class="op">.</span>h<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;        <span class="co">// ok, likewise</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> h4 <span class="op">=</span> H<span class="op">{{.</span>f<span class="op">=</span><span class="dv">1</span><span class="op">}</span> <span class="op">{.</span>g<span class="op">=</span><span class="dv">2</span><span class="op">}</span>, <span class="op">.</span>g<span class="op">=</span><span class="dv">3</span>, <span class="op">.</span>h<span class="op">=</span><span class="dv">4</span><span class="op">}</span>; <span class="co">// ill-formed: attempting to initialize the G subobject in</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>                                        <span class="co">// different ways</span></span></code></pre></div>
</blockquote>
</div>
<p>Coming up with a way to <em>name</em> the base class subobject of a
class seems useful, but that’s largely orthogonal. It can be done
later.</p>
<h2 data-number="3.2" id="naming-all-the-subobjects"><span class="header-section-number">3.2</span> Naming all the subobjects<a href="#naming-all-the-subobjects" class="self-link"></a></h2>
<p>The current wording we have says that, from <span>9.5.2 <a href="https://wg21.link/dcl.init.aggr">[dcl.init.aggr]</a></span>/3.1:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">(3.1)</a></span>
If the initializer list is a brace-enclosed
<em>designated-initializer-list</em>, the aggregate shall be of class
type, the <em>identifier</em> in each designator shall name a direct
non-static data member of the class […]</p>
</blockquote>
</div>
<p>And, from <span>9.5.5 <a href="https://wg21.link/dcl.init.list">[dcl.init.list]</a></span>/3.1
(conveniently, it’s 3.1 in both cases):</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">(3.1)</a></span>
If the <em>braced-init-list</em> contains a
<em>designated-initializer-list</em>,
<code class="sourceCode cpp">T</code> shall be an aggregate class. The
ordered identifiers in the designators of the
<em>designated-initializer-list</em> shall form a subsequence of the
ordered identifiers in the direct non-static data members of
<code class="sourceCode cpp">T</code>. Aggregate initialization is
performed ([dcl.init.aggr]).</p>
</blockquote>
</div>
<p>The proposal here is to extend both of these rules to cover not just
the direct non-static data members of
<code class="sourceCode cpp">T</code> but also all indirect members,
such that every interleaving base class is also an aggregate class. That
is:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> b; <span class="op">}</span>;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">:</span> A <span class="op">{</span> C<span class="op">()</span>; <span class="dt">int</span> c; <span class="op">}</span>;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> D <span class="op">:</span> C <span class="op">{</span> <span class="dt">int</span> d; <span class="op">}</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>A<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>;       <span class="co">// okay since C++17</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>B<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>; <span class="co">// proposed okay, &#39;a&#39; is a direct member of an aggregate class</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>               <span class="co">// and A is a direct base</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>C<span class="op">{.</span>c<span class="op">=</span><span class="dv">1</span><span class="op">}</span>;       <span class="co">// error: C is not an aggregate</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>D<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span>;       <span class="co">// error: &#39;a&#39; is a direct member of an aggregate class</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>               <span class="co">// but an intermediate base class (C) is not an aggregate</span></span></code></pre></div>
</blockquote>
</div>
<p>Or, put differently, every identifier shall name a non-static data
member that is not a (direct or indirect) member of any base class that
is not an aggregate.</p>
<p>Also this is still based on lookup rules, so if the same name appears
in multiple base classes, then either it’s only the most derived one
that counts:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Y <span class="op">:</span> X <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>Y<span class="op">{.</span>x<span class="op">=</span><span class="dv">1</span><span class="op">}</span>; <span class="co">// initializes Y::x</span></span></code></pre></div>
</blockquote>
</div>
<p>or is ambiguous:</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">struct</span> X <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Y <span class="op">{</span> <span class="dt">int</span> x; <span class="op">}</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Z <span class="op">:</span> X, Y <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>Z<span class="op">{.</span>x<span class="op">=</span><span class="dv">1</span><span class="op">}</span>; <span class="co">// error:: ambiguous which X</span></span></code></pre></div>
</blockquote>
</div>
<p>would be ill-formed on the basis that
<code class="sourceCode cpp">Z<span class="op">::</span>x</code> is
ambiguous.</p>
<h2 data-number="3.3" id="impact-on-existing-code"><span class="header-section-number">3.3</span> Impact on Existing Code<a href="#impact-on-existing-code" class="self-link"></a></h2>
<p>There is one case I can think of where code would change meaning:</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">struct</span> A <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> b; <span class="op">}</span>;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>A<span class="op">)</span>; <span class="co">// #1</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>B<span class="op">)</span>; <span class="co">// #2</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    f<span class="op">({.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">})</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>In C++23, <code class="sourceCode cpp">f<span class="op">({.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">})</span></code>
calls <code class="sourceCode cpp"><span class="pp">#1</span></code>, as
it’s the only viable candidate. But with this change,
<code class="sourceCode cpp"><span class="pp">#2</span></code> also
becomes a viable candidate, so this call becomes ambiguous. I have no
idea how much such code exists. This is, at least, easy to fix.</p>
<p>I don’t think there’s a case where code would change from one valid
meaning to a different valid meaning - just from valid to ambiguous.</p>
<h2 data-number="3.4" id="implementation-experience"><span class="header-section-number">3.4</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h2>
<p>I implemented this <a href="https://github.com/llvm/llvm-project/compare/main...brevzin:llvm-project:p2287?expand=1">in
clang</a> in a very literal way — by synthesizing a new
designated-initializer-list to initialize the base classes in the
situations where that comes up. There is probably a more straightforward
way to do this, but all the examples in the paper work.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="4.1" id="strategy"><span class="header-section-number">4.1</span> Strategy<a href="#strategy" class="self-link"></a></h2>
<p>The wording strategy here is as follows. Let’s say we have this
simple case:</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">struct</span> A <span class="op">{</span> <span class="dt">int</span> a; <span class="op">}</span>;</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> b; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>In the current wording, <code class="sourceCode cpp">B</code> has two
elements (the <code class="sourceCode cpp">A</code> direct base class
and then the <code class="sourceCode cpp">b</code> member). The
initialization <code class="sourceCode cpp">B<span class="op">{.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>
is considered to have one explicitly initialized element (the
<code class="sourceCode cpp">b</code>, initialized with
<code class="sourceCode cpp"><span class="dv">2</span></code>) and then
the <code class="sourceCode cpp">A</code> is not explicitly initialized
and cannot have a default member initializer, so it is copy-initialized
from <code class="sourceCode cpp"><span class="op">{}</span></code>.</p>
<p>The strategy to handle <code class="sourceCode cpp">B<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>
is to group the indirect non-static data members under their
corresponding direct base class and to treat those base class elements
as being explicitly initialized. So here, the
<code class="sourceCode cpp">A</code> element is explicitly initialized
from <code class="sourceCode cpp"><span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span></code>
and the <code class="sourceCode cpp">b</code> element continues to be
explicitly initialized from
<code class="sourceCode cpp"><span class="dv">2</span></code>. And then
this applies recursively, so given:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">:</span> B <span class="op">{</span> <span class="dt">int</span> c; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>With <code class="sourceCode cpp">C<span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>c<span class="op">=</span><span class="dv">2</span><span class="op">}</span></code>,
we have:</p>
<ul>
<li>the <code class="sourceCode cpp">B</code> element is explicitly
initialized from <code class="sourceCode cpp"><span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span></code>,
which leads to:
<ul>
<li>the <code class="sourceCode cpp">A</code> element is explicitly
initialized from <code class="sourceCode cpp"><span class="op">{.</span>a<span class="op">=</span><span class="dv">1</span><span class="op">}</span></code>,
which leads to:
<ul>
<li>the <code class="sourceCode cpp">a</code> element is explicitly
initialized from
<code class="sourceCode cpp"><span class="dv">1</span></code></li>
</ul></li>
<li>the <code class="sourceCode cpp">b</code> element is not explicitly
initialized and has no default member initializer, so it is
copy-initialized from
<code class="sourceCode cpp"><span class="op">{}</span></code></li>
</ul></li>
<li>the <code class="sourceCode cpp">c</code> element is explicitly
initialized from
<code class="sourceCode cpp"><span class="dv">2</span></code></li>
</ul>
<h2 data-number="4.2" id="actual-wording"><span class="header-section-number">4.2</span> Actual Wording<a href="#actual-wording" class="self-link"></a></h2>
<p>Change the grammar in <span>9.5.1 <a href="https://wg21.link/dcl.init.general">[dcl.init.general]</a></span>/1
to allow a
<code class="sourceCode cpp"><em>designated-initializer-list</em></code>
to start with an
<code class="sourceCode cpp"><em>initializer-list</em></code>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb16"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="va">+ <em>designated-only-initializer-list</em>:</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>designated-initializer-clause</em></span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>designated-only-initializer-list</em> , <em>designated-initializer-clause</em></span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <em>designated-initializer-list</em>:</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="st">-   <em>designated-initializer-clause</em></span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="st">-   <em>designated-initializer-list</em> , <em>designated-initializer-clause</em></span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>designated-only-initializer-list</em></span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="va">+   <em>initializer-list</em> , <em>designated-only-initializer-list</em></span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add a new term after we define what an aggregate and the elements of
an aggregate are in <span>9.5.2 <a href="https://wg21.link/dcl.init.aggr">[dcl.init.aggr]</a></span> and
then extend the next sections.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">1</a></span>
An <em>aggregate</em> is […]</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">2</a></span>
The <em>elements</em> of an aggregate are: […]</p>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">x</a></span>
The <em>associated element</em> of a member
<code class="sourceCode cpp">M</code> of an aggregate
<code class="sourceCode cpp">T</code> is:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(x.1)</a></span>
<code class="sourceCode cpp">M</code> if
<code class="sourceCode cpp">M</code> is an element of
<code class="sourceCode cpp">T</code>;</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(x.2)</a></span>
otherwise, the element of <code class="sourceCode cpp">T</code> that
contains <code class="sourceCode cpp">M</code>.</li>
</ul>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<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">struct</span> A <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> a1;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> a2;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> a3;</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> b1;</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">double</span> b2;</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The associated element of each of the members
<code class="sourceCode cpp">A<span class="op">::</span>a1</code>,
<code class="sourceCode cpp">A<span class="op">::</span>a2</code>, and
<code class="sourceCode cpp">A<span class="op">::</span>a3</code> of
<code class="sourceCode cpp">B</code> is
<code class="sourceCode cpp">A</code>. The associated element of the
member <code class="sourceCode cpp">B<span class="op">::</span>b1</code>
of <code class="sourceCode cpp">B</code> is itself. The associated
element of the member
<code class="sourceCode cpp">B<span class="op">::</span>b2</code> of
<code class="sourceCode cpp">B</code> is the anonymous union containing
it.<span> — <em>end example</em> ]</span></p>
</div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">3</a></span>
When an aggregate is initialized by an initializer list as specified in
[dcl.init.list], the elements of the initializer list are taken as
initializers for the elements of the aggregate. The <em>explicitly
initialized elements</em> of the aggregate are determined as
follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(3.1)</a></span>
<span class="rm" style="color: #bf0303"><del>If the initializer list is
a brace-enclosed
<span><code class="sourceCode default"><em>designated-initializer-list</em></code></span></del></span>
<span class="addu">If the
<code class="sourceCode cpp"><em>braced-init-list</em></code> has a
<code class="sourceCode cpp"><em>designated-only-initializer-list</em></code>
within a
<code class="sourceCode cpp"><em>designated-initializer-list</em></code></span>,
the aggregate shall be of class type <span class="addu"><code class="sourceCode cpp"><em>C</em></code>.</span>
<span class="rm" style="color: #bf0303"><del>, the identifier in each
<span><code class="sourceCode default"><em>designator</em></code></span>
shall name a direct non-static data member of the class, and the
explicitly initialized elements of the aggregate are the elements that
are, or contain, those members.</del></span></p>
<div class="addu">
<p>For each <code class="sourceCode cpp"><em>designator</em></code>, the
lookup set for the
<code class="sourceCode cpp"><em>identifier</em></code> in
<code class="sourceCode cpp"><em>C</em></code> ([class.member.lookup])
shall comprise</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(3.1.1)</a></span>
a declaration set consisting of a single non-static data member and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(3.1.2)</a></span>
a subobject set containing only one subobject, whose type shall be an
aggregate base of <code class="sourceCode cpp"><em>C</em></code>. An
aggregate <code class="sourceCode cpp"><em>B</em></code> is an
<em>aggregate base</em> of a class
<code class="sourceCode cpp"><em>D</em></code> if it is
<code class="sourceCode cpp"><em>D</em></code> or a direct base class of
an aggregate base of
<code class="sourceCode cpp"><em>D</em></code>.</li>
</ul>
<p>That non-static data member is <em>designated</em> by the
<code class="sourceCode cpp"><em>identifier</em></code>. Each
<code class="sourceCode cpp"><em>initializer-clause</em></code>, if any,
shall appertain (see below) to a base class subobject of
<code class="sourceCode cpp"><em>C</em></code>. The explicitly
initialized elements of the aggregate include the associated elements of
each member <code class="sourceCode cpp"><em>M</em></code> of
<code class="sourceCode cpp"><em>C</em></code> for which
<code class="sourceCode cpp"><em>M</em></code> is designated by an
<code class="sourceCode cpp"><em>identifier</em></code> in a
<code class="sourceCode cpp"><em>designated-initializer-clause</em></code>.</p>
</div></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">(3.2)</a></span>
<span class="rm" style="color: #bf0303"><del>If the initializer list is
a brace-enclosed
<span><code class="sourceCode default"><em>initializer-list</em></code></span></del></span>
<span class="addu">If the
<code class="sourceCode cpp"><em>braced-init-list</em></code> has an
<code class="sourceCode cpp"><em>initializer-list</em></code> (possibly
within a
<code class="sourceCode cpp"><em>designated-initializer-list</em></code>)</span>,
the explicitly initialized elements of the aggregate <span class="rm" style="color: #bf0303"><del>are</del></span> <span class="addu">include</span> those for which an element of the
initializer list appertains to the aggregate element or to a subobject
thereof (see below).</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">(3.3)</a></span>
<span class="rm" style="color: #bf0303"><del>Otherwise, the initializer
list must be <span><code class="sourceCode default">{}</code></span>,
and there are no explicitly initialized elements.</del></span> <span class="addu">No other elements of the aggregate are explicitly
initialized. <span class="note"><span>[ <em>Note 1:</em> </span>The
initializer
<code class="sourceCode cpp"><span class="op">{}</span></code> does not
explicitly initialize any elements of the aggregate.<span> — <em>end
note</em> ]</span></span></span></p></li>
</ul>
<div class="addu">
<p>If any element of the aggregate is explicitly initialized by both an
<code class="sourceCode cpp"><em>initializer-list</em></code> and a
<code class="sourceCode cpp"><em>designated-initializer-list</em></code>,
the program is ill-formed. If a non-static data member is explicitly
initialized by an
<code class="sourceCode cpp"><em>initializer-list</em></code>, a
<code class="sourceCode cpp"><em>designated-only-initializer-list</em></code>
shall not be present.</p>
<div class="example">
<span>[ <em>Example 2:</em> </span>
<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">struct</span> A <span class="op">{</span> <span class="dt">int</span> a1, a2; <span class="op">}</span>;</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> b; <span class="op">}</span>;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">:</span> A <span class="op">{</span> <span class="dt">int</span> a1; <span class="op">}</span>;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>B v1 <span class="op">=</span> B<span class="op">{.</span>a1<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">2</span><span class="op">}</span>;         <span class="co">// the explicitly initialized elements are [A, B::b]</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>B v2 <span class="op">=</span> B<span class="op">{.</span>a1<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>a2<span class="op">=</span><span class="dv">2</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;  <span class="co">// the explicitly initialized elements are [A, B::b]</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>B v3 <span class="op">=</span> B<span class="op">{</span>A<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;       <span class="co">// the explicitly initialized elements are [A, B::b]</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>B v4 <span class="op">=</span> B<span class="op">{</span>A<span class="op">{}</span>, <span class="op">.</span>a2<span class="op">=</span><span class="dv">1</span>, <span class="op">.</span>b<span class="op">=</span><span class="dv">3</span><span class="op">}</span>;    <span class="co">// error: A initialized two different ways</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>C v5 <span class="op">=</span> C<span class="op">{.</span>a1<span class="op">=</span><span class="dv">4</span><span class="op">}</span>;               <span class="co">// the explicitly initialized elements are [C::a1]</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">4</a></span>
For each explicitly initialized element:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(4.1)</a></span>
If the element is an anonymous union member and <span class="rm" style="color: #bf0303"><del>the initializer list is a brace-enclosed
<span><code class="sourceCode default"><em>designated-initializer-list</em></code></span></del></span>
<span class="addu">is explicitly initialized by a
<code class="sourceCode cpp"><em>designated-only-initializer-list</em></code></span>,
the element is initialized by the <code class="sourceCode cpp"><em>braced-init-list</em> <span class="op">{</span> <em>D</em> <span class="op">}</span></code>,
where <code class="sourceCode cpp"><em>D</em></code> is the
<code class="sourceCode cpp"><em>designated-initializer-clause</em></code>
<span class="addu">whose associated element is the anonymous union
member</span> <span class="rm" style="color: #bf0303"><del>naming a
member of the anonymous union member</del></span>. There shall be only
one such
<code class="sourceCode cpp"><em>designated-initializer-clause</em></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(4.2)</a></span>
Otherwise, if the <span class="rm" style="color: #bf0303"><del>initializer list is a brace-enclosed
<span><code class="sourceCode default"><em>designated-initializer-list</em></code></span></del></span>
<span class="addu">element is explicitly initialized by a
<code class="sourceCode cpp"><em>designated-only-initializer-list</em></code>,
then</span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">(4.2.1)</a></span>
<span class="addu">if the element is a direct, non-static data member,
then</span> the element is initialized with the
<code class="sourceCode cpp"><em>brace-or-equal-initializer</em></code>
of the corresponding
<code class="sourceCode cpp"><em>designated-initializer-clause</em></code>.
If that initializer is of the form <code class="sourceCode cpp"><span class="op">=</span> <em>assignment-expression</em></code>
and a narrowing conversion ([dcl.init.list]) is required to convert the
expression, the program is ill-formed. <span class="note"><span>[ <em>Note 2:</em> </span>The form of the initializer
determines whether copy-initialization or direct-initialization is
performed.<span> — <em>end note</em> ]</span></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(4.2.2)</a></span>
<span class="addu">otherwise, the element is a base class subobject
<code class="sourceCode cpp"><em>B</em></code>, and is copy-initialized
from a brace-enclosed
<code class="sourceCode cpp"><em>designated-initializer-list</em></code>
consisting of all of the
<code class="sourceCode cpp"><em>designated-initializer-clause</em></code>s
whose associated element is
<code class="sourceCode cpp"><em>B</em></code>, in
order.</span></p></li>
</ul>
<div class="addu">
<div class="example">
<span>[ <em>Example 3:</em> </span>
<div class="sourceCode" id="cb19"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>struct A { int a; };</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>struct B : A { int b; };</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>struct C : B { int c; };</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>// the A element is initialized from {.a=1}</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>B x = B{.a=1};</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>// the B element is initialized from {.a=2, .b=3}</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>// which leads to its A element being initialized from {.a=2}</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>C y = C{.a=2, .b=3, .c=4};</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</div></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">(4.3)</a></span>
Otherwise, the <span class="rm" style="color: #bf0303"><del>initializer
list is a brace-enclosed
<span><code class="sourceCode default"><em>initializer-list</em></code></span></del></span>
<span class="addu">element is explicitly initialized by an
<code class="sourceCode cpp"><em>initializer-list</em></code></span>.
[…]</p></li>
</ul>
</blockquote>
</div>
<p>Extend <span>9.5.5 <a href="https://wg21.link/dcl.init.list">[dcl.init.list]</a></span>/3.1:</p>
<div class="std">
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">(3.1)</a></span>
If the <em>braced-init-list</em> contains a
<em>designated-initializer-list</em>,
<code class="sourceCode cpp">T</code> shall be an aggregate class. The
<span class="addu">associated elements of the non-static data members
designated by the</span> ordered <em>identifier</em>s in the designators
of the <em>designated-initializer-list</em> shall <span class="rm" style="color: #bf0303"><del>form a subsequence of the ordered
<span><code class="sourceCode default"><em>identifiers</em></code></span>
in the direct non-static data members</del></span> <span class="addu">be
in non-decreasing declaration order</span>. Aggregate initialization is
performed ([dcl.init.aggr]).</p>
<div class="example">
<span>[ <em>Example 4:</em> </span>
<div>
<div class="sourceCode" id="cb20"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>    struct A { int x; int y; int z; };</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    A a{.y = 2, .x = 1};                // error: designator order does not match declaration order</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    A b{.x = 1, .z = 2};                // OK, b.y initialized to 0</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct B : A { int q; };</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="va">+   B e{.x = 1, .q = 3};                // OK, e.y and e.z initialized to 0</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   B f{.q = 3, .x = 1};                // error: designator order does not match declaration order</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct C { int p; int x; };</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct D : A, C { };</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="va">+   D g{.y=1, .p=2};                    // OK</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="va">+   D h{.x=2};                          // error: ambiguous lookup for x</span></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="va">+   struct NonAggr { int na; NonAggr(int); };</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a><span class="va">+   struct E : NonAggr { int e; };</span></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a><span class="va">+   E i{.na=1, .e=2};                   // error: the lookup set for na finds NonAggr, which is not an aggregate base of E</span></span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div></li>
</ul>
</blockquote>
</div>
<p>And update paragraph 14, since now we can have
<code class="sourceCode cpp"><em>initializer-clause</em></code>s in
<code class="sourceCode cpp"><em>designated-initializer-list</em></code>s
too:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">14</a></span>
Each <code class="sourceCode cpp"><em>initializer-clause</em></code> in
a <span class="rm" style="color: #bf0303"><del>brace-enclosed
<span><code class="sourceCode default"><em>initializer-list</em></code></span></del></span>
<span class="addu"><code class="sourceCode cpp"><em>braced-init-list</em></code></span>
is said to <em>appertain</em> to an element of the aggregate being
initialized or to an element of one of its subaggregates.</p>
</blockquote>
</div>
<p>Add an Annex C entry:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><strong>Affected sublcause</strong>: [dcl.init] <br />
<strong>Change</strong>: Support for designated initialization of base
classes of aggregates. <br /> <strong>Rationale</strong>: New
functionality. <br /> <strong>Effect on original feature</strong>: Some
valid C++23 code may fail to compile. For example:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>struct A { int a; };</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>struct B : A { int b; };</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>void f(A); // #1</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>void f(B); // #2</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>void g() {</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    f({.a=1}); // ambiguous between #1 and #2; previously called #1</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
</blockquote>
</div>
<h2 data-number="4.3" id="feature-test-macro"><span class="header-section-number">4.3</span> Feature-test Macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>Bump
<code class="sourceCode cpp">__cpp_­designated_­initializers</code> in
<span>15.12 <a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span>:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb22"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="st">- __cpp_­designated_­initializers <span class="diffdel">201707L</span></span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ __cpp_­designated_­initializers <span class="diffins">2025XXL</span></span></span></code></pre></div>
</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 Matthias Stearn for, basically, the proposal. Thanks to Tim
Song for helping with design questions and wording. Thanks to Brian Bi
and Davis Herring for a lot of help with the wording.</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-P0017R1" class="csl-entry" role="doc-biblioentry">
[P0017R1] Oleg Smolsky. 2015-10-24. Extension to aggregate
initialization. <a href="https://wg21.link/p0017r1"><div class="csl-block">https://wg21.link/p0017r1</div></a>
</div>
<div id="ref-P0329R4" class="csl-entry" role="doc-biblioentry">
[P0329R4] Tim Shen, Richard Smith. 2017-07-12. Designated Initialization
Wording. <a href="https://wg21.link/p0329r4"><div class="csl-block">https://wg21.link/p0329r4</div></a>
</div>
<div id="ref-P2287R0" class="csl-entry" role="doc-biblioentry">
[P2287R0] Barry Revzin. 2021-01-21. Designated-initializers for base
classes. <a href="https://wg21.link/p2287r0"><div class="csl-block">https://wg21.link/p2287r0</div></a>
</div>
<div id="ref-P2287R1" class="csl-entry" role="doc-biblioentry">
[P2287R1] Barry Revzin. 2021-02-15. Designated-initializers for base
classes. <a href="https://wg21.link/p2287r1"><div class="csl-block">https://wg21.link/p2287r1</div></a>
</div>
<div id="ref-P2287R2" class="csl-entry" role="doc-biblioentry">
[P2287R2] Barry Revzin. 2023-03-12. Designated-initializers for base
classes. <a href="https://wg21.link/p2287r2"><div class="csl-block">https://wg21.link/p2287r2</div></a>
</div>
<div id="ref-P2287R3" class="csl-entry" role="doc-biblioentry">
[P2287R3] Barry Revzin. 2024-09-10. Designated-initializers for base
classes. <a href="https://wg21.link/p2287r3"><div class="csl-block">https://wg21.link/p2287r3</div></a>
</div>
<div id="ref-P2287R4" class="csl-entry" role="doc-biblioentry">
[P2287R4] Barry Revzin. 2025-03-11. Designated-initializers for base
classes. <a href="https://wg21.link/p2287r4"><div class="csl-block">https://wg21.link/p2287r4</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
