<!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="2023-12-15" />
  <title>constexpr union lifetime</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.hanging-indent{margin-left: 1.5em; text-indent: -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; }
      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;
}
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: #e6ffed;
--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); }
</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"><span class="kw">constexpr</span></code> union lifetime</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3074R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-12-15</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="#introduction"><span class="toc-section-number">1</span> Introduction<span></span></a>
<ul>
<li><a href="#a-library-type-stduninitializedt"><span class="toc-section-number">1.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="#just-make-it-work"><span class="toc-section-number">1.2</span> Just Make It Work<span></span></a></li>
<li><a href="#make-the-user-explicitly-start-lifetime"><span class="toc-section-number">1.3</span> Make the user explicitly start lifetime<span></span></a></li>
</ul></li>
<li><a href="#proposal"><span class="toc-section-number">2</span> Proposal<span></span></a>
<ul>
<li><a href="#wording"><span class="toc-section-number">2.1</span> Wording<span></span></a></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">3</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>Consider the following example:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-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"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></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"></a>    U u;</span>
<span id="cb1-5"><a href="#cb1-5"></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"></a></span>
<span id="cb1-7"><a href="#cb1-7"></a>    <span class="co">// note: we are *not* constructing storage</span></span>
<span id="cb1-8"><a href="#cb1-8"></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"></a></span>
<span id="cb1-10"><a href="#cb1-10"></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"></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"></a>    <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13"></a></span>
<span id="cb1-14"><a href="#cb1-14"></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"></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"></a>        <span class="op">++</span>size;</span>
<span id="cb1-17"><a href="#cb1-17"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18"></a><span class="op">}</span>;</span>
<span id="cb1-19"><a href="#cb1-19"></a></span>
<span id="cb1-20"><a href="#cb1-20"></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"></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"></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"></a>    <span class="cf">return</span> v<span class="op">.</span>size;</span>
<span id="cb1-24"><a href="#cb1-24"></a><span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25"></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>
<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="#ref-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="#ref-P2747R0" role="doc-biblioref">P2747R0</a>]</span>.</p>
<p>There are basically three ways we can approach this problem.</p>
<h2 data-number="1.1" id="a-library-type-stduninitializedt"><span class="header-section-number">1.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>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-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="cb2-2"><a href="#cb2-2"></a><span class="kw">class</span> uninitialized <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>    T <em>storage</em>; <span class="co">// exposition only</span></span>
<span id="cb2-4"><a href="#cb2-4"></a></span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ptr<span class="op">()</span> <span class="op">-&gt;</span> remove_extent_t<span class="op">&lt;</span>T<span class="op">&gt;*</span>;</span>
<span id="cb2-7"><a href="#cb2-7"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ptr<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> remove_extent_t<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">const</span><span class="op">*</span>;</span>
<span id="cb2-8"><a href="#cb2-8"></a></span>
<span id="cb2-9"><a href="#cb2-9"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ref<span class="op">()</span> <span class="op">-&gt;</span> remove_extent_t<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span>;</span>
<span id="cb2-10"><a href="#cb2-10"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> ref<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> remove_extent_t<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb2-11"><a href="#cb2-11"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<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.</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="P2747R1">[<a href="#ref-P2747R1" role="doc-biblioref">P2747R1</a>]</span>, simply placement-new) into the appropriate elements of that array and everything would just work.</p>
<h2 data-number="1.2" id="just-make-it-work"><span class="header-section-number">1.2</span> Just Make It Work<a href="#just-make-it-work" class="self-link"></a></h2>
<p>We could change the union rules such that if the first alternative of a <code class="sourceCode cpp"><span class="kw">union</span></code> is an implicit-lifetime type, then its lifetime is started when the <code class="sourceCode cpp"><span class="kw">union</span></code>’s lifetime is started. This is a pretty reasonable rule in my opinion, and follows from what implicit-lifetime means, and also seems to follow what the expectation might actually be for the above code.</p>
<p>As a result, the above example would just work with no further code changes, since the lifetime of <code class="sourceCode cpp">storage</code> is started (<code class="sourceCode cpp">T<span class="op">[</span>N<span class="op">]</span></code> is an implicit-lifetime type for all <code class="sourceCode cpp">T</code>), which makes it the active member of the union, and we’re all good on that front.</p>
<h2 data-number="1.3" id="make-the-user-explicitly-start-lifetime"><span class="header-section-number">1.3</span> Make the user explicitly start lifetime<a href="#make-the-user-explicitly-start-lifetime" class="self-link"></a></h2>
<p>One issue with just making it work, as described above, is what if you have something like:</p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">union</span> U <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>    T x<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb3-3"><a href="#cb3-3"></a>    U y<span class="op">[</span>M<span class="op">]</span>;</span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="op">}</span> u;</span></code></pre></div>
</blockquote>
<p>Now what? Maybe in different contexts we want to populate <code class="sourceCode cpp">u<span class="op">.</span>x</code> or <code class="sourceCode cpp">u<span class="op">.</span>y</code>, and we can’t implicitly start both alternatives’ lifetimes. We have to choose.</p>
<p>To that end, we already have a seemingly-relevant function in the standard library:</p>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-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"></a>  T<span class="op">*</span> start_lifetime_as<span class="op">(</span><span class="dt">void</span><span class="op">*</span> p<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
</blockquote>
<p>Now, there are two problems with this function as far as its uses in <code class="sourceCode cpp"><span class="kw">constexpr</span></code> go. The simple one is that it’s not marked <code class="sourceCode cpp"><span class="kw">constexpr</span></code>. The more complicated one is that the <em>Effects</em> of this function are:</p>
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">3</a></span> <em>Effects</em>: Implicitly creates objects ([intro.object]) within the denoted region consisting of an object a of type <code class="sourceCode cpp">T</code> whose address is <code class="sourceCode cpp">p</code>, and objects nested within <code class="sourceCode cpp">a</code>, as follows: The object representation of <code class="sourceCode cpp">a</code> is the contents of the storage prior to the call to <code class="sourceCode cpp">start_lifetime_as</code>. The value of each created object <code class="sourceCode cpp">o</code> of trivially copyable type ([basic.types.general]) <code class="sourceCode cpp">U</code> is determined in the same manner as for a call to <code class="sourceCode cpp">bit_cast<span class="op">&lt;</span>U<span class="op">&gt;(</span>E<span class="op">)</span></code> ([bit.cast]), where <code class="sourceCode cpp">E</code> is an lvalue of type <code class="sourceCode cpp">U</code> denoting <code class="sourceCode cpp">o</code>, except that the storage is not accessed. The value of any other created object is unspecified.</li>
</ul>
</blockquote>
<p>We can’t really be talking about <code class="sourceCode cpp">bit_cast</code>ing anything out of our not-yet-even-initialized storage. That wording would have to change. But we could just say that during constant evaluation, this function simply starts the lifetime of the denoted object.</p>
<p>That is:</p>
<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-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="cb5-2"><a href="#cb5-2"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3"></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="cb5-4"><a href="#cb5-4"></a>    U u;</span>
<span id="cb5-5"><a href="#cb5-5"></a>    <span class="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb5-6"><a href="#cb5-6"></a></span>
<span id="cb5-7"><a href="#cb5-7"></a>    <span class="co">// note: we are *not* constructing storage</span></span>
<span id="cb5-8"><a href="#cb5-8"></a>    <span class="kw">constexpr</span> FixedVector<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9"></a>        <span class="cf">if</span> <span class="kw">consteval</span> <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10"></a>            std<span class="op">::</span>start_lifetime_as<span class="op">&lt;</span>T<span class="op">[</span>N<span class="op">]&gt;(&amp;</span>u<span class="op">.</span>storage<span class="op">)</span>;</span>
<span id="cb5-11"><a href="#cb5-11"></a>        <span class="op">}</span></span>
<span id="cb5-12"><a href="#cb5-12"></a>    <span class="op">}</span></span>
<span id="cb5-13"><a href="#cb5-13"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>This is a mildly inconvenient interface, since we have to repeat the type, but it has to match anyway. Plus we really don’t want implementations to actually be copying anything in debug builds for sanitizing purposes, that would be completely wrong here - hence the <code class="sourceCode cpp"><span class="cf">if</span> <span class="kw">consteval</span></code>. But also surely the only reason to call <code class="sourceCode cpp">start_lifetime_as<span class="op">&lt;</span>T<span class="op">&gt;(</span>p<span class="op">)</span></code> is to actually then use the resulting <code class="sourceCode cpp">T<span class="op">*</span></code>, so implementations will presumably mark this function <code class="sourceCode cpp"><span class="op">[[</span><span class="at">nodiscard</span><span class="op">]]</span></code>.</p>
<p>It’d be annoying to introduce a new function (whose name would surely be similar) to achieve a similar feat, but we could do that:</p>
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-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="cb6-2"><a href="#cb6-2"></a>  <span class="kw">constexpr</span> <span class="dt">void</span> start_lifetime<span class="op">(</span>T<span class="op">*)</span>;</span></code></pre></div>
</blockquote>
<p>as in:</p>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-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="cb7-2"><a href="#cb7-2"></a><span class="kw">struct</span> FixedVector <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3"></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="cb7-4"><a href="#cb7-4"></a>    U u;</span>
<span id="cb7-5"><a href="#cb7-5"></a>    <span class="dt">size_t</span> size <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb7-6"><a href="#cb7-6"></a></span>
<span id="cb7-7"><a href="#cb7-7"></a>    <span class="co">// note: we are *not* constructing storage</span></span>
<span id="cb7-8"><a href="#cb7-8"></a>    <span class="kw">constexpr</span> FixedVector<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9"></a>        std<span class="op">::</span>start_lifetime<span class="op">(&amp;</span>u<span class="op">.</span>storage<span class="op">)</span>;</span>
<span id="cb7-10"><a href="#cb7-10"></a>    <span class="op">}</span></span>
<span id="cb7-11"><a href="#cb7-11"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>This would be a function that would start the lifetime of the provided union alternative without performing any initialization. Which is the desired behavior here: it would simply require slightly more typing than the <a href="#just-make-it-work">just make it work</a> option.</p>
<p>Note that this would make implementing <a href="#a-library-type-stduninitializedt"><code class="sourceCode cpp">std<span class="op">::</span>uninitalized<span class="op">&lt;</span>T<span class="op">&gt;</span></code></a> fairly straightforward - you just call the function if you need to (if <code class="sourceCode cpp">T</code> is trivially default constructible, you wouldn’t need to).</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">2</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>This paper proposes the third option: introduce a new library function:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-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="cb8-2"><a href="#cb8-2"></a>  <span class="kw">constexpr</span> <span class="dt">void</span> start_lifetime<span class="op">(</span>T<span class="op">*)</span>;</span></code></pre></div>
</blockquote>
<p>Not to be confused with:</p>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-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="cb9-2"><a href="#cb9-2"></a>  <span class="co">/* not constexpr */</span> T<span class="op">*</span> start_lifetime_as<span class="op">(</span><span class="dt">void</span><span class="op">*)</span>;</span></code></pre></div>
</blockquote>
<p>Whose job it is to begin the lifetime of union alternative.</p>
<h2 data-number="2.1" id="wording"><span class="header-section-number">2.1</span> Wording<a href="#wording" class="self-link"></a></h2>
<p>Add to <span>20.2.2 <a href="https://wg21.link/memory.syn">[memory.syn]</a></span>:</p>
<blockquote>
<div>
<div class="sourceCode" id="cb10"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb10-1"><a href="#cb10-1"></a>namespace std {</span>
<span id="cb10-2"><a href="#cb10-2"></a>  // ...</span>
<span id="cb10-3"><a href="#cb10-3"></a>  // [obj.lifetime], explicit lifetime management</span>
<span id="cb10-4"><a href="#cb10-4"></a>  template&lt;class T&gt;</span>
<span id="cb10-5"><a href="#cb10-5"></a>    T* start_lifetime_as(void* p) noexcept;                                         // freestanding</span>
<span id="cb10-6"><a href="#cb10-6"></a>  template&lt;class T&gt;</span>
<span id="cb10-7"><a href="#cb10-7"></a>    const T* start_lifetime_as(const void* p) noexcept;                             // freestanding</span>
<span id="cb10-8"><a href="#cb10-8"></a>  template&lt;class T&gt;</span>
<span id="cb10-9"><a href="#cb10-9"></a>    volatile T* start_lifetime_as(volatile void* p) noexcept;                       // freestanding</span>
<span id="cb10-10"><a href="#cb10-10"></a>  template&lt;class T&gt;</span>
<span id="cb10-11"><a href="#cb10-11"></a>    const volatile T* start_lifetime_as(const volatile void* p) noexcept;           // freestanding</span>
<span id="cb10-12"><a href="#cb10-12"></a>  template&lt;class T&gt;</span>
<span id="cb10-13"><a href="#cb10-13"></a>    T* start_lifetime_as_array(void* p, size_t n) noexcept;                         // freestanding</span>
<span id="cb10-14"><a href="#cb10-14"></a>  template&lt;class T&gt;</span>
<span id="cb10-15"><a href="#cb10-15"></a>    const T* start_lifetime_as_array(const void* p, size_t n) noexcept;             // freestanding</span>
<span id="cb10-16"><a href="#cb10-16"></a>  template&lt;class T&gt;</span>
<span id="cb10-17"><a href="#cb10-17"></a>    volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept;       // freestanding</span>
<span id="cb10-18"><a href="#cb10-18"></a>  template&lt;class T&gt;</span>
<span id="cb10-19"><a href="#cb10-19"></a>    const volatile T* start_lifetime_as_array(const volatile void* p,               // freestanding</span>
<span id="cb10-20"><a href="#cb10-20"></a>                                          size_t n) noexcept;</span>
<span id="cb10-21"><a href="#cb10-21"></a></span>
<span id="cb10-22"><a href="#cb10-22"></a><span class="va">+ template&lt;class T&gt;</span></span>
<span id="cb10-23"><a href="#cb10-23"></a><span class="va">+   constexpr void start_lifetime(T* p) noexcept;                                   // freestanding</span></span>
<span id="cb10-24"><a href="#cb10-24"></a>}</span></code></pre></div>
</div>
</blockquote>
<p>With corresponding wording in <span>20.2.6 <a href="https://wg21.link/obj.lifetime">[obj.lifetime]</a></span>:</p>
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2"></a>  <span class="kw">constexpr</span> <span class="dt">void</span> start_lifetime<span class="op">(</span>T<span class="op">*</span> p<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">9</a></span> <em>Mandates</em>: <code class="sourceCode cpp">T</code> is a complete type and an implicit-lifetime type.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">10</a></span> <em>Preconditions</em>: <code class="sourceCode cpp">p</code> is a pointer to a variant member of a union.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">11</a></span> <em>Effects</em>: Begins the lifetime ([basic.life]) of the non-static data member denoted by <code class="sourceCode cpp">p</code>. It is now the active member of its union. This ends the lifetime of the previously-active member of the union, if any.</li>
</ul>
</div>
</blockquote>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">3</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-P0843R9">
<p>[P0843R9] Gonzalo Brito Gadeschi, Timur Doumler, Nevin Liber, David Sankel. 2023-09-14. inplace_vector. <br />
<a href="https://wg21.link/p0843r9">https://wg21.link/p0843r9</a></p>
</div>
<div id="ref-P2747R0">
<p>[P2747R0] Barry Revzin. 2022-12-17. Limited support for constexpr void*. <br />
<a href="https://wg21.link/p2747r0">https://wg21.link/p2747r0</a></p>
</div>
<div id="ref-P2747R1">
<p>[P2747R1] Barry Revzin. 2023. `constexpr`` placement new. <br />
<a href="https://wg21.link/p2747r1">https://wg21.link/p2747r1</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
