<!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="2025-01-11" />
  <title>Accessing object representations</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 { } 
code span.al { color: #ff0000; } 
code span.an { } 
code span.at { } 
code span.bn { color: #9f6807; } 
code span.bu { color: #9f6807; } 
code span.cf { color: #00607c; } 
code span.ch { color: #9f6807; } 
code span.cn { } 
code span.co { color: #008000; font-style: italic; } 
code span.cv { color: #008000; font-style: italic; } 
code span.do { color: #008000; } 
code span.dt { color: #00607c; } 
code span.dv { color: #9f6807; } 
code span.er { color: #ff0000; font-weight: bold; } 
code span.ex { } 
code span.fl { color: #9f6807; } 
code span.fu { } 
code span.im { } 
code span.in { color: #008000; } 
code span.kw { color: #00607c; } 
code span.op { color: #af1915; } 
code span.ot { } 
code span.pp { color: #6f4e37; } 
code span.re { } 
code span.sc { color: #9f6807; } 
code span.ss { color: #9f6807; } 
code span.st { color: #9f6807; } 
code span.va { } 
code span.vs { color: #9f6807; } 
code span.wa { color: #008000; font-weight: bold; } 
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: 2.5em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
ol {
padding-left: 2.5em;
}
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;
}

#TOC ul > li:before {
content: none;
}
#TOC > ul {
padding-left: 0;
}

.toc-section-number {
margin-right: 0.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>
  <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">Accessing object
representations</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1839R7</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-01-11</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      CWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Timur Doumler<br>&lt;<a href="mailto:papers@timur.audio" class="email">papers@timur.audio</a>&gt;<br>
      Krystian Stasiowski<br>&lt;<a href="mailto:sdkrystian@gmail.com" class="email">sdkrystian@gmail.com</a>&gt;<br>
      Brian Bi<br>&lt;<a href="mailto:bbi10@bloomberg.net" class="email">bbi10@bloomberg.net</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="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract</a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation</a></li>
<li><a href="#the-problem" id="toc-the-problem"><span class="toc-section-number">3</span> The problem</a></li>
<li><a href="#history-and-context" id="toc-history-and-context"><span class="toc-section-number">4</span> History and context</a></li>
<li><a href="#non-goals" id="toc-non-goals"><span class="toc-section-number">5</span> Non-goals</a></li>
<li><a href="#proposed-solution" id="toc-proposed-solution"><span class="toc-section-number">6</span> Proposed solution</a></li>
<li><a href="#polls" id="toc-polls"><span class="toc-section-number">7</span> Polls</a></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">8</span> Proposed wording</a></li>
<li><a href="#document-history" id="toc-document-history"><span class="toc-section-number">9</span> Document history</a></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">10</span> Acknowledgements</a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">11</span> References</a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper proposes a wording fix to the C++ standard to allow read
access to the object representation (i.e. the underlying bytes) of an
object. This is valid in C, and is widely used and assumed to be valid
in C++ as well. However, in C++ this is is undefined behaviour under the
current specification.</p>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Consider the following program, which takes an
<code class="sourceCode cpp"><span class="dt">int</span></code> and
prints the underlying bytes of its value in hex format:</p>
<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="dt">void</span> print_hex<span class="op">(</span><span class="dt">int</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">unsigned</span> <span class="dt">char</span><span class="op">*</span> a <span class="op">=</span> <span class="op">(</span><span class="dt">unsigned</span> <span class="dt">char</span><span class="op">*)(&amp;</span>n<span class="op">)</span>;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span>; <span class="op">++</span>i<span class="op">)</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;%02x &quot;</span>, a<span class="op">[</span>i<span class="op">])</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</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="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  print_hex<span class="op">(</span><span class="dv">123456</span><span class="op">)</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In C, this is a valid program. On a little-endian machine where <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">==</span> <span class="dv">4</span></code>,
this will print <code class="sourceCode cpp"><span class="dv">40</span> e2 <span class="bn">01</span> <span class="bn">00</span></code>.
In C++, this is widely assumed to be valid as well, and this
functionality is widely used in existing code bases (think of binary
file formats, hex viewers, and many other low-level use cases).</p>
<p>However, surprisingly, in C++ this code has undefined behaviour under
the current specification. In fact, it is impossible in C++ to directly
access the object representation of an object (i.e. to read its
underlying bytes), even for built-in types such as
<code class="sourceCode cpp"><span class="dt">int</span></code>.
Instead, we would have to use <code class="sourceCode cpp">memcpy</code>
to copy the bytes into a separate array of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
and access them from there.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> However, this workaround
only works for trivially copyable types. It also directly violates one
of the fundamental principles of C++: to leave no room for a lower-level
language.</p>
<p>The goal of this paper is to provide the necessary wording fixes to
make accessing object representations such as in the code above defined
behaviour. Existing compilers already assume that this should be valid.
The goal of the paper is therefore to <em>not</em> require any changes
to existing compilers or existing code, but to legalise existing code
that already works in practice and was always intended to be valid.</p>
<h1 data-number="3" id="the-problem"><span class="header-section-number">3</span> The problem<a href="#the-problem" class="self-link"></a></h1>
<p>The cast to <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span><span class="op">*</span></code>,
which performs a <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>,
is fine, because
<code class="sourceCode cpp"><span class="dt">char</span></code>, <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
and
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>
can alias any other type, so we do not violate the rules for type
punning. However, with the current wording, this cast does <em>not</em>
yield a pointer to the first element of
<code class="sourceCode cpp">n</code>’s object representation (i.e. a
pointer to a byte), and in fact it is currently impossible in C++ to
obtain such a pointer. This is because this particular <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>
is exactly equivalent to <code class="sourceCode cpp"><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">unsigned</span> <span class="dt">char</span><span class="op">*&gt;(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span><span class="op">*&gt;(&amp;</span>n<span class="op">))</span></code>
as per §<span>7.6.1.10
<a href="https://wg21.link/N5001#expr.reinterpret.cast">[expr.reinterpret.cast]</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></span>p7, and as such,
§<span>7.6.1.9
<a href="https://wg21.link/N5001#expr.static.cast">[expr.static.cast]</a></span>p13
dictates that the value of the pointer is unchanged and therefore it
points to the original object (the
<code class="sourceCode cpp"><span class="dt">int</span></code>). When
<code class="sourceCode cpp">a</code> is dereferenced, the behaviour is
undefined as per §<span>7.1
<a href="https://wg21.link/N5001#expr.pre">[expr.pre]</a></span>p4
because the value of the resulting expression would <em>not</em> be the
value of the first byte, but the value of the whole
<code class="sourceCode cpp"><span class="dt">int</span></code> object
(123456), which is not a value representable by <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>.</p>
<p>Further, even if we ignore this issue,
<code class="sourceCode cpp">a</code> does not point to an array of
<code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
because such an array has never been created, and therefore pointer
arithmetic on <code class="sourceCode cpp">a</code> has undefined
behaviour. An object representation as defined by §<span>6.8
<a href="https://wg21.link/N5001#basic.types">[basic.types]</a></span>p4
is merely a <em>sequence</em> of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
objects, not an array, and is therefore unsuitable for pointer
arithmetic. No array is ever created explicitly, and no operation is
being called in the above code that would implicitly create an array,
since casts are not operations that implicitly create objects as per
§<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p11.</p>
<p>It is possible to explicitly start the lifetime of an array of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
in the storage occupied by <code class="sourceCode cpp">n</code> whose
values are the values of <code class="sourceCode cpp">n</code>’s object
representation. This can be done by using
<code class="sourceCode cpp">std<span class="op">::</span>memmove</code>
to copy <code class="sourceCode cpp">n</code> to itself or, since C++23,
calling the <code class="sourceCode cpp">std<span class="op">::</span>start_lifetime_as_array</code>
function. However, these operations are destructive: because the new
array reuses the storage of <code class="sourceCode cpp">n</code>,
<code class="sourceCode cpp">n</code>’s lifetime ends when the new array
comes into existence. In a multithreaded program, this operation can
race with another operation that reads
<code class="sourceCode cpp">n</code>, and is therefore less useful than
copying the bytes into a separate array in order to examine them.</p>
<h1 data-number="4" id="history-and-context"><span class="header-section-number">4</span> History and context<a href="#history-and-context" class="self-link"></a></h1>
<p>The intent of CWG has always been that the above code should work, as
exemplified by <span class="citation" data-cites="CWG1314">[<a href="https://wg21.link/cwg1314" role="doc-biblioref">CWG1314</a>]</span>, in which it is stated that
access to the object representation is intended to be well-defined.
Further, it seems that the above code actually <em>did</em> work until
C++17, when <span class="citation" data-cites="P0137R1">[<a href="https://wg21.link/p0137r1" role="doc-biblioref">P0137R1</a>]</span> was accepted. This proposal
fixed an unrelated core issue and included a change to how pointers
work, notably that they point to objects, rather than just representing
an address. It seems that the proposal neglected to add any provisions
to allow access to the object representation of an object, and thus
inadvertently broke this functionality. Therefore, this paper is a
defect report, not a proposal of a new feature.</p>
<p>Notably, there are even standard library facilities that directly use
this functionality and cannot be implemented in standard C++ without
fixing it. One such facility is <code class="sourceCode cpp">std<span class="op">::</span>as_bytes</code>
(introduced in C++20), which obtains a <code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span><span class="kw">const</span> std<span class="op">::</span>byte<span class="op">&gt;</span></code>
view to the object representation of the elements of another span. Now,
we do have a few “magic” functions in the C++ standard library that
cannot be implemented in standard C++, but reading the underlying bytes
of an object is such basic functionality that it should not fall into
this category.</p>
<h1 data-number="5" id="non-goals"><span class="header-section-number">5</span> Non-goals<a href="#non-goals" class="self-link"></a></h1>
<p>This paper does not propose to make in-place modification of the
object representation valid, i.e. <em>writing</em> into the underlying
bytes, only <em>reading</em> them. The following code will still have
undefined behaviour:</p>
<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="dt">void</span> increment_first_byte<span class="op">(</span><span class="dt">int</span><span class="op">*</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">*</span> a <span class="op">=</span> <span class="kw">reinterpret_cast</span><span class="op">&lt;</span><span class="dt">char</span><span class="op">*&gt;(</span>n<span class="op">)</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">++(*</span>a<span class="op">)</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It may be desirable to allow such code as well. However, unlike
reading the object representation, the effect of modifying it has never
been specified in C++, so specifying it would be a new feature, not a
defect report. Therefore, CWG gave the guidance to reduce the scope of
this paper to reading only, and propose the modifying case in a separate
paper (not yet published).</p>
<p>This paper also does not propose to subvert existing type punning
rules in any way. The proposed changes will not allow type punning
between two different types where it was not previously allowed, such as
between <code class="sourceCode cpp"><span class="dt">int</span></code>
and <code class="sourceCode cpp"><span class="dt">float</span></code>
(this should be done using <code class="sourceCode cpp">std<span class="op">::</span>bit_cast</code>). It
only allows type punning to
<code class="sourceCode cpp"><span class="dt">char</span></code>, <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
and
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>,
which are already allowed to alias any other type.</p>
<p>We also do not propose to make accessing the object representation
work for <em>all</em> types in C++, only for types that are currently
guaranteed to occupy contiguous bytes of storage, that is, for trivially
copyable or standard-layout types as per §<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p8.
On the one hand, this is unnecessarily restrictive: in practice, any
sane implementation will have complete objects, array elements, and
member subobjects occupying contiguous memory, as the only reason an
object would need to be non-contiguous would be if it was a virtual base
subobject. On the other hand, making more objects contiguous (and
therefore, their object representations accessible) is not in scope for
this paper, and is instead tackled in a separate proposal <span class="citation" data-cites="P1945R0">[<a href="https://wg21.link/p1945r0" role="doc-biblioref">P1945R0</a>]</span>.</p>
<h1 data-number="6" id="proposed-solution"><span class="header-section-number">6</span> Proposed solution<a href="#proposed-solution" class="self-link"></a></h1>
<p>For an object <em>a</em> of type
<code class="sourceCode cpp">T</code>, we propose to change the
definition of <em>object representation</em> to be considered an array
of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
and not merely a <em>sequence</em> of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
objects, if <code class="sourceCode cpp">T</code> is a type that
occupies contiguous bytes of storage. We propose that this object
representation should be an object in its own right, occupying the same
storage as <em>a</em> and having the same lifetime. This will make
pointer arithmetic work with a pointer to an element of the object
representation.</p>
<p>To avoid an infinite recursion of nested object representations, we
further specify that an array of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
acts as its own object representation. We also need to prevent implicit
object creation <span class="citation" data-cites="P0593R6">[<a href="https://wg21.link/p0593r6" role="doc-biblioref">P0593R6</a>]</span> within object
representations.</p>
<p>We further propose that obtaining a pointer to the object
representation should be possible through the use of a cast to
<code class="sourceCode cpp"><span class="dt">char</span></code>, <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
or
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>,
and allow this pointer to be cast back to a pointer to its respective
object. For this, we need to make the appropriate changes to the
specification of
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>
and to make <em>a</em> pointer-interconvertible with its own object
representation as well as with the first element thereof. We need to do
this in a way that preserves <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>’s
equivalence with
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>
with respect to converting object pointers. Simultaneously, if multiple
pointer-interconvertible objects exist, we need to specify which one is
chosen.</p>
<p>Additionally, we need to make reading an object representation
through a pointer to
<code class="sourceCode cpp"><span class="dt">char</span></code> or
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>
well-defined, even though it points to an element of the object
representation which is of type <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>.
In these cases, we must allow for the type of the expression to differ
from that of the object pointed to.</p>
<p>We also need to say something about the values of the elements of an
object representation. We propose that for objects of type
<code class="sourceCode cpp"><span class="dt">char</span></code>, <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
and
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>,
the value of each element is the value of the object it represents. For
all other types, the values of the elements of the object representation
are unspecified. It seems extremely difficult to specify for the general
case what the value of each element would be, but it is also
unnecessary, since our goal is only to make reading the elements
well-defined, not to specify a particular result (which won’t be the
same across platforms).</p>
<p>Finally, multiple objects may occupy the same storage, in which case
the objects’ respective object representations will overlap. We must
therefore adjust the specification of
<code class="sourceCode cpp">std<span class="op">::</span>launder</code>
to define which object it will return a pointer to.</p>
<p>In order to preserve reachability-based restrictions that currently
exist in C++, we propose that object representations of subobjects are
distinct arrays that are simply allowed to overlap in memory with object
representations of their enclosing objects. Therefore, a pointer to an
element of an object representation that is obtained by a <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>
applied to a pointer to <em>a1</em> cannot be used to “escape” from the
bytes of <em>a1</em> and reach bytes of <em>a2</em> that exist outside
<em>a1</em>.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<h1 data-number="7" id="polls"><span class="header-section-number">7</span> Polls<a href="#polls" class="self-link"></a></h1>
<p><strong>EWGI</strong></p>
<p>Should accessing the object representation be defined behavior?</p>
<blockquote>
<p>Unanimous consent</p>
</blockquote>
<p>Forward P1839R1 as presented to EWG, recommending that this be a core
issue?</p>
<blockquote>
<p>Unanimous consent</p>
</blockquote>
<p><strong>EWG</strong></p>
<p>It should be possible to access the entire object representation
through a pointer to a char-like type as a DR.</p>
<blockquote>
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>F</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>N</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>A</strong>
</div></th>
<th style="text-align: center;"><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">10</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">2</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">0</td>
</tr>
</tbody>
</table>
</blockquote>
<blockquote>
<p>Consensus</p>
</blockquote>
<h1 data-number="8" id="proposed-wording"><span class="header-section-number">8</span> Proposed wording<a href="#proposed-wording" class="self-link"></a></h1>
<p>The reported issue is intended as a defect report with the proposed
resolution as follows. The effect of the wording changes should be
applied in implementations of all previous versions of C++ where they
apply. The proposed changes are relative to the C++ working draft <span class="citation" data-cites="N5001">[<a href="https://wg21.link/n5001" role="doc-biblioref">N5001</a>]</span>.</p>
<p>Modify §<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p3
as follows:</p>
<blockquote>
<p>If a complete object is created ([expr.new]) in storage associated
with another object <em>e</em> of type “array of <em>N</em> <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>”
<span class="add" style="color: #006e28"><ins>other than a synthesized
object representation ([basic.types.general])</ins></span> or of type
“array of <em>N</em>
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>”
([cstddef.syn]), that array <em>provides storage</em> for the created
object if […]</p>
</blockquote>
<p>Modify §<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p4
as follows:</p>
<blockquote>
<p>An object <em>a</em> is <em>nested within</em> another object
<em>b</em> if</p>
<ul>
<li><em>a</em> is a subobject of <em>b</em>, or</li>
<li><em>b</em> provides storage for <em>a</em>, or</li>
<li>there exists an object <em>c</em> where <em>a</em> is nested within
<em>c</em>, and <em>c</em> is nested within <em>b</em>.</li>
</ul>
<div class="add" style="color: #006e28">
<p>[<em>Note</em>: An object representation is not nested within any
other object representation. —<em>end note</em>]</p>
</div>
</blockquote>
<p>Modify §<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p10
as follows:</p>
<blockquote>
<p>Unless an object is a bit-field or a subobject of zero size, the
address of that object is the address of the first byte it occupies. Two
objects with overlapping lifetimes that are not bit-fields may have the
same address if</p>
<ul>
<li>one is nested within the other,</li>
<li>at least one is a subobject of zero size and they are not of similar
types ([conv.qual]),<span class="rm" style="color: #bf0303"><del>or</del></span></li>
<li><span class="add" style="color: #006e28"><ins>at least one is a
synthesized object representation or element thereof,
or</ins></span></li>
<li>they are both potentially non-unique objects;</li>
</ul>
<p>otherwise, they have distinct addresses and occupy disjoint bytes of
storage.</p>
</blockquote>
<p>Modify §<span>6.7.2
<a href="https://wg21.link/N5001#intro.object">[intro.object]</a></span>p14
as follows:</p>
<blockquote>
<p>Except during constant evaluation, an operation that begins the
lifetime of an array of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
or <code class="sourceCode cpp">std<span class="op">::</span>byte</code>
<span class="add" style="color: #006e28"><ins>other than a synthesized
object representation ([basic.types.general])</ins></span> implicitly
creates objects within the region of storage occupied by the array.</p>
</blockquote>
<p>Edit §<span>6.7.4
<a href="https://wg21.link/N5001#basic.life">[basic.life]</a></span>p1
as follows:</p>
<blockquote>
<p>[…] The lifetime of an object of type
<code class="sourceCode cpp">T</code> <span class="add" style="color: #006e28"><ins>other than an element of a synthesized
object representation ([basic.types.general])</ins></span> begins
when:</p>
<ul>
<li>storage with the proper alignment and size for type
<code class="sourceCode cpp">T</code> is obtained, and</li>
<li><span class="add" style="color: #006e28"><ins>if it is not a
synthesized object representation</ins></span>, its initialization (if
any) is complete (including vacuous initialization) ([dcl.init]),</li>
</ul>
<p>except […]. The lifetime of an object <em>o</em> of type
<code class="sourceCode cpp">T</code> <span class="add" style="color: #006e28"><ins>other than an element of a synthesized
object representation</ins></span> ends when:</p>
<ul>
<li>if <code class="sourceCode cpp">T</code> is a non-class type, the
object is destroyed, or</li>
<li>if <code class="sourceCode cpp">T</code> is a class type, the
destructor call starts, or</li>
<li>the storage which the object occupies is released, or is reused by
an object that is <span class="rm" style="color: #bf0303"><del>not</del></span><span class="add" style="color: #006e28"><ins>neither</ins></span> nested within
<em>o</em> ([intro.object]) <span class="add" style="color: #006e28"><ins>nor nested within the object of which
<em>o</em> is the object representation, if any
([basic.types.general])</ins></span>.</li>
</ul>
<p>When evaluating a <em>new-expression</em>, storage is considered
reused after it is returned from the allocation function, but before the
evaluation of the <em>new-initializer</em> ([expr.new]).<br />
[<em>Example 1</em>: […] — <em>end example</em>]<br />
<span class="add" style="color: #006e28"><ins>A synthesized object
representation is not considered to reuse the storage of any other
object.</ins></span></p>
</blockquote>
<p>Insert a new paragraph after §<span>6.7.4
<a href="https://wg21.link/N5001#basic.life">[basic.life]</a></span>p3
as follows:</p>
<blockquote>
<p>The lifetime of a reference begins when its initialization is
complete. The lifetime of a reference ends as if it were a scalar object
requiring storage.</p>
</blockquote>
<blockquote>
<p>[<em>Note 1</em>: [class.base.init] describes the lifetime of base
and member subobjects. —<em>end note</em>]</p>
</blockquote>
<blockquote>
<p><span class="add" style="color: #006e28"><ins>For an object
<em>o</em> of class type, the lifetimes of the elements of the
synthesized object representation begin when the construction of
<em>o</em> begins and end when the destruction of <em>o</em> completes.
Otherwise, the lifetimes of the elements of the synthesized object
representation (if any) are the lifetime of <em>o</em>.</ins></span></p>
</blockquote>
<p>Modify §<span>6.8.1
<a href="https://wg21.link/N5001#basic.types.general">[basic.types.general]</a></span>p4
as follows, splitting it into two paragraphs, and add one paragraph
after it:</p>
<blockquote>
<p>The <em>object representation</em> of a complete object type
<code class="sourceCode cpp">T</code> is the sequence of <em>N</em>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">unsigned char</code></span>
objects</del></span><span class="add" style="color: #006e28"><ins>bytes</ins></span> taken up by a <span class="rm" style="color: #bf0303"><del>non-bit-field</del></span>
complete object of type <code class="sourceCode cpp">T</code>, where
<em>N</em> equals <code class="sourceCode cpp"><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span></code>.
The <em>value representation</em> of a type
<code class="sourceCode cpp">T</code> is the set of bits in the object
representation of <code class="sourceCode cpp">T</code> that participate
in representing a value of type
<code class="sourceCode cpp">T</code>.</p>
</blockquote>
<p><strong>Editor’s note: The paragraph break should be inserted
here.</strong></p>
<blockquote>
<p><span class="add" style="color: #006e28"><ins>For</ins></span><span class="rm" style="color: #bf0303"><del>The object and value
representation of</del></span> a <span class="rm" style="color: #bf0303"><del>non-bit-field</del></span> complete object
<span class="add" style="color: #006e28"><ins>or a non-bit-field
non-potentially-overlapping subobject ([intro.object])</ins></span> of
type <span class="add" style="color: #006e28"><ins><em>cv</em></ins></span>
<code class="sourceCode cpp">T</code><span class="add" style="color: #006e28"><ins>, the object and value
representation</ins></span> are the bytes and bits, respectively, of the
object corresponding to the object and value representation of its
type<span class="add" style="color: #006e28"><ins>; the object
representation is considered to be an array of <em>N</em> <em>cv</em>
<span><code class="sourceCode default">unsigned char</code></span> if
the object occupies contiguous bytes of storage</ins></span>. The object
representation of a bit-field object is the sequence of
<code class="sourceCode cpp">N</code> bits taken up by the object, where
<code class="sourceCode cpp">N</code> is the width of the bit-field
(11.4.10). The value representation of a bit-field object is the set of
bits in the object representation that participate in representing its
value. Bits in the object representation of a type or object that are
not part of the value representation are padding bits. For trivially
copyable types, the value representation is a set of bits in the object
representation that determines a value, which is one discrete element of
an implementation-defined set of values.</p>
</blockquote>
<p><em>Drafting note:</em> The status quo does not specify even the
number of bytes in the object representation of a subobject other than a
bit-field. This is because of issues related to potentially-overlapping
subobjects and was considered a pre-existing defect in the discussion of
<span class="citation" data-cites="CWG2519">[<a href="https://wg21.link/cwg2519" role="doc-biblioref">CWG2519</a>]</span> (Jan 6, 2023 telecon). We leave
object/value representations of potentially-overlapping subobjects
unspecified here, while fixing non-potentially-overlapping
subobjects.</p>
<div class="add" style="color: #006e28">

<blockquote>
<p>For an object <em>o</em> with type <em>cv</em>
<code class="sourceCode default">T</code> whose object representation is
an array <em>A</em>:</p>
<ul>
<li>If <em>o</em> is a complete object of type “array of <em>cv</em>
<code class="sourceCode default">unsigned char</code>”, then <em>A</em>
is <em>o</em>.</li>
<li>Otherwise, if <em>o</em> is the sole element of a complete object
<em>B</em> of type “array of 1 <em>cv</em>
<code class="sourceCode default">unsigned char</code>”, then <em>A</em>
is <em>B</em>.</li>
<li>Otherwise, <em>A</em> is said to be a <em>synthesized object
representation</em>, and is distinct from any object that is not an
object representation.
<ul>
<li>If <em>o</em> is of type <em>cv</em>
<code class="sourceCode default">char</code>, <em>cv</em>
<code class="sourceCode default">unsigned char</code>, or <em>cv</em>
<code class="sourceCode default">std::byte</code>, then the value of the
sole element of <em>A</em> is the value congruent ([basic.fundamental])
to the value of <em>o</em>.</li>
<li>Otherwise, if <em>o</em> is an array whose element type is
<em>cv</em> <code class="sourceCode default">char</code>, <em>cv</em>
<code class="sourceCode default">unsigned char</code>, or <em>cv</em>
<code class="sourceCode default">std::byte</code>, then the value of
each element of <em>A</em> is the value congruent to that of the
corresponding element of <em>o</em>.</li>
<li>Otherwise, for each bit <em>b</em> in <em>o</em>, let <em>b</em>’ be
the corresponding bit of <em>A</em>. Let <em>p(b)</em> be the smallest
subobject of <em>o</em> that contains <em>b</em> other than an inactive
union member or subobject thereof. If <em>p(b)</em> is a union object or
is not within its lifetime or has an indeterminate value, or if
<em>b</em> is not part of the value representation of <em>p(b)</em>,
then <em>b</em>’ has indeterminate value. Otherwise, if <em>b</em> has
an erroneous value, then <em>b</em>’ has an erroneous value. Otherwise,
<em>b</em>’ has an unspecified value that is neither indeterminate nor
erroneous; such a bit retains its value until <em>p(b)</em> is
subsequently modified.</li>
</ul>
[<em>Note:</em> Attempting to access an element of a synthesized object
representation of a volatile object results in undefined behavior
([dcl.type.cv]). —<em>end note</em>]</li>
</ul>
<p>[<em>Note:</em> An object representation is always a complete object.
—<em>end note</em>]</p>
</blockquote>

</div>
<p><em>Drafting note:</em> It’s not entirely clear why
potentially-overlapping subobjects couldn’t be allowed here; reading
from the object representation of a potentially-overlapping subobject
doesn’t seem to pose the same problems as writing to it. But since
potentially-overlapping subobjects were already carved out by <span class="citation" data-cites="CWG43">[<a href="https://wg21.link/cwg43" role="doc-biblioref">CWG43</a>]</span>, even as the source of a copy, it
seems wise to repeat the restriction here unless CWG is certain that the
restriction is not needed.</p>
<p><em>Drafting note:</em> Because an object representation is
pointer-interconvertible with its first element (see below), this new
rule would expand reachability if we allowed an array object that isn’t
a complete object to be its own object representation: the first element
of that array would become pointer-interconvertible with whatever the
array itself is pointer-interconvertible with. To prevent this, we must
restrict the set of objects that are allowed to be their own object
representation to complete objects only; you can already reach every
byte of a complete <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
array from a pointer to its first element.</p>
<p>Modify §<span>6.8.4
<a href="https://wg21.link/N5001#basic.compound">[basic.compound]</a></span>p5
as follows:</p>
<blockquote>
<p>Two objects <em>a</em> and <em>b</em> are
<em>pointer-interconvertible</em> if:</p>
<ul>
<li>they are the same object, or</li>
<li>one is a union object and the other is a non-static data member of
that object ([class.union]), or</li>
<li>one is a standard-layout class object and the other is the first
non-static data member of that object or any base class subobject of
that object ([class.mem]), or</li>
<li><span class="add" style="color: #006e28"><ins>one is the object
representation of the other, or the first element thereof,
or</ins></span></li>
<li>there exists an object <em>c</em> such that <em>a</em> and
<em>c</em> are pointer-interconvertible, and <em>c</em> and <em>b</em>
are pointer-interconvertible.</li>
</ul>
<p>If two objects are pointer-interconvertible, then they have the same
address<span class="rm" style="color: #bf0303"><del>, and it is possible
to obtain a pointer to one from a pointer to the other via a
<span><code class="sourceCode default">reinterpret_cast</code></span>
([expr.reinterpret.cast])</del></span>.<br />
<span class="add" style="color: #006e28"><ins>[<em>Note</em>: A
<span><code class="sourceCode default">reinterpret_cast</code></span>
([expr.reinterpret.cast]) never converts a pointer to <em>a</em> to a
pointer to <em>b</em> unless <em>a</em> and <em>b</em> are
pointer-interconvertible. —<em>end note</em>]</ins></span><br />
[<em>Note</em>: An array object and its first element are not
pointer-interconvertible, even though they have the same address<span class="add" style="color: #006e28"><ins>, unless the array is an object
representation</ins></span>. —<em>end note</em>]</p>
</blockquote>
<p>Modify §<span>7.2.1
<a href="https://wg21.link/N5001#basic.lval">[basic.lval]</a></span>p11
as follows:</p>
<blockquote>
<p>An object of dynamic type
<code class="sourceCode cpp">T</code><sub>obj</sub> is
<em>type-accessible</em> through a glvalue of type
<code class="sourceCode cpp">T</code><sub>ref</sub> if
<code class="sourceCode cpp">T</code><sub>ref</sub> is similar
([conv.qual]) to:</p>
<ul>
<li><code class="sourceCode cpp">T</code><sub>obj</sub>,</li>
<li>a type that is the signed or unsigned type corresponding to
<code class="sourceCode cpp">T</code><sub>obj</sub>, or</li>
<li>a
<code class="sourceCode cpp"><span class="dt">char</span></code><span class="rm" style="color: #bf0303"><del>,
<span><code class="sourceCode default">unsigned char</code></span>,</del></span>
or <code class="sourceCode cpp">std<span class="op">::</span>byte</code>
type<span class="add" style="color: #006e28"><ins>, if the object is an
element of an object representation
([basic.life.general])</ins></span>.</li>
</ul>
<p>If a program attempts to access ([defns.access]) the stored value of
an object through a glvalue through which it is not type-accessible, the
behavior is undefined. […]<br />
[<em>Note 11:</em> […]]<br />
<span class="add" style="color: #006e28"><ins>[<em>Example 2:</em> An
element of an object representation can be accessed through a glvalue of
type <span><code class="sourceCode default">char</code></span>,
<span><code class="sourceCode default">unsigned char</code></span>,
<span><code class="sourceCode default">signed char</code></span>,
<span><code class="sourceCode default">std::byte</code></span>, or a
cv-qualified version of any of these types. —<em>end
example</em>]</ins></span></p>
</blockquote>
<p><em>Drafting note</em>: Because this paper doesn’t address object
representations of potentially-overlapping subobjects, we lack the
wording to say what happens if a reference to such an object is cast to
<code class="sourceCode cpp"><span class="dt">char</span><span class="op">&amp;</span></code>,
<code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span><span class="op">&amp;</span></code>,
or <code class="sourceCode cpp">std<span class="op">::</span>byte<span class="op">&amp;</span></code>,
and the resulting lvalue is accessed. Therefore, the wording above
avoids giving the impression that such an access is well defined: if we
claimed that it were well defined, we would have to specify the
behavior. A similar issue arises when the object is discontiguous.</p>
<p>Modify §<span>7.3.2
<a href="https://wg21.link/N5001#conv.lval">[conv.lval]</a></span>p3.4,
as amended by the proposed resolution of <span class="citation" data-cites="CWG2901">[<a href="https://wg21.link/cwg2901" role="doc-biblioref">CWG2901</a>]</span>, as follows:</p>
<blockquote>
<ul>
<li>Otherwise, the object indicated by the glvalue is read
([defns.access]). Let <em>V</em> be the value contained in the object.
If <code class="sourceCode cpp">T</code> is an integer type <span class="add" style="color: #006e28"><ins>or <em>cv</em>
<span><code class="sourceCode default">std::byte</code></span></ins></span>,
the prvalue result is the value of type
<code class="sourceCode cpp">T</code> congruent ([basic.fundamental]) to
<em>V</em>, and <em>V</em> otherwise. […]</li>
</ul>
</blockquote>
<p>Modify §<span>7.6.1.9
<a href="https://wg21.link/N5001#expr.static.cast">[expr.static.cast]</a></span>p13
as follows:</p>
<blockquote>
<p>[…] Otherwise, if the original pointer value points to an object
<em>a</em>, <span class="rm" style="color: #bf0303"><del>and there is an
object <em>b</em> of type similar to
<span><code class="sourceCode default">T</code></span> that is
pointer-interconvertible ([basic.compound]) with <em>a</em>, the result
is a pointer to <em>b</em>. Otherwise, the pointer value is unchanged by
the conversion.</del></span><span class="add" style="color: #006e28"><ins>let <em>S</em> be the set of objects that
are pointer-interconvertible with <em>a</em> and have type similar to
<span><code class="sourceCode default">T</code></span>.</ins></span></p>
<div class="add" style="color: #006e28">

<ul>
<li>If <em>S</em> contains <em>a</em>, the result is a pointer to
<em>a</em>.</li>
<li>Otherwise, the result is a member of <em>S</em> whose complete
object is not a synthesized object representation if any such result
would give the program defined behavior. If there are multiple possible
results that would give the program defined behavior, the result is an
unspecified choice among them.</li>
<li>Otherwise (i.e. when there are no such members of <em>S</em> that
would give the program defined behavior), if <em>a</em>’s object
representation is an array <em>A</em> and
<code class="sourceCode default">T</code> is similar to the type of
<em>A</em>, the result is a pointer to <em>A</em>.</li>
<li>Otherwise, if <em>a</em>’s object representation is an array
<em>A</em> and <code class="sourceCode default">T</code> is <em>cv</em>
<code class="sourceCode default">unsigned char</code>, the result is a
pointer to the first element of <em>a</em>’s object representation.</li>
<li>Otherwise, if <code class="sourceCode default">T</code> is
<em>cv</em> <code class="sourceCode default">std::byte</code>,
<em>cv</em> <code class="sourceCode default">char</code>, or an array of
one of these types, let <code class="sourceCode default">U</code> be the
type obtained from <code class="sourceCode default">T</code> by
replacing <code class="sourceCode default">std::byte</code> or
<code class="sourceCode default">char</code> with
<code class="sourceCode default">unsigned char</code>. If a
<code class="sourceCode default">static_cast</code> of the operand to
<code class="sourceCode default">U*</code> would yield a pointer to an
object representation or element thereof, the result of the cast to
<code class="sourceCode default">T*</code> is that pointer value.</li>
<li>Otherwise, the result is a pointer to <em>a</em>.</li>
</ul>
<p>Otherwise, if the original pointer value points past the end of an
object <em>a</em>:</p>
<ul>
<li>If <em>a</em>’s object representation is an array <em>A</em> and
<code class="sourceCode default">T</code> is similar to the type of
<em>A</em>, the result is
<code class="sourceCode default">&amp;A + 1</code>.</li>
<li>Otherwise, if <em>a</em>’s object representation is an array
<em>A</em> and <code class="sourceCode default">T</code> is <em>cv</em>
<code class="sourceCode default">unsigned char</code>, the result is a
pointer past the last element of <em>A</em>.</li>
<li>Otherwise, if <code class="sourceCode default">T</code> is
<em>cv</em> <code class="sourceCode default">std::byte</code>,
<em>cv</em> <code class="sourceCode default">char</code>, or an array of
one of these types, let <code class="sourceCode default">U</code> be the
type obtained from <code class="sourceCode default">T</code> by
replacing <code class="sourceCode default">std::byte</code> or
<code class="sourceCode default">char</code> with
<code class="sourceCode default">unsigned char</code>. If a
<code class="sourceCode default">static_cast</code> of the operand to
<code class="sourceCode default">U*</code> would yield a pointer value
defined by one of the above cases, the result of the cast to
<code class="sourceCode default">T*</code> is that pointer value.</li>
<li>Otherwise, the result is the value of the operand.</li>
</ul>

</div>
</blockquote>
<p><em>Drafting note:</em> The case of multiple objects is a
pre-existing defect: when a union has multiple members of type similar
to <code class="sourceCode cpp">T</code>, a
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>
from <code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span></code>
to <code class="sourceCode cpp">T<span class="op">*</span></code> can
yield a pointer to any of them. In cases that are allowed during
constant evaluation, the above change ensures that there is no ambiguity
about the result (<em>i.e.</em> the result always points to the original
object). At runtime, the choice is unobservable except when some choices
would result in lifetime-related UB, modifying a const object, or
accessing a volatile object through a non-volatile glvalue.</p>
<p>Modify §<span>7.6.6
<a href="https://wg21.link/N5001#expr.add">[expr.add]</a></span>p6 as
follows:</p>
<blockquote>
<p>For addition or subtraction, if the expressions
<code class="sourceCode cpp">P</code> or
<code class="sourceCode cpp">Q</code> have type “pointer to <em>cv</em>
<code class="sourceCode cpp">T</code>”<span class="rm" style="color: #bf0303"><del>, where
<span><code class="sourceCode default">T</code></span> and the array
element type are not similar, the behavior is
undefined.</del></span><span class="add" style="color: #006e28"><ins>,
one of the following shall hold:</ins></span></p>
<ul>
<li><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">T</code></span>
is similar to the array element type, or</ins></span></li>
<li><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">T</code></span>
is similar to <span><code class="sourceCode default">char</code></span>
or <span><code class="sourceCode default">std::byte</code></span> and
the pointer value points to a (possibly-hypothetical) element of an
object representation.</ins></span></li>
</ul>
<p><span class="add" style="color: #006e28"><ins>Otherwise, the behavior
is undefined.</ins></span></p>
</blockquote>
<p>Modify §<span>9.2.9.2
<a href="https://wg21.link/N5001#dcl.type.cv">[dcl.type.cv]</a></span>p5
as follows:</p>
<blockquote>
<p><span class="add" style="color: #006e28"><ins>If an attempt is made
to access an element <em>e</em> of a synthesized object representation
([basic.types.general]) and <em>e</em> overlaps the storage occupied by
a volatile object (including a subobject), the behavior is undefined.
Otherwise, the</ins></span> <span class="rm" style="color: #bf0303"><del>The</del></span> semantics of an access
through a volatile glvalue are implementation-defined. If an attempt is
made to access an object defined with a volatile-qualified type through
the use of a non-volatile glvalue, the behavior is undefined.</p>
</blockquote>
<p>Modify §<span>17.6.5
<a href="https://wg21.link/N5001#ptr.launder">[ptr.launder]</a></span>p2
as follows, relative to the CWG-approved resolution for <a href="https://cplusplus.github.io/LWG/lwg-active.html#4130">LWG4130</a>:</p>
<blockquote>
<p><em>Preconditions:</em> <code class="sourceCode cpp">p</code>
represents the address <em>A</em> of a byte in memory. <span class="rm" style="color: #bf0303"><del>An</del></span> <span class="add" style="color: #006e28"><ins>There is an</ins></span> object <em>X</em>
<span class="rm" style="color: #bf0303"><del>whose type is similar
([conv.qual]) to <span><code class="sourceCode default">T</code></span>
is</del></span> located at the address <em>A</em> <span class="add" style="color: #006e28"><ins>such that</ins></span></p>
<div class="add" style="color: #006e28">

<ul>
<li><em>X</em>’s type is similar ([conv.qual]) to
<code class="sourceCode default">T</code>,</li>
<li><code class="sourceCode default">T</code> is <em>cv</em>
<code class="sourceCode default">std::byte</code> or <em>cv</em>
<code class="sourceCode default">char</code>, and <em>X</em> is an
element of an object representation ([basic.types.general]), or</li>
<li><code class="sourceCode default">T</code> is an array type whose
element type is <em>cv</em>
<code class="sourceCode default">std::byte</code> or <em>cv</em>
<code class="sourceCode default">char</code>, and <em>X</em> is an
object representation</li>
</ul>

</div>
<p><span class="rm" style="color: #bf0303"><del>, and</del></span><span class="add" style="color: #006e28"><ins>and such that
<em>X</em></ins></span> is either within its lifetime ([basic.life]) or
is an array element subobject whose containing array object is within
its lifetime. All bytes of storage that would be reachable through
([basic.compound]) the result are reachable through
<code class="sourceCode cpp">p</code>.</p>
</blockquote>
<p>Modify §<span>17.6.5
<a href="https://wg21.link/N5001#ptr.launder">[ptr.launder]</a></span>p3
as follows:</p>
<blockquote>
<p><em>Returns:</em> A value of type
<code class="sourceCode cpp">T<span class="op">*</span></code> that
points to <span class="add" style="color: #006e28"><ins>the
object</ins></span> <em>X</em> <span class="add" style="color: #006e28"><ins>that would give the program defined
behavior, or to an unspecified choice among them if more than one such
object exists. If no such object exists, the behavior is
undefined</ins></span>.</p>
</blockquote>
<h1 data-number="9" id="document-history"><span class="header-section-number">9</span> Document history<a href="#document-history" class="self-link"></a></h1>
<ul>
<li><strong>R0</strong>, 2019-07-30: Initial version.</li>
<li><strong>R1</strong>, 2019-09-28: Allowed pointer arithmetic on
expressions of type <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span><span class="op">*</span></code>,
<code class="sourceCode cpp"><span class="dt">char</span><span class="op">*</span></code>
and <code class="sourceCode cpp">std<span class="op">::</span>byte<span class="op">*</span></code>
when pointing to objects of different type. Removed exclusion of the
object representation of objects of zero size from appearing in the
object representation of their containing object. Added
multi-dimensional arrays of contiguous-layout types to the definition of
contiguous-layout types. Slight change to the behavior of
<code class="sourceCode cpp">std<span class="op">::</span>launder</code>
for when there are multiple viable objects.</li>
<li><strong>R2</strong>, 2019-11-20: Removed contiguous-layout types
from wording, this should be tackled by <span class="citation" data-cites="P1945R0">[<a href="https://wg21.link/p1945r0" role="doc-biblioref">P1945R0</a>]</span>.</li>
<li><strong>R3</strong>, 2022-02-15: Moved wording for casts to the
rules of pointer-interconvertibility. Changed the wording for
<code class="sourceCode cpp">std<span class="op">::</span>launder</code>
to bind to the best candidate object.</li>
<li><strong>R4</strong>, 2022-03-16: Changed the wording to fix
ambiguous usage of <em>N</em> in object representations
specification.</li>
<li><strong>R5</strong>, 2022-06-16: Reduced scope of paper to only
reading object representations, not writing. Completely rewrote
rationale. Added wording to prevent implicit object creation within
object representations. Added cross-reference to types with contiguous
storage ([intro.object]) in the wording. Fixed inconsistency in the
wording by defining that only <code class="sourceCode cpp"><span class="dt">unsigned</span>   <span class="dt">char</span></code>
is its own object representation, not
<code class="sourceCode cpp"><span class="dt">char</span></code> or
<code class="sourceCode cpp">std<span class="op">::</span>byte</code>.
Removed erroneous wording regarding memory locations. Added list of
known issues.</li>
<li><strong>R6</strong>, 2024-09-26: Converted to HTML (generated from
Markdown). Rebased wording on N4988. Removed unnecessary speculation
about the behaviour of modifying object representations. Made elements
of a subobject object representation distinct objects from the elements
of the containing object’s object representation and adjusted wording
accordingly. Clarified which bits of object representations are
indeterminate or erroneous. Removed some ambiguity over the result of
<code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>
and added wording for the case of past-the-end pointers and casts to
<code class="sourceCode cpp">std<span class="op">::</span>byte<span class="op">*</span></code>.
Made the object representation of a non-contiguous object no longer
consist of <em>cv</em> <code class="sourceCode cpp"><span class="dt">unsigned</span>   <span class="dt">char</span></code>
objects. Defined object representation of (some) subobjects. Fixed a
wording bug for pointer arithmetic.</li>
<li><strong>R7</strong>, 2025-01-10: Fixes after CWG review:
<ul>
<li>Accessing object representation is no longer permitted for volatile
objects.</li>
<li><code class="sourceCode cpp">std<span class="op">::</span>launder</code>
now gives an unspecified choice in the case of multiple objects of the
same type, and allows the case where
<code class="sourceCode cpp">T</code> is of type <em>cv</em>
<code class="sourceCode cpp">std<span class="op">::</span>byte</code> or
array thereof: you can get a pointer to the object representation or
array thereof.</li>
<li>The lifetimes of elements of synthesized object representations are
now considered to cover the entire period of construction and
destruction. We also clarify that a synthesized object representation
doesn’t have to be initialized (so its lifetime starts as soon as
suitable storage is obtained) and that its storage isn’t considered
reused by objects that are nested within the actual object.</li>
<li>The description of <em>p(b)</em> now excludes inactive union members
and their subobjects, so you get an active union member if possible,
otherwise the bit is treated as if it were a padding bit.</li>
<li>Unspecified object representation bit values are now explicitly
specified to be stable (but the value is still unspecified) and to not
be indeterminate nor erroneous.</li>
<li>Added “congruent to” for determing the value of an element of an
object representation of a
<code class="sourceCode cpp"><span class="dt">char</span></code> or
array of
<code class="sourceCode cpp"><span class="dt">char</span></code>.</li>
<li>Subobject object representations are no longer considered to be
nested within enclosing objects’ object representations. Instead, we
carve out explicit exceptions to allow object representations to share
storage and to not reuse storage of another object. We also clarify that
synthesized object representations never provide storage.</li>
<li>The wording has been improved for object representations of
non-potentially-overlapping subobjects.</li>
<li>Added explanation for why only <em>complete</em> arrays of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
are allowed to be their own object representations.</li>
<li>The strict aliasing rule has been modified to reflect the fact that
access to object representations is now access to <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>
objects, not to the original object.</li>
<li>The wording for obtaining a pointer to an element of an object
representation by casting to <code class="sourceCode cpp"><span class="dt">char</span><span class="op">*</span></code>
has been restored; it appears to have been removed accidentally in
R3.</li>
<li>Removed the “would be well-formed” condition from
[expr.static.cast]p13: the cases that cast away constness are checked
earlier in the paragraph.</li>
</ul></li>
</ul>
<h1 data-number="10" id="acknowledgements"><span class="header-section-number">10</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Many thanks to Jens Maurer and Hubert Tong for their help with the
wording. Thanks to Janet Cobb, John Iacino, Marcell Kiss, Killian Long,
Theodoric Stier, and everyone who participated on the std-proposals
mailing list and Core reflector for their countless reviews and
suggestions for earlier revisions of this paper. Thanks to Professor Ben
Woodard for his grammatical review of an earlier revision of this
paper.</p>
<h1 data-number="11" id="bibliography"><span class="header-section-number">11</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-CWG1314" class="csl-entry" role="doc-biblioentry">
[CWG1314] Nikolay Ivchenkov. 2011-05-06. Pointer arithmetic within
standard-layout objects. <a href="https://wg21.link/cwg1314"><div class="csl-block">https://wg21.link/cwg1314</div></a>
</div>
<div id="ref-CWG2519" class="csl-entry" role="doc-biblioentry">
[CWG2519] Jiang An. 2022-01-20. Object representation of a bit-field. <a href="https://wg21.link/cwg2519"><div class="csl-block">https://wg21.link/cwg2519</div></a>
</div>
<div id="ref-CWG2901" class="csl-entry" role="doc-biblioentry">
[CWG2901] Jan Schultke. 2024-06-14. Unclear semantics for near-match
aliased access. <a href="https://wg21.link/cwg2901"><div class="csl-block">https://wg21.link/cwg2901</div></a>
</div>
<div id="ref-CWG43" class="csl-entry" role="doc-biblioentry">
[CWG43] Nathan Myers. 1998-09-15. Copying base classes (PODs) using
memcpy. <a href="https://wg21.link/cwg43"><div class="csl-block">https://wg21.link/cwg43</div></a>
</div>
<div id="ref-N5001" class="csl-entry" role="doc-biblioentry">
[N5001] Thomas Köppe. 2024-12-17. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n5001"><div class="csl-block">https://wg21.link/n5001</div></a>
</div>
<div id="ref-P0137R1" class="csl-entry" role="doc-biblioentry">
[P0137R1] Richard Smith. 2016-06-23. Core Issue 1776: Replacement of
class objects containing reference members. <a href="https://wg21.link/p0137r1"><div class="csl-block">https://wg21.link/p0137r1</div></a>
</div>
<div id="ref-P0593R6" class="csl-entry" role="doc-biblioentry">
[P0593R6] Richard Smith, Ville Voutilainen. 2020-02-14. Implicit
creation of objects for low-level object manipulation. <a href="https://wg21.link/p0593r6"><div class="csl-block">https://wg21.link/p0593r6</div></a>
</div>
<div id="ref-P1945R0" class="csl-entry" role="doc-biblioentry">
[P1945R0] Krystian Stasiowski. 2019-10-28. Making More Objects
Contiguous. <a href="https://wg21.link/p1945r0"><div class="csl-block">https://wg21.link/p1945r0</div></a>
</div>
</div>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Since C++20, one can also use <code class="sourceCode cpp">std<span class="op">::</span>bit_cast</code> to
copy the bytes into a struct that contains an array of <code class="sourceCode cpp"><span class="dt">unsigned</span> <span class="dt">char</span></code>,
assuming that the struct does not have any padding.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>All citations to the Standard are to working draft N5001
unless otherwise specified.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>These reachability-based restrictions limit
compatibility between C and C++, in particular when it comes to C code
that uses <code class="sourceCode cpp">offsetof</code> to implement
intrusive data structures. A separate paper, <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3407r0.html">P3407R0</a>,
proposes to remove these restrictions. Additional specification
difficulties are raised by such a direction, which will not be discussed
here.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
