<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-04-14" />
  <title>trivial union (was std::uninitialized&lt;T&gt;)</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: #ffdddd;
--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: #FFC8EB;
border: none; }
code del { border: 1px solid #ECB3C7; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center"><code class="sourceCode cpp">trivial <span class="kw">union</span></code> (was
<code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>)</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3074R3</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-04-14</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
    </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="#the-uninitialized-storage-problem" id="toc-the-uninitialized-storage-problem"><span class="toc-section-number">2.1</span> The uninitialized storage
problem<span></span></a></li>
</ul></li>
<li><a href="#design-space" id="toc-design-space"><span class="toc-section-number">3</span> Design Space<span></span></a>
<ul>
<li><a href="#a-library-type-stduninitializedt" id="toc-a-library-type-stduninitializedt"><span class="toc-section-number">3.1</span> A library type: <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code><span></span></a></li>
<li><a href="#a-language-annotation" id="toc-a-language-annotation"><span class="toc-section-number">3.2</span> A language
annotation<span></span></a></li>
<li><a href="#just-make-it-work" id="toc-just-make-it-work"><span class="toc-section-number">3.3</span> Just make it
work<span></span></a></li>
<li><a href="#trivial-unions" id="toc-trivial-unions"><span class="toc-section-number">3.4</span> Trivial
Unions<span></span></a></li>
<li><a href="#existing-practice" id="toc-existing-practice"><span class="toc-section-number">3.5</span> Existing
Practice<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="#wording-for-just-making-it-work" id="toc-wording-for-just-making-it-work"><span class="toc-section-number">4.1</span> Wording for just making it
work<span></span></a></li>
<li><a href="#wording-for-trivial-union" id="toc-wording-for-trivial-union"><span class="toc-section-number">4.2</span> Wording for <code class="sourceCode cpp">trivial <span class="kw">union</span></code><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="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span>
Revision History<a href="#revision-history" class="self-link"></a></h1>
<p><span class="citation" data-cites="P3074R0">[<a href="https://wg21.link/p3074r0" role="doc-biblioref">P3074R0</a>]</span> originally proposed the
function <code class="sourceCode cpp">std<span class="op">::</span>start_lifetime<span class="op">(</span>p<span class="op">)</span></code>.
This revision adds a new section discussing the <a href="#the-uninitialized-storage-problem">uninitialized storage
problem</a>, which motivates a change in design to instead propose <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.</p>
<p><span class="citation" data-cites="P3074R1">[<a href="https://wg21.link/p3074r1" role="doc-biblioref">P3074R1</a>]</span> changed to propose <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
and was discussed in an EWG telecon. There, the suggestion was made to
make this a language feature, which this revision discusses and argues
against. Also re-spelled <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
to be a union instead of a class containing an anonymous union.</p>
<p><span class="citation" data-cites="P3074R2">[<a href="https://wg21.link/p3074r2" role="doc-biblioref">P3074R2</a>]</span> still argued for <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.
This revision changes to instead proposing a language change to unions
to solve the problems presented.</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>Consider the following example:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> U <span class="op">{</span> <span class="kw">constexpr</span> U<span class="op">()</span> <span class="op">{</span> <span class="op">}</span> <span class="kw">constexpr</span> <span class="op">~</span>U<span class="op">()</span> <span class="op">{</span> <span class="op">}</span> T storage<span class="op">[</span>N<span class="op">]</span>; <span class="op">}</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    U u;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// note: we are *not* constructing storage</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> FixedVector<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="op">~</span>FixedVector<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>destroy<span class="op">(</span>u<span class="op">.</span>storage, u<span class="op">.</span>storage<span class="op">+</span>size<span class="op">)</span>;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> push_back<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> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>construct_at<span class="op">(</span>u<span class="op">.</span>storage <span class="op">+</span> size, v<span class="op">)</span>;</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>size;</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> silly_test<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">size_t</span> <span class="op">{</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    FixedVector<span class="op">&lt;</span>std<span class="op">::</span>string, <span class="dv">3</span><span class="op">&gt;</span> v;</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    v<span class="op">.</span>push_back<span class="op">(</span><span class="st">&quot;some sufficiently longer string&quot;</span><span class="op">)</span>;</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> v<span class="op">.</span>size;</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>silly_test<span class="op">()</span> <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This is basically how any static/non-allocating/in-place vector is
implemented: we have some storage, that we <em>definitely do not value
initialize</em> and then we steadily construct elements into it.</p>
<p>The problem is that the above does not work (although there is <a href="https://godbolt.org/z/a3318n63v">implementation divergence</a> -
MSVC and EDG accept it and GCC did accept it even up to 13.2, but GCC
trunk and Clang reject).</p>
<p>Getting this example to work would allow <code class="sourceCode cpp">std<span class="op">::</span>inplace_vector</code>
(<span class="citation" data-cites="P0843R9">[<a href="https://wg21.link/p0843r9" role="doc-biblioref">P0843R9</a>]</span>) to simply work during
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
time for all times (instead of just trivial ones), and was a problem
briefly touched on in <span class="citation" data-cites="P2747R0">[<a href="https://wg21.link/p2747r0" role="doc-biblioref">P2747R0</a>]</span>.</p>
<h2 data-number="2.1" id="the-uninitialized-storage-problem"><span class="header-section-number">2.1</span> The uninitialized storage
problem<a href="#the-uninitialized-storage-problem" class="self-link"></a></h2>
<p>A closely related problem to the above is: how do you do
uninitialized storage? The straightforward implementation would be to
do:</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">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BufferStorage <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">alignas</span><span class="op">(</span>T<span class="op">)</span> <span class="dt">unsigned</span> <span class="dt">char</span> buffer<span class="op">[</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)]</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// accessors</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This approach generally works, but it has two limitations:</p>
<ol type="1">
<li>it cannot work in
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
and that’s likely a fundamental limitation that will never change,
and</li>
<li>it does not quite handle overlapping objects correctly.</li>
</ol>
<p>What I mean by the second one is basically given this structure:</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">struct</span> Empty <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">struct</span> Sub <span class="op">:</span> Empty <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    BufferStorage<span class="op">&lt;</span>Empty<span class="op">&gt;</span> buffer_storage;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>If we initialize the <code class="sourceCode cpp">Empty</code> that
<code class="sourceCode cpp">buffer_storage</code> is intended to have,
then <code class="sourceCode cpp">Sub</code> has two subobjects of type
<code class="sourceCode cpp">Empty</code>. But the compiler doesn’t
really… know that, and doesn’t adjust them accordingly. As a result, the
<code class="sourceCode cpp">Empty</code> base class subobject and the
<code class="sourceCode cpp">Empty</code> initialized in
<code class="sourceCode cpp">buffer_storage</code> are at the same
address, which violates the rule that all objects of one type are at
unique addresses.</p>
<p>An alternative approach to storage is to use a
<code class="sourceCode cpp"><span class="kw">union</span></code>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> UnionStorage <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">union</span> <span class="op">{</span> T value; <span class="op">}</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// accessors</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Sub <span class="op">:</span> Empty <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    UnionStorage<span class="op">&lt;</span>Empty<span class="op">&gt;</span> union_storage;</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Here, now the compiler knows for sure there is an
<code class="sourceCode cpp">Empty</code> in
<code class="sourceCode cpp">union_storage</code> and will lay out the
types appropriately. See also <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112591">gcc bug
112591</a>.</p>
<p>So it seems that the <code class="sourceCode cpp">UnionStorage</code>
approach is strictly superior: it will work in constexpr and it lays out
overlapping types properly. But it has limitations of its own. As with
the <code class="sourceCode cpp">FixedVector</code> example earlier, you
cannot just start the lifetime of
<code class="sourceCode cpp">value</code>. But also in this case we run
into the
<code class="sourceCode cpp"><span class="kw">union</span></code> rules
for special member functions: a special member of a
<code class="sourceCode cpp"><span class="kw">union</span></code>, by
default, is either trivial (if that special member for all alternatives
is trivial) or deleted (otherwise). Which means that <code class="sourceCode cpp">UnionStorage<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span></code>
has both its constructor and destructor <em>deleted</em>.</p>
<p>We can work around this by simply adding an empty constructor and
destructor (as shown earlier as well):</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">class</span> T<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> UnionStorage2 <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">union</span> U <span class="op">{</span> U<span class="op">()</span> <span class="op">{</span> <span class="op">}</span> <span class="op">~</span>U<span class="op">()</span> <span class="op">{</span> <span class="op">}</span> T value; <span class="op">}</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  U u;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// accessors</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This is a fundamentally weird concept since
<code class="sourceCode cpp">U</code> there has a destructor that does
nothing (and given that this is a class to be used for uninitialized
storage), it <em>should</em> do nothing - that’s correct. But that
destructor still isn’t trivial. And it turns out there is still a
difference between “destructor that does nothing” and “trivial
destructor”:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Trivially Destructible</strong>
</div></th>
<th><div style="text-align:center">
<strong>Non-trivially Destructible</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="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">auto</span> alloc_a<span class="op">(</span><span class="dt">int</span> n<span class="op">)</span> <span class="op">-&gt;</span> A<span class="op">*</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">new</span> A<span class="op">[</span>n<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> del<span class="op">(</span>A<span class="op">*</span> p<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span> <span class="kw">delete</span> <span class="op">[]</span> p; <span class="op">}</span></span></code></pre></div>

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

<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> B <span class="op">{</span> <span class="op">~</span>B<span class="op">()</span> <span class="op">{</span> <span class="op">}</span> <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> alloc_b<span class="op">(</span><span class="dt">int</span> n<span class="op">)</span> <span class="op">-&gt;</span> B<span class="op">*</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">new</span> B<span class="op">[</span>n<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> del<span class="op">(</span>B<span class="op">*</span> p<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span> <span class="kw">delete</span> <span class="op">[]</span> p; <span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb1"><pre class="sourceCode asm"><code class="sourceCode fasm"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>alloc_a<span class="op">(</span>int<span class="op">):</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>        <span class="bu">movsx</span>   <span class="kw">rdi</span><span class="op">,</span> <span class="kw">edi</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">jmp</span>     operator new<span class="op">[](</span>unsigned long<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>del<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="bu">test</span>    <span class="kw">rdi</span><span class="op">,</span> <span class="kw">rdi</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">je</span>      <span class="op">.</span>L3</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">jmp</span>     operator delete<span class="op">[](</span>void<span class="op">*)</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">.L3:</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">ret</span></span></code></pre></div>

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

<div class="sourceCode" id="cb2"><pre class="sourceCode asm"><code class="sourceCode fasm"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>alloc_b<span class="op">(</span>int<span class="op">):</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>        movabs  <span class="kw">rax</span><span class="op">,</span> <span class="dv">9223372036854775800</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">push</span>    <span class="kw">rbx</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">movsx</span>   <span class="kw">rbx</span><span class="op">,</span> <span class="kw">edi</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">cmp</span>     <span class="kw">rax</span><span class="op">,</span> <span class="kw">rbx</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">lea</span>     <span class="kw">rdi</span><span class="op">,</span> <span class="op">[</span><span class="kw">rbx</span><span class="op">+</span><span class="dv">8</span><span class="op">]</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span>     <span class="kw">rax</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">cmovb</span>   <span class="kw">rdi</span><span class="op">,</span> <span class="kw">rax</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">call</span>    operator new<span class="op">[](</span>unsigned long<span class="op">)</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span>     <span class="dt">QWORD</span> <span class="dt">PTR</span> <span class="op">[</span><span class="kw">rax</span><span class="op">],</span> <span class="kw">rbx</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        <span class="bu">add</span>     <span class="kw">rax</span><span class="op">,</span> <span class="dv">8</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">pop</span>     <span class="kw">rbx</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">ret</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>del<span class="op">(</span>B<span class="op">*):</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>        <span class="bu">test</span>    <span class="kw">rdi</span><span class="op">,</span> <span class="kw">rdi</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">je</span>      <span class="op">.</span>L9</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>        <span class="bu">mov</span>     <span class="kw">rax</span><span class="op">,</span> <span class="dt">QWORD</span> <span class="dt">PTR</span> <span class="op">[</span><span class="kw">rdi</span><span class="op">-</span><span class="dv">8</span><span class="op">]</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>        <span class="bu">sub</span>     <span class="kw">rdi</span><span class="op">,</span> <span class="dv">8</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>        <span class="bu">lea</span>     <span class="kw">rsi</span><span class="op">,</span> <span class="op">[</span><span class="kw">rax</span><span class="op">+</span><span class="dv">8</span><span class="op">]</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">jmp</span>     operator delete<span class="op">[](</span>void<span class="op">*,</span> unsigned long<span class="op">)</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="fu">.L9:</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">ret</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>That’s a big difference in code-gen, due to the need to put a cookie
in the allocation so that the corresponding <code class="sourceCode cpp"><span class="kw">delete</span><span class="op">[]</span></code>
knows how many elements there so that their destructors (even though
they do nothing!) can be invoked.</p>
<p>While the union storage solution solves some language problems for
us, the buffer storage solution can lead to more efficient code -
because <code class="sourceCode cpp">StorageBuffer<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is always trivially destructible. It would be nice if he had a good
solution to all of these problems - and that solution was also the most
efficient one.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="design-space"><span class="header-section-number">3</span> Design
Space<a href="#design-space" class="self-link"></a></h1>
<p>There are several potential solutions in this space:</p>
<ol type="1">
<li>a library solution (add a <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>)</li>
<li>a language solution (add some annotation to members to mark them
uninitialized, as distinct from
<code class="sourceCode cpp"><span class="kw">union</span></code>s)</li>
<li>just make it work (change the union rules to implicitly start the
lifetime of the first alternative, if it’s an implicit-lifetime
type)</li>
<li>introduce a new kind of union</li>
<li>provide an explicit function to start lifetime of a union
alternative (<code class="sourceCode cpp">std<span class="op">::</span>start_lifetime</code>).</li>
</ol>
<p>The first revision of this paper (<span class="citation" data-cites="P3074R0">[<a href="https://wg21.link/p3074r0" role="doc-biblioref">P3074R0</a>]</span>) proposed that last option.
However, with the addition of the overlapping subobjects problem and the
realization that the union solution has overhead compared to the buffer
storage solution, it would be more desirable to solve both problems in
one go. That is, it’s not enough to just start the lifetime of the
alternative, we also want a trivially constructible/destructible
solution for uninitialized storage.</p>
<p><span class="citation" data-cites="P3074R1">[<a href="https://wg21.link/p3074r1" role="doc-biblioref">P3074R1</a>]</span> and <span class="citation" data-cites="P3074R2">[<a href="https://wg21.link/p3074r2" role="doc-biblioref">P3074R2</a>]</span> proposed the first solution
(<code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>).
This revision proposes the third or fourth.</p>
<p>Let’s go over some of the solutions.</p>
<h2 data-number="3.1" id="a-library-type-stduninitializedt"><span class="header-section-number">3.1</span> A library type: <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code><a href="#a-library-type-stduninitializedt" class="self-link"></a></h2>
<p>We could introduce another magic library type, <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
with an interface like:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> uninitialized <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-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="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>As basically a better version of <code class="sourceCode cpp">std<span class="op">::</span>aligned_storage</code>.
Here is storage for a <code class="sourceCode cpp">T</code>, that
implicitly begins its lifetime if <code class="sourceCode cpp">T</code>
is an implicit-lifetime-type, but otherwise will not actually initialize
it for you - you have to do that yourself. Likewise it will not destroy
it for you, you have to do that yourself too. This type would be
specified to always be trivially default constructible and trivially
destructible. It would be trivially copyable if
<code class="sourceCode cpp">T</code> is trivially copyable, otherwise
not copyable.</p>
<p><code class="sourceCode cpp">std<span class="op">::</span>inplace_vector<span class="op">&lt;</span>T, N<span class="op">&gt;</span></code>
would then have a <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">[</span>N<span class="op">]&gt;</span></code>
and go ahead and <code class="sourceCode cpp">std<span class="op">::</span>construct_at</code>
(or, with <span class="citation" data-cites="P2747R2">[<a href="https://wg21.link/p2747r2" role="doc-biblioref">P2747R2</a>]</span>, simply placement-new) into the
appropriate elements of that array and everything would just work.</p>
<p>Because the language would recognize this type, this would also solve
the overlapping objects problem.</p>
<h2 data-number="3.2" id="a-language-annotation"><span class="header-section-number">3.2</span> A language annotation<a href="#a-language-annotation" class="self-link"></a></h2>
<p>During the EWG telecon in <a href="https://wiki.edg.com/bin/view/Wg21telecons2024/P3074R1-EWG">January
2023</a>, the suggestion was made that instead of a magic library type
like <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
we could instead have some kind of language annotation to achieve the
same effect.</p>
<p>For example:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// as a library feature</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">[</span>N<span class="op">]&gt;</span> lib;</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">//as a language feature, something like this</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> storage T lang<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    T storage<span class="op">[</span>N<span class="op">]</span> <span class="op">=</span> <span class="cf">for</span> lang;</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    T storage<span class="op">[</span>N<span class="op">]</span> <span class="op">=</span> <span class="dt">void</span>;</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    uninitialized T lang<span class="op">[</span>N<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="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The advantage of the language syntax is that you can directly use
<code class="sourceCode cpp">lang</code> - you would placement new onto
<code class="sourceCode cpp">lang<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>,
you read from <code class="sourceCode cpp">lang<span class="op">[</span><span class="dv">1</span><span class="op">]</span></code>,
etc, whereas with the library syntax you have to placement new onto
<code class="sourceCode cpp">lib<span class="op">.</span>value<span class="op">[</span><span class="dv">0</span><span class="op">]</span></code>
and read from <code class="sourceCode cpp">lib<span class="op">.</span>value<span class="op">[</span><span class="dv">1</span><span class="op">]</span></code>,
etc.</p>
<p>In that telecon, there was preference (including by me) for the
language solution:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>5</td>
<td>4</td>
<td>4</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>However, an uninitialized object of type
<code class="sourceCode cpp">T</code> really isn’t the same thing as a
<code class="sourceCode cpp">T</code>. <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>lang<span class="op">)</span></code>
would have to be <code class="sourceCode cpp">T</code>, any kind of
(imminent) reflection over this type would give you a
<code class="sourceCode cpp">T</code>. But there might not actually be a
<code class="sourceCode cpp">T</code> there yet, it behaves like a <code class="sourceCode cpp"><span class="kw">union</span> <span class="op">{</span> T; <span class="op">}</span></code>
rather than a <code class="sourceCode cpp">T</code>, so spelling it
<code class="sourceCode cpp">T</code> strikes me as misleading.</p>
<p>We would have to ensure that all the other member-wise algorithms we
have today (the special member functions and the comparisons) use the
“uninitialized <code class="sourceCode cpp">T</code>” meaning rather
than the <code class="sourceCode cpp">T</code> meaning. And with
reflection, that also means all future member-wise algorithms would have
to account for this also - rather than rejecting
<code class="sourceCode cpp"><span class="kw">union</span></code>s. This
seems to open the door to a lot of mistakes.</p>
<p>The syntactic benefits of the language syntax are nice, but this is a
rarely used type for specific situations - so having slightly longer
syntax (and really,
<code class="sourceCode cpp">lib<span class="op">.</span>value</code> is
not especially cumbersome) is not only not a big downside here but could
even be viewed as a benefit.</p>
<p>For this reason, R2 of this paper still proposed <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as the solution in preference to any language annotation. This did not
go over well in <a href="https://github.com/cplusplus/papers/issues/1734#issuecomment-2012474793">Tokyo</a>,
where again there was preference for the language solution:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>6</td>
<td>7</td>
<td>3</td>
<td>4</td>
<td>2</td>
</tr>
</tbody>
</table>
<p>This leads to…</p>
<h2 data-number="3.3" id="just-make-it-work"><span class="header-section-number">3.3</span> Just make it work<a href="#just-make-it-work" class="self-link"></a></h2>
<p>Now, for the <code class="sourceCode cpp">inplace_vector</code>
problem, today’s
<code class="sourceCode cpp"><span class="kw">union</span></code> is
insufficient:</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span> T storage<span class="op">[</span>N<span class="op">]</span>; <span class="op">}</span>;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Similarly a simple <code class="sourceCode cpp"><span class="kw">union</span> <span class="op">{</span> T storage; <span class="op">}</span></code>
is insufficient for the uninitialized storage problem.</p>
<p>There are three reasons for this:</p>
<ol type="1">
<li>the default constructor can be deleted (this can be easily worked
around though)</li>
<li>the default constructor does not start the lifetime of implicit
lifetime types</li>
<li>the destructor can be deleted (this can be worked around by
providing a no-op destructor, which has ABI cost that cannot be worked
around)</li>
</ol>
<p>However, what if instead of coming up with a solution for these
problems, we just… made it work?</p>
<p>That is, change the union rules as follows:</p>
<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>member</strong>
</div></th>
<th><div style="text-align:center">
<strong>status quo</strong>
</div></th>
<th><div style="text-align:center">
<strong>new rule</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>default constructor<br />(absent default member initializers)</td>
<td>If all the alternatives are trivially default constructible,
trivial.<br />Otherwise, deleted.</td>
<td>If the first alternative is an implicit-lifetime type, trivial and
starts the lifetime of that alternative and sets it as the active
member.<br />Otherwise, if all the alternatives are trivially default
constructible, trivial.<br />Otherwise, deleted.</td>
</tr>
<tr class="even">
<td>destructor</td>
<td>If all the alternatives are trivially destructible,
trivial.<br />Otherwise, deleted.</td>
<td>If the first alternative is an implicit-lifetime type or if all the
alternatives are trivially default constructible,
trivial.<br />Otherwise, deleted.</td>
</tr>
</tbody>
</table>
<p>This attempt at a minimal extension works fine for the
<code class="sourceCode cpp">inplace_vector</code> example where we want
a union holding a <code class="sourceCode cpp">T<span class="op">[</span>N<span class="op">]</span></code>.
Such a union would become trivially default constructible (and start the
lifetime of the array) and trivially destructible, as desired. But it
has odd effects for the typical uninitialized storage case:</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="co">// default constructor and destructor are both deleted</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U1 <span class="op">{</span> std<span class="op">::</span>string s; <span class="op">}</span>;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">// default constructor and destructor are both trivial</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U2 <span class="op">{</span> std<span class="op">::</span>string a<span class="op">[</span><span class="dv">1</span><span class="op">]</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>For uninitialized storage, we really want trivial
construction/destruction. And it would be nice to not have to resort to
having members of type <code class="sourceCode cpp">T<span class="op">[</span><span class="dv">1</span><span class="op">]</span></code>
instead of <code class="sourceCode cpp">T</code> to achieve this. But I
really don’t think it’s a good idea to just make all unions trivially
constructible and destructible. Seems a bit too late for that.
However…</p>
<h2 data-number="3.4" id="trivial-unions"><span class="header-section-number">3.4</span> Trivial Unions<a href="#trivial-unions" class="self-link"></a></h2>
<p>What if we introduced a new kind of union, with special annotation?
That is:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    trivial <span class="kw">union</span> <span class="op">{</span> T storage<span class="op">[</span>N<span class="op">]</span>; <span class="op">}</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>With the rule that a trivial union is just always trivially default
constructible, trivially destructible, and, if the first alternative is
implicit-lifetime, starts the lifetime of that alternative (and sets it
to be the active member).</p>
<p>This is a language solution that doesn’t have any of the consequences
for memberwise algorithms - since we’re still a
<code class="sourceCode cpp"><span class="kw">union</span></code>. It
provides a clean solution to the uninitialized storage problem, the
aliasing problem, and the constexpr
<code class="sourceCode cpp">inplace_vector</code> storage problem.
Without having to deal with potentially changing behavior of existing
unions.</p>
<p>This brings up the question about default member initializers. Should
a <code class="sourceCode cpp">trivial <span class="kw">union</span></code> be
allowed to have a default member initializer? I don’t think so. If
you’re initializing the thing, it’s not really uninitialized storage
anymore. Use a regular union.</p>
<p>An alternative spelling for this might be <code class="sourceCode cpp">uninitialized <span class="kw">union</span></code>
instead of <code class="sourceCode cpp">trivial <span class="kw">union</span></code>. An
alternative alternative would be to instead provide a different way of
declaring the constructor and destructor:</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">union</span> U <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  U<span class="op">()</span> <span class="op">=</span> trivial;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>U<span class="op">()</span> <span class="op">=</span> trivial;</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>  T storage<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>This is explicit (unlike <a href="#just-make-it-work">just making it
work</a>), but seems unnecessary much to type compared to a single
<code class="sourceCode cpp">trivial</code> token - and these things
really aren’t orthogonal. Plus it wouldn’t allow for anonymous trivial
unions, which seems like a nice usability gain.</p>
<h2 data-number="3.5" id="existing-practice"><span class="header-section-number">3.5</span> Existing Practice<a href="#existing-practice" class="self-link"></a></h2>
<p>There are three similar features in other languages that I’m aware
of.</p>
<p>Rust has <a href="https://doc.rust-lang.org/std/mem/union.MaybeUninit.html"><code class="sourceCode cpp">MaybeUninit<span class="op">&lt;</span>T<span class="op">&gt;</span></code></a>
which is similar to what’s described here as <code class="sourceCode cpp">std<span class="op">::</span>uninitialized<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.</p>
<p>Kotlin has a <a href="https://kotlinlang.org/docs/properties.html#late-initialized-properties-and-variables"><code class="sourceCode cpp">lateinit var</code></a>
language feature, which is similar to some kind of language annotation
(although additionally allows for checking whether it has been
initialized, which the language feature would not provide).</p>
<p>D has the ability to initialize a variable to
<code class="sourceCode cpp"><span class="dt">void</span></code>, as in
<code class="sourceCode cpp"><span class="dt">int</span> x <span class="op">=</span> <span class="dt">void</span>;</code>
This leaves <code class="sourceCode cpp">x</code> uninitialized.
However, this feature only affects construction - not destruction. A
member <code class="sourceCode cpp">T<span class="op">[</span>N<span class="op">]</span> storage <span class="op">=</span> <span class="dt">void</span>;</code>
would leave the array uninitialized, but would destroy the whole array
in the destructor. So not really suitable for this particular
purpose.</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 paper now proposes support for a new kind of union: <a href="#trivial-unions">trivial union</a> with the following rules:</p>
<ul>
<li>a <code class="sourceCode cpp"><span class="kw">union</span></code>
may be declared <code class="sourceCode cpp">trivial</code> (this is a
context-sensitive keyword). If any declaration of a union
<code class="sourceCode cpp">U</code> contains
<code class="sourceCode cpp">trivial</code>, every declaration of
<code class="sourceCode cpp">U</code> must do so.</li>
<li>a <code class="sourceCode cpp">trivial <span class="kw">union</span></code>
shall not have any default member initializers.</li>
<li>a <code class="sourceCode cpp">trivial <span class="kw">union</span></code> is
trivially default constructible. If the first alternative has
implicit-lifetime type, this also begins the lifetime of that
alternative and sets it as the active member.</li>
<li>a <code class="sourceCode cpp">trivial <span class="kw">union</span></code> is
trivially destructible.</li>
</ul>
<p>The syntax is <code class="sourceCode cpp">trivial <span class="kw">union</span></code>
instead of <code class="sourceCode cpp"><span class="kw">union</span> trivial</code>
(which might be more consistent with the use of
<code class="sourceCode cpp"><span class="kw">final</span></code>)
because the former allows an anonymous union declaration as <code class="sourceCode cpp">trivial <span class="kw">union</span> <span class="op">{</span> T n; <span class="op">}</span></code>
whereas <code class="sourceCode cpp"><span class="kw">union</span> trivial <span class="op">{</span> T n; <span class="op">}</span></code>
is already a valid declaration today. Nor can you put the
<code class="sourceCode cpp">trivial</code> even later - as in <code class="sourceCode cpp"><span class="kw">union</span> <span class="op">{</span> T n; <span class="op">}</span> trivial</code>
since now that is declaring a variable.</p>
<p>A better syntax that wouldn’t lead to conversations about
context-sensitive keywords would be <code class="sourceCode cpp"><span class="kw">union</span> <span class="op">[[</span><span class="at">trivial</span><span class="op">]]</span></code>.</p>
<p>Another potential choice of word instead of
<code class="sourceCode cpp">trivial</code> here would be
<code class="sourceCode cpp">uninitialized</code>.</p>
<p>An alternative design would be to change all existing
<code class="sourceCode cpp"><span class="kw">union</span></code>s to
have this behavior (except still allowing default member initializers).
That is:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>trivial union</strong>
</div></th>
<th><div style="text-align:center">
<strong>just make it work</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="co">// trivial default constructor</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="co">// does not start lifetime of s</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial destructor</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>trivial <span class="kw">union</span> U1 <span class="op">{</span> string s; <span class="op">}</span>;</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="co">// deleted default constructor</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="co">// deleted destructor</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U2 <span class="op">{</span> string s; <span class="op">}</span>;</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial default constructor</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="co">// starts lifetime of s</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial destructor</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>trivial <span class="kw">union</span> U3 <span class="op">{</span> string s<span class="op">[</span><span class="dv">10</span><span class="op">]</span>; <span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial default constructor</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="co">// does not start lifetime of s</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial destructor</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U4 <span class="op">{</span> string s; <span class="op">}</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="co">// non-trivial default constructor</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="co">// deleted destructor</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U5 <span class="op">{</span> string s <span class="op">=</span> <span class="st">&quot;hello&quot;</span>; <span class="op">}</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial default constructor</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="co">// starts lifetime of s</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a><span class="co">// trivial destructor</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> U6 <span class="op">{</span> string s<span class="op">[</span><span class="dv">10</span><span class="op">]</span>; <span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>It’s worth discussing both options. Unions already have very sharp
edges, so perhaps this added protection of deleting the default
constructor and destructor aren’t really super useful - that’s probably
not the feature that really saves you.</p>
<p>Note that just making work will change some code from ill-formed to
well-formed, whereas introducing a <code class="sourceCode cpp">trivial <span class="kw">union</span></code> will
not change the meaning of any existing code.</p>
<h2 data-number="4.1" id="wording-for-just-making-it-work"><span class="header-section-number">4.1</span> Wording for just making it
work<a href="#wording-for-just-making-it-work" class="self-link"></a></h2>
<p>Change <span>11.4.5.2 <a href="https://wg21.link/class.default.ctor">[class.default.ctor]</a></span>/2-3.
<span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The third
and fourth bullets can be removed because such cases become trivially
default constructible too ]</span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">2</a></span>
A defaulted default constructor for class
<code class="sourceCode cpp">X</code> is defined as deleted if <span class="addu"><code class="sourceCode cpp">X</code> is a non-union class
and</span>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">(2.1)</a></span>
any non-static data member with no default member initializer
([class.mem]) is of reference type,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(2.2)</a></span>
any <span class="rm" style="color: #bf0303"><del>non-variant</del></span> non-static data
member of const-qualified type (or possibly multi-dimensional array
thereof) with no brace-or-equal-initializer is not
const-default-constructible ([dcl.init]),</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">(2.3)</a></span>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">X</code></span>
is a union and all of its variant members are of const-qualified type
(or possibly multi-dimensional array thereof),</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">(2.4)</a></span>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">X</code></span>
is a non-union class and all members of any anonymous union member are
of const-qualified type (or possibly multi-dimensional array
thereof)</del></span>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(2.5)</a></span>
any potentially constructed subobject, except for a non-static data
member with a brace-or-equal-initializer <span class="rm" style="color: #bf0303"><del>or a variant member of a union where another
non-static data member has a brace-or-equal-initializer</del></span>,
has class type <code class="sourceCode cpp">M</code> (or possibly
multi-dimensional array thereof) and overload resolution ([over.match])
as applied to find <code class="sourceCode cpp">M</code>’s corresponding
constructor either does not result in a usable candidate
([over.match.general]) <span class="rm" style="color: #bf0303"><del>or,
in the case of a variant member, selects a non-trivial
function,</del></span> or</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">3</a></span>
A default constructor <span class="addu">for a class
<code class="sourceCode cpp">X</code></span> is <em>trivial</em> if it
is not user-provided and if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">(3.1)</a></span>
<span class="rm" style="color: #bf0303"><del>its class</del></span>
<span class="addu"><code class="sourceCode cpp">X</code></span> has no
virtual functions ([class.virtual]) and no virtual base classes
([class.mi]), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(3.2)</a></span>
no non-static data member of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> has a default
member initializer ([class.mem]), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(3.3)</a></span>
all the direct base classes of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> have trivial
default constructors, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(3.4)</a></span>
<span class="addu">either <code class="sourceCode cpp">X</code> is a
union or</span> for all the non-static data members of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> that are of
class type (or array thereof), each such class has a trivial default
constructor.</li>
</ul>
<p>Otherwise, the default constructor is <em>non-trivial</em>. <span class="addu">If the default constructor of a union
<code class="sourceCode cpp">X</code> is trivial and the first variant
member of <code class="sourceCode cpp">X</code> has implicit-lifetime
type ([basic.types.general]), the default constructor begins the
lifetime of that member <span class="note"><span>[ <em>Note 1:</em>
</span>It becomes the active member of the union<span> — <em>end
note</em> ]</span></span>.</span></p>
</blockquote>
</div>
<p>Change <span>11.4.7 <a href="https://wg21.link/class.dtor">[class.dtor]</a></span>/7-8:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">7</a></span>
A defaulted destructor for a class <code class="sourceCode cpp">X</code>
is defined as deleted if <span class="addu"><code class="sourceCode cpp">X</code> is a non-union class
and</span>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">(7.1)</a></span>
any potentially constructed subobject has class type
<code class="sourceCode cpp">M</code> (or possibly multi-dimensional
array thereof) and <code class="sourceCode cpp">M</code> has a
destructor that is deleted or is inaccessible from the defaulted
destructor <span class="rm" style="color: #bf0303"><del>or, in the case
of a variant member, is non-trivial,</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(7.2)</a></span>
or, for a virtual destructor, lookup of the non-array deallocation
function results in an ambiguity or in a function that is deleted or
inaccessible from the defaulted destructor.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">8</a></span>
A destructor <span class="addu">for a class
<code class="sourceCode cpp">X</code></span> is <em>trivial</em> if it
is not user-provided and if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(8.1)</a></span>
the destructor is not virtual,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">(8.2)</a></span>
all of the direct base classes of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> have trivial
destructors, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(8.3)</a></span>
<span class="addu">either <code class="sourceCode cpp">X</code> is a
union with no default member initializer or</span> for all of the
non-static data members of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> that are of
class type (or array thereof), each such class has a trivial
destructor.</li>
</ul>
</blockquote>
</div>
<h2 data-number="4.2" id="wording-for-trivial-union"><span class="header-section-number">4.2</span> Wording for <code class="sourceCode cpp">trivial <span class="kw">union</span></code><a href="#wording-for-trivial-union" class="self-link"></a></h2>
<p>Add <code class="sourceCode cpp">trivial</code> to the identifiers
with special meaning table in <span>5.10 <a href="https://wg21.link/lex.name">[lex.name]</a></span>:</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>  final</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  import</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  module</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  override</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="va">+ trivial</span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Change <span>11.1 <a href="https://wg21.link/class.pre">[class.pre]</a></span> to add the
ability to declare a
<code class="sourceCode cpp"><span class="kw">union</span></code>
trivial:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb17"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>  <em>class-key</em>:</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    class</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    struct</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="st">-   union</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="va">+   trivial<sub>opt</sub> union</span></span></code></pre></div>
</div>
</blockquote>
</div>
<p>Add to the end of <span>11.1 <a href="https://wg21.link/class.pre">[class.pre]</a></span>:</p>
<div class="std ins">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">8</a></span>
A <code class="sourceCode cpp"><em>class-key</em></code> shall only
contain <code class="sourceCode cpp">trivial</code> when used in a
<code class="sourceCode cpp"><em>class-head</em></code>. If any
declaration of a union <code class="sourceCode cpp">U</code> has a
<code class="sourceCode cpp">trivial</code> specifier, then all
declarations of <code class="sourceCode cpp">U</code> shall contain
<code class="sourceCode cpp">trivial</code> <span class="note"><span>[ <em>Note 1:</em> </span>This includes those
declarations that use an
<code class="sourceCode cpp"><em>elaborated-type-specifier</em></code>,
which cannot provide the <code class="sourceCode cpp">trivial</code>
specifier.<span> — <em>end note</em> ]</span></span>.</p>
</blockquote>
</div>
<p>Add to <span>11.5.1 <a href="https://wg21.link/class.union.general">[class.union.general]</a></span>/1:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">1</a></span>
A <em>union</em> is a class defined with the
<code class="sourceCode cpp"><em>class-key</em></code>
<code class="sourceCode cpp"><span class="kw">union</span></code>. <span class="addu">A <em>trivial union</em> is a union defined with the
<code class="sourceCode cpp"><em>class-key</em></code> <code class="sourceCode cpp">trivial <span class="kw">union</span></code>. A
trivial union shall not have a default member initializer.</span></p>
</blockquote>
</div>
<p>Change <span>11.5.2 <a href="https://wg21.link/class.union.anon">[class.union.anon]</a></span>/1:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">1</a></span>
A union of the form</p>
<div>
<div class="sourceCode" id="cb18"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="st">- union { <em>member-specification</em> } ;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ trivial<sub>opt</sub> union { <em>member-specification</em> } ;</span></span></code></pre></div>
</div>
<p>is called an <em>anonymous union</em> […]</p>
</blockquote>
</div>
<p>Change <span>11.4.5.2 <a href="https://wg21.link/class.default.ctor">[class.default.ctor]</a></span>/2-3.</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">2</a></span>
A defaulted default constructor for class
<code class="sourceCode cpp">X</code> is defined as deleted if <span class="addu"><code class="sourceCode cpp">X</code> is not a trivial
union and</span>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_23" id="pnum_23">(2.1)</a></span>
[…]</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">3</a></span>
A default constructor <span class="addu">for a class
<code class="sourceCode cpp">X</code></span> is <em>trivial</em> if it
is not user-provided and if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">(3.1)</a></span>
<span class="rm" style="color: #bf0303"><del>its class</del></span>
<span class="addu"><code class="sourceCode cpp">X</code></span> has no
virtual functions ([class.virtual]) and no virtual base classes
([class.mi]), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">(3.2)</a></span>
no non-static data member of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> has a default
member initializer ([class.mem]), and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">(3.3)</a></span>
all the direct base classes of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> have trivial
default constructors, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">(3.4)</a></span>
<span class="addu">either <code class="sourceCode cpp">X</code> is a
trivial union or</span> for all the non-static data members of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> that are of
class type (or array thereof), each such class has a trivial default
constructor.</li>
</ul>
<p>Otherwise, the default constructor is <em>non-trivial</em>. <span class="addu">If the default constructor of a trivial union
<code class="sourceCode cpp">X</code> is trivial and the first variant
member of <code class="sourceCode cpp">X</code> has implicit-lifetime
type ([basic.types.general]), the default constructor begins the
lifetime of that member <span class="note"><span>[ <em>Note 2:</em>
</span>It becomes the active member of the union<span> — <em>end
note</em> ]</span></span>.</span></p>
</blockquote>
</div>
<p>Change <span>11.4.7 <a href="https://wg21.link/class.dtor">[class.dtor]</a></span>/7-8:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_29" id="pnum_29">7</a></span>
A defaulted destructor for a class <code class="sourceCode cpp">X</code>
is defined as deleted if <span class="addu"><code class="sourceCode cpp">X</code> is not a trivial
union and</span>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_30" id="pnum_30">(7.1)</a></span>
[…]</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_31" id="pnum_31">8</a></span>
A destructor <span class="addu">for a class
<code class="sourceCode cpp">X</code></span> is <em>trivial</em> if it
is not user-provided and if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_32" id="pnum_32">(8.1)</a></span>
the destructor is not virtual,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_33" id="pnum_33">(8.2)</a></span>
all of the direct base classes of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> have trivial
destructors, and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_34" id="pnum_34">(8.3)</a></span>
<span class="addu">either <code class="sourceCode cpp">X</code> is a
trivial union or</span> for all of the non-static data members of <span class="rm" style="color: #bf0303"><del>its class</del></span> <span class="addu"><code class="sourceCode cpp">X</code></span> that are of
class type (or array thereof), each such class has a trivial
destructor.</li>
</ul>
</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>Either way, we need a new feature-test macro. Add a new macro to
<span>15.11 <a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span>:</p>
<div class="std ins">
<blockquote>
<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>__cpp_trivial_union 2024XXL</span></code></pre></div>
</blockquote>
</div>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-P0843R9" class="csl-entry" role="doc-biblioentry">
[P0843R9] Gonzalo Brito Gadeschi, Timur Doumler, Nevin Liber, David
Sankel. 2023-09-14. inplace_vector. <a href="https://wg21.link/p0843r9"><div class="csl-block">https://wg21.link/p0843r9</div></a>
</div>
<div id="ref-P2747R0" class="csl-entry" role="doc-biblioentry">
[P2747R0] Barry Revzin. 2022-12-17. Limited support for constexpr void*.
<a href="https://wg21.link/p2747r0"><div class="csl-block">https://wg21.link/p2747r0</div></a>
</div>
<div id="ref-P2747R2" class="csl-entry" role="doc-biblioentry">
[P2747R2] Barry Revzin. 2024-03-19.
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
placement new. <a href="https://wg21.link/p2747r2"><div class="csl-block">https://wg21.link/p2747r2</div></a>
</div>
<div id="ref-P3074R0" class="csl-entry" role="doc-biblioentry">
[P3074R0] Barry Revzin. 2023-12-15. constexpr union lifetime. <a href="https://wg21.link/p3074r0"><div class="csl-block">https://wg21.link/p3074r0</div></a>
</div>
<div id="ref-P3074R1" class="csl-entry" role="doc-biblioentry">
[P3074R1] Barry Revzin. 2024-01-30. std::uninitialized&lt;T&gt;. <a href="https://wg21.link/p3074r1"><div class="csl-block">https://wg21.link/p3074r1</div></a>
</div>
<div id="ref-P3074R2" class="csl-entry" role="doc-biblioentry">
[P3074R2] Barry Revzin. 2024-02-13. std::uninitialized&lt;T&gt;. <a href="https://wg21.link/p3074r2"><div class="csl-block">https://wg21.link/p3074r2</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
