<!doctype html><html lang="en">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<title>d0593r2: Implicit creation of objects for low-level object manipulation</title>
<style data-fill-with="stylesheet">/******************************************************************************
* Style sheet for the W3C specifications *
*
* Special classes handled by this style sheet include:
*
* Indices
* - .toc for the Table of Contents (<ol class="toc">)
* + <span class="secno"> for the section numbers
* - #toc for the Table of Contents (<nav id="toc">)
* - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
* - table.index for Index Tables (e.g. for properties or elements)
*
* Structural Markup
* - table.data for general data tables
* -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
* -> use <table class='complex data'> for extra-complex tables
* -> use <td class='long'> for paragraph-length cell content
* -> use <td class='pre'> when manual line breaks/indentation would help readability
* - dl.switch for switch statements
* - ol.algorithm for algorithms (helps to visualize nesting)
* - .figure and .caption (HTML4) and figure and figcaption (HTML5)
* -> .sidefigure for right-floated figures
* - ins/del
*
* Code
* - pre and code
*
* Special Sections
* - .note for informative notes (div, p, span, aside, details)
* - .example for informative examples (div, p, pre, span)
* - .issue for issues (div, p, span)
* - .assertion for assertions (div, p, span)
* - .advisement for loud normative statements (div, p, strong)
* - .annoying-warning for spec obsoletion notices (div, aside, details)
*
* Definition Boxes
* - pre.def for WebIDL definitions
* - table.def for tables that define other entities (e.g. CSS properties)
* - dl.def for definition lists that define other entitles (e.g. HTML elements)
*
* Numbering
* - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
* - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
* - ::before styled for CSS-generated issue/example/figure numbers:
* -> Documents wishing to use this only need to add
* figcaption::before,
* .caption::before { content: "Figure " counter(figure) " "; }
* .example::before { content: "Example " counter(example) " "; }
* .issue::before { content: "Issue " counter(issue) " "; }
*
* Header Stuff (ignore, just don't conflict with these classes)
* - .head for the header
* - .copyright for the copyright
*
* Miscellaneous
* - .overlarge for things that should be as wide as possible, even if
* that overflows the body text area. This can be used on an item or
* on its container, depending on the effect desired.
* Note that this styling basically doesn't help at all when printing,
* since A4 paper isn't much wider than the max-width here.
* It's better to design things to fit into a narrower measure if possible.
* - js-added ToC jump links (see fixup.js)
*
******************************************************************************/
/******************************************************************************/
/* Body */
/******************************************************************************/
        body {
                counter-reset: example figure issue;
                /* Layout */
                max-width: 50em; /* limit line length to 50em for readability */
                margin: 0 auto; /* center text within page */
                padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
                padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag */
                /* Typography */
                line-height: 1.5;
                font-family: sans-serif;
                widows: 2;
                orphans: 2;
                word-wrap: break-word;
                overflow-wrap: break-word;
                hyphens: auto;
                /* Colors */
                color: black;
                background: white top left fixed no-repeat;
                background-size: 25px auto;
        }
/******************************************************************************/
/* Front Matter & Navigation */
/******************************************************************************/
/** Header ********************************************************************/
        div.head { margin-bottom: 1em }
        div.head hr { border-style: solid; }
        div.head h1 {
                font-weight: bold;
                margin: 0 0 .1em;
                font-size: 220%;
        }
        div.head h2 { margin-bottom: 1.5em;}
/** W3C Logo ******************************************************************/
        .head .logo {
                float: right;
                margin: 0.4rem 0 0.2rem .4rem;
        }
        .head img[src*="logos/W3C"] {
                display: block;
                border: solid #1a5e9a;
                border-width: .65rem .7rem .6rem;
                border-radius: .4rem;
                background: #1a5e9a;
                color: white;
                font-weight: bold;
        }
        .head a:hover > img[src*="logos/W3C"],
        .head a:focus > img[src*="logos/W3C"] {
                opacity: .8;
        }
        .head a:active > img[src*="logos/W3C"] {
                background: #c00;
                border-color: #c00;
        }
        /* see also additional rules in Link Styling section */
/** Copyright *****************************************************************/
        p.copyright,
        p.copyright small { font-size: small }
/** Back to Top / ToC Toggle **************************************************/
        @media print {
                #toc-nav {
                        display: none;
                }
        }
        @media not print {
                #toc-nav {
                        position: fixed;
                        z-index: 2;
                        bottom: 0; left: 0;
                        margin: 0;
                        min-width: 1.33em;
                        border-top-right-radius: 2rem;
                        box-shadow: 0 0 2px;
                        font-size: 1.5em;
                        color: black;
                }
                #toc-nav > a {
                        display: block;
                        white-space: nowrap;
                        height: 1.33em;
                        padding: .1em 0.3em;
                        margin: 0;
                        background: white;
                        box-shadow: 0 0 2px;
                        border: none;
                        border-top-right-radius: 1.33em;
                        background: white;
                }
                #toc-nav > #toc-jump {
                        padding-bottom: 2em;
                        margin-bottom: -1.9em;
                }
                #toc-nav > a:hover,
                #toc-nav > a:focus {
                        background: #f8f8f8;
                }
                #toc-nav > a:not(:hover):not(:focus) {
                        color: #707070;
                }
                /* statusbar gets in the way on keyboard focus; remove once browsers fix */
                #toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
                        padding-bottom: 1.5rem;
                }
                #toc-nav:not(:hover) > a:not(:focus) > span + span {
                        /* Ideally this uses :focus-within on #toc-nav */
                        display: none;
                }
                #toc-nav > a > span + span {
                        padding-right: 0.2em;
                }
                #toc-toggle-inline {
                        vertical-align: 0.05em;
                        font-size: 80%;
                        color: gray;
                        color: hsla(203,20%,40%,.7);
                        border-style: none;
                        background: transparent;
                        position: relative;
                }
                #toc-toggle-inline:hover:not(:active),
                #toc-toggle-inline:focus:not(:active) {
                        text-shadow: 1px 1px silver;
                        top: -1px;
                        left: -1px;
                }
                #toc-nav :active {
                        color: #C00;
                }
        }
/** ToC Sidebar ***************************************************************/
        /* Floating sidebar */
        @media screen {
                body.toc-sidebar #toc {
                        position: fixed;
                        top: 0; bottom: 0;
                        left: 0;
                        width: 23.5em;
                        max-width: 80%;
                        max-width: calc(100% - 2em - 26px);
                        overflow: auto;
                        padding: 0 1em;
                        padding-left: 42px;
                        padding-left: calc(1em + 26px);
                        background: inherit;
                        background-color: #f7f8f9;
                        z-index: 1;
                        box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
                }
                body.toc-sidebar #toc h2 {
                        margin-top: .8rem;
                        font-variant: small-caps;
                        font-variant: all-small-caps;
                        text-transform: lowercase;
                        font-weight: bold;
                        color: gray;
                        color: hsla(203,20%,40%,.7);
                }
                body.toc-sidebar #toc-jump:not(:focus) {
                        width: 0;
                        height: 0;
                        padding: 0;
                        position: absolute;
                        overflow: hidden;
                }
        }
        /* Hide main scroller when only the ToC is visible anyway */
        @media screen and (max-width: 28em) {
                body.toc-sidebar {
                        overflow: hidden;
                }
        }
        /* Sidebar with its own space */
        @media screen and (min-width: 78em) {
                body:not(.toc-inline) #toc {
                        position: fixed;
                        top: 0; bottom: 0;
                        left: 0;
                        width: 23.5em;
                        overflow: auto;
                        padding: 0 1em;
                        padding-left: 42px;
                        padding-left: calc(1em + 26px);
                        background: inherit;
                        background-color: #f7f8f9;
                        z-index: 1;
                        box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
                }
                body:not(.toc-inline) #toc h2 {
                        margin-top: .8rem;
                        font-variant: small-caps;
                        font-variant: all-small-caps;
                        text-transform: lowercase;
                        font-weight: bold;
                        color: gray;
                        color: hsla(203,20%,40%,.7);
                }
                body:not(.toc-inline) {
                        padding-left: 29em;
                }
                /* See also Overflow section at the bottom */
                body:not(.toc-inline) #toc-jump:not(:focus) {
                        width: 0;
                        height: 0;
                        padding: 0;
                        position: absolute;
                        overflow: hidden;
                }
        }
        @media screen and (min-width: 90em) {
                body:not(.toc-inline) {
                        margin: 0 4em;
                }
        }
/******************************************************************************/
/* Sectioning */
/******************************************************************************/
/** Headings ******************************************************************/
        h1, h2, h3, h4, h5, h6, dt {
                page-break-after: avoid;
                page-break-inside: avoid;
                font: 100% sans-serif; /* Reset all font styling to clear out UA styles */
                font-family: inherit; /* Inherit the font family. */
                line-height: 1.2; /* Keep wrapped headings compact */
                hyphens: manual; /* Hyphenated headings look weird */
        }
        h2, h3, h4, h5, h6 {
                margin-top: 3rem;
        }
        h1, h2, h3 {
                color: #005A9C;
                background: transparent;
        }
        h1 { font-size: 170%; }
        h2 { font-size: 140%; }
        h3 { font-size: 120%; }
        h4 { font-weight: bold; }
        h5 { font-style: italic; }
        h6 { font-variant: small-caps; }
        dt { font-weight: bold; }
/** Subheadings ***************************************************************/
        h1 + h2,
        #subtitle {
                /* #subtitle is a subtitle in an H2 under the H1 */
                margin-top: 0;
        }
        h2 + h3,
        h3 + h4,
        h4 + h5,
        h5 + h6 {
                margin-top: 1.2em; /* = 1 x line-height */
        }
/** Section divider ***********************************************************/
        :not(.head) > hr {
                font-size: 1.5em;
                text-align: center;
                margin: 1em auto;
                height: auto;
                border: transparent solid 0;
                background: transparent;
        }
        :not(.head) > hr::before {
                content: "\2727\2003\2003\2727\2003\2003\2727";
        }
/******************************************************************************/
/* Paragraphs and Lists */
/******************************************************************************/
        p {
                margin: 1em 0;
        }
        dd > p:first-child,
        li > p:first-child {
                margin-top: 0;
        }
        ul, ol {
                margin-left: 0;
                padding-left: 2em;
        }
        li {
                margin: 0.25em 0 0.5em;
                padding: 0;
        }
        dl dd {
                margin: 0 0 .5em 2em;
        }
        .head dd + dd { /* compact for header */
                margin-top: -.5em;
        }
        /* Style for algorithms */
        ol.algorithm ol:not(.algorithm),
        .algorithm > ol ol:not(.algorithm) {
         border-left: 0.5em solid #DEF;
        }
        /* Put nice boxes around each algorithm. */
        [data-algorithm]:not(.heading) {
         padding: .5em;
         border: thin solid #ddd; border-radius: .5em;
         margin: .5em calc(-0.5em - 1px);
        }
        [data-algorithm]:not(.heading) > :first-child {
         margin-top: 0;
        }
        [data-algorithm]:not(.heading) > :last-child {
         margin-bottom: 0;
        }
        /* Style for switch/case <dl>s */
        dl.switch > dd > ol.only,
        dl.switch > dd > .only > ol {
         margin-left: 0;
        }
        dl.switch > dd > ol.algorithm,
        dl.switch > dd > .algorithm > ol {
         margin-left: -2em;
        }
        dl.switch {
         padding-left: 2em;
        }
        dl.switch > dt {
         text-indent: -1.5em;
         margin-top: 1em;
        }
        dl.switch > dt + dt {
         margin-top: 0;
        }
        dl.switch > dt::before {
         content: '\21AA';
         padding: 0 0.5em 0 0;
         display: inline-block;
         width: 1em;
         text-align: right;
         line-height: 0.5em;
        }
/** Terminology Markup ********************************************************/
/******************************************************************************/
/* Inline Markup */
/******************************************************************************/
/** Terminology Markup ********************************************************/
        dfn { /* Defining instance */
                font-weight: bolder;
        }
        a > i { /* Instance of term */
                font-style: normal;
        }
        dt dfn code, code.idl {
                font-size: medium;
        }
        dfn var {
                font-style: normal;
        }
/** Change Marking ************************************************************/
        del { color: red; text-decoration: line-through; }
        ins { color: #080; text-decoration: underline; }
/** Miscellaneous improvements to inline formatting ***************************/
        sup {
                vertical-align: super;
                font-size: 80%
        }
/******************************************************************************/
/* Code */
/******************************************************************************/
/** General monospace/pre rules ***********************************************/
        pre, code, samp {
                font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
                font-size: .9em;
                page-break-inside: avoid;
                hyphens: none;
                text-transform: none;
        }
        pre code,
        code code {
                font-size: 100%;
        }
        pre {
                margin-top: 1em;
                margin-bottom: 1em;
                overflow: auto;
        }
/** Inline Code fragments *****************************************************/
/* Do something nice. */
/******************************************************************************/
/* Links */
/******************************************************************************/
/** General Hyperlinks ********************************************************/
        /* We hyperlink a lot, so make it less intrusive */
        a[href] {
                color: #034575;
                text-decoration: none;
                border-bottom: 1px solid #707070;
                /* Need a bit of extending for it to look okay */
                padding: 0 1px 0;
                margin: 0 -1px 0;
        }
        a:visited {
                border-bottom-color: #BBB;
        }
        /* Use distinguishing colors when user is interacting with the link */
        a[href]:focus,
        a[href]:hover {
                background: #f8f8f8;
                background: rgba(75%, 75%, 75%, .25);
                border-bottom-width: 3px;
                margin-bottom: -2px;
        }
        a[href]:active {
                color: #C00;
                border-color: #C00;
        }
        /* Backout above styling for W3C logo */
        .head .logo,
        .head .logo a {
                border: none;
                text-decoration: none;
                background: transparent;
        }
/******************************************************************************/
/* Images */
/******************************************************************************/
        img {
                border-style: none;
        }
        /* For autogen numbers, add
         .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
        */
        figure, .figure, .sidefigure {
                page-break-inside: avoid;
                text-align: center;
                margin: 2.5em 0;
        }
        .figure img, .sidefigure img, figure img,
        .figure object, .sidefigure object, figure object {
                max-width: 100%;
                margin: auto;
        }
        .figure pre, .sidefigure pre, figure pre {
                text-align: left;
                display: table;
                margin: 1em auto;
        }
        .figure table, figure table {
                margin: auto;
        }
        @media screen and (min-width: 20em) {
                .sidefigure {
                        float: right;
                        width: 50%;
                        margin: 0 0 0.5em 0.5em
                }
        }
        .caption, figcaption, caption {
                font-style: italic;
                font-size: 90%;
        }
        .caption::before, figcaption::before, figcaption > .marker {
                font-weight: bold;
        }
        .caption, figcaption {
                counter-increment: figure;
        }
        /* DL list is indented 2em, but figure inside it is not */
        dd > .figure, dd > figure { margin-left: -2em }
/******************************************************************************/
/* Colored Boxes */
/******************************************************************************/
        .issue, .note, .example, .assertion, .advisement, blockquote {
                padding: .5em;
                border: .5em;
                border-left-style: solid;
                page-break-inside: avoid;
        }
        span.issue, span.note {
                padding: .1em .5em .15em;
                border-right-style: solid;
        }
        .issue,
        .note,
        .example,
        .advisement,
        .assertion,
        blockquote {
                margin: 1em auto;
        }
        .note > p:first-child,
        .issue > p:first-child,
        blockquote > :first-child {
                margin-top: 0;
        }
        blockquote > :last-child {
                margin-bottom: 0;
        }
/** Blockquotes ***************************************************************/
        blockquote {
                border-color: silver;
        }
/** Open issue ****************************************************************/
        .issue {
                border-color: #E05252;
                background: #FBE9E9;
                counter-increment: issue;
                overflow: auto;
        }
        .issue::before, .issue > .marker {
                text-transform: uppercase;
                color: #AE1E1E;
                padding-right: 1em;
                text-transform: uppercase;
        }
        /* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
         or use class="marker" to mark up the issue number in source. */
/** Example *******************************************************************/
        .example {
                border-color: #E0CB52;
                background: #FCFAEE;
                counter-increment: example;
                overflow: auto;
                clear: both;
        }
        .example::before, .example > .marker {
                text-transform: uppercase;
                color: #827017;
                min-width: 7.5em;
                display: block;
        }
        /* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
         or use class="marker" to mark up the example number in source. */
/** Non-normative Note ********************************************************/
        .note {
                border-color: #52E052;
                background: #E9FBE9;
                overflow: auto;
        }
        .note::before, .note > .marker,
        details.note > summary::before,
        details.note > summary > .marker {
                text-transform: uppercase;
                display: block;
                color: hsl(120, 70%, 30%);
        }
        /* Add .note::before { content: "Note"; } for autogen label,
         or use class="marker" to mark up the label in source. */
        details.note > summary {
                display: block;
                color: hsl(120, 70%, 30%);
        }
        details.note[open] > summary {
                border-bottom: 1px silver solid;
        }
/** Assertion Box *************************************************************/
        /* for assertions in algorithms */
        .assertion {
                border-color: #AAA;
                background: #EEE;
        }
/** Advisement Box ************************************************************/
        /* for attention-grabbing normative statements */
        .advisement {
                border-color: orange;
                border-style: none solid;
                background: #FFEECC;
        }
        strong.advisement {
                display: block;
                text-align: center;
        }
        .advisement > .marker {
                color: #B35F00;
        }
/** Spec Obsoletion Notice ****************************************************/
        /* obnoxious obsoletion notice for older/abandoned specs. */
        details {
                display: block;
        }
        summary {
                font-weight: bolder;
        }
        .annoying-warning:not(details),
        details.annoying-warning:not([open]) > summary,
        details.annoying-warning[open] {
                background: #fdd;
                color: red;
                font-weight: bold;
                padding: .75em 1em;
                border: thick red;
                border-style: solid;
                border-radius: 1em;
        }
        .annoying-warning :last-child {
                margin-bottom: 0;
        }
@media not print {
        details.annoying-warning[open] {
                position: fixed;
                left: 1em;
                right: 1em;
                bottom: 1em;
                z-index: 1000;
        }
}
        details.annoying-warning:not([open]) > summary {
                text-align: center;
        }
/** Entity Definition Boxes ***************************************************/
        .def {
                padding: .5em 1em;
                background: #DEF;
                margin: 1.2em 0;
                border-left: 0.5em solid #8CCBF2;
        }
/******************************************************************************/
/* Tables */
/******************************************************************************/
        th, td {
                text-align: left;
                text-align: start;
        }
/** Property/Descriptor Definition Tables *************************************/
        table.def {
                /* inherits .def box styling, see above */
                width: 100%;
                border-spacing: 0;
        }
        table.def td,
        table.def th {
                padding: 0.5em;
                vertical-align: baseline;
                border-bottom: 1px solid #bbd7e9;
        }
        table.def > tbody > tr:last-child th,
        table.def > tbody > tr:last-child td {
                border-bottom: 0;
        }
        table.def th {
                font-style: italic;
                font-weight: normal;
                padding-left: 1em;
                width: 3em;
        }
        /* For when values are extra-complex and need formatting for readability */
        table td.pre {
                white-space: pre-wrap;
        }
        /* A footnote at the bottom of a def table */
        table.def td.footnote {
                padding-top: 0.6em;
        }
        table.def td.footnote::before {
                content: " ";
                display: block;
                height: 0.6em;
                width: 4em;
                border-top: thin solid;
        }
/** Data tables (and properly marked-up index tables) *************************/
        /*
                 <table class="data"> highlights structural relationships in a table
                 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)
                 Use class="complex data" for particularly complicated tables --
                 (This will draw more lines: busier, but clearer.)
                 Use class="long" on table cells with paragraph-like contents
                 (This will adjust text alignment accordingly.)
                 Alternately use class="longlastcol" on tables, to have the last column assume "long".
        */
        table {
                word-wrap: normal;
                overflow-wrap: normal;
                hyphens: manual;
        }
        table.data,
        table.index {
                margin: 1em auto;
                border-collapse: collapse;
                border: hidden;
                width: 100%;
        }
        table.data caption,
        table.index caption {
                max-width: 50em;
                margin: 0 auto 1em;
        }
        table.data td, table.data th,
        table.index td, table.index th {
                padding: 0.5em 1em;
                border-width: 1px;
                border-color: silver;
                border-top-style: solid;
        }
        table.data thead td:empty {
                padding: 0;
                border: 0;
        }
        table.data thead,
        table.index thead,
        table.data tbody,
        table.index tbody {
                border-bottom: 2px solid;
        }
        table.data colgroup,
        table.index colgroup {
                border-left: 2px solid;
        }
        table.data tbody th:first-child,
        table.index tbody th:first-child {
                border-right: 2px solid;
                border-top: 1px solid silver;
                padding-right: 1em;
        }
        table.data th[colspan],
        table.data td[colspan] {
                text-align: center;
        }
        table.complex.data th,
        table.complex.data td {
                border: 1px solid silver;
                text-align: center;
        }
        table.data.longlastcol td:last-child,
        table.data td.long {
         vertical-align: baseline;
         text-align: left;
        }
        table.data img {
                vertical-align: middle;
        }
/*
Alternate table alignment rules
        table.data,
        table.index {
                text-align: center;
        }
        table.data thead th[scope="row"],
        table.index thead th[scope="row"] {
                text-align: right;
        }
        table.data tbody th:first-child,
        table.index tbody th:first-child {
                text-align: right;
        }
Possible extra rowspan handling
        table.data tbody th[rowspan]:not([rowspan='1']),
        table.index tbody th[rowspan]:not([rowspan='1']),
        table.data tbody td[rowspan]:not([rowspan='1']),
        table.index tbody td[rowspan]:not([rowspan='1']) {
                border-left: 1px solid silver;
        }
        table.data tbody th[rowspan]:first-child,
        table.index tbody th[rowspan]:first-child,
        table.data tbody td[rowspan]:first-child,
        table.index tbody td[rowspan]:first-child{
                border-left: 0;
                border-right: 1px solid silver;
        }
*/
/******************************************************************************/
/* Indices */
/******************************************************************************/
/** Table of Contents *********************************************************/
        .toc a {
                /* More spacing; use padding to make it part of the click target. */
                padding-top: 0.1rem;
                /* Larger, more consistently-sized click target */
                display: block;
                /* Reverse color scheme */
                color: black;
                border-color: #3980B5;
                border-bottom-width: 3px !important;
                margin-bottom: 0px !important;
        }
        .toc a:visited {
                border-color: #054572;
        }
        .toc a:not(:focus):not(:hover) {
                /* Allow colors to cascade through from link styling */
                border-bottom-color: transparent;
        }
        .toc, .toc ol, .toc ul, .toc li {
                list-style: none; /* Numbers must be inlined into source */
                /* because generated content isn't search/selectable and markers can't do multilevel yet */
                margin: 0;
                padding: 0;
                line-height: 1.1rem; /* consistent spacing */
        }
        /* ToC not indented until third level, but font style & margins show hierarchy */
        .toc > li { font-weight: bold; }
        .toc > li li { font-weight: normal; }
        .toc > li li li { font-size: 95%; }
        .toc > li li li li { font-size: 90%; }
        .toc > li li li li li { font-size: 85%; }
        .toc > li { margin: 1.5rem 0; }
        .toc > li li { margin: 0.3rem 0; }
        .toc > li li li { margin-left: 2rem; }
        /* Section numbers in a column of their own */
        .toc .secno {
                float: left;
                width: 4rem;
                white-space: nowrap;
        }
        .toc > li li li li .secno {
                font-size: 85%;
        }
        .toc > li li li li li .secno {
                font-size: 100%;
        }
        :not(li) > .toc { margin-left: 5rem; }
        .toc .secno { margin-left: -5rem; }
        .toc > li li li .secno { margin-left: -7rem; }
        .toc > li li li li .secno { margin-left: -9rem; }
        .toc > li li li li li .secno { margin-left: -11rem; }
        /* Tighten up indentation in narrow ToCs */
        @media (max-width: 30em) {
                :not(li) > .toc { margin-left: 4rem; }
                .toc .secno { margin-left: -4rem; }
                .toc > li li li { margin-left: 1rem; }
                .toc > li li li .secno { margin-left: -5rem; }
                .toc > li li li li .secno { margin-left: -6rem; }
                .toc > li li li li li .secno { margin-left: -7rem; }
        }
        @media screen and (min-width: 78em) {
                body:not(.toc-inline) :not(li) > .toc { margin-left: 4rem; }
                body:not(.toc-inline) .toc .secno { margin-left: -4rem; }
                body:not(.toc-inline) .toc > li li li { margin-left: 1rem; }
                body:not(.toc-inline) .toc > li li li .secno { margin-left: -5rem; }
                body:not(.toc-inline) .toc > li li li li .secno { margin-left: -6rem; }
                body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
        }
        body.toc-sidebar #toc :not(li) > .toc { margin-left: 4rem; }
        body.toc-sidebar #toc .toc .secno { margin-left: -4rem; }
        body.toc-sidebar #toc .toc > li li li { margin-left: 1rem; }
        body.toc-sidebar #toc .toc > li li li .secno { margin-left: -5rem; }
        body.toc-sidebar #toc .toc > li li li li .secno { margin-left: -6rem; }
        body.toc-sidebar #toc .toc > li li li li li .secno { margin-left: -7rem; }
        .toc li {
                clear: both;
        }
/** Index *********************************************************************/
        /* Index Lists: Layout */
        ul.index { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
        ul.index li { margin-left: 0; list-style: none; break-inside: avoid; }
        ul.index li li { margin-left: 1em }
        ul.index dl { margin-top: 0; }
        ul.index dt { margin: .2em 0 .2em 20px;}
        ul.index dd { margin: .2em 0 .2em 40px;}
        /* Index Lists: Typography */
        ul.index ul,
        ul.index dl { font-size: smaller; }
        @media not print {
                ul.index li span {
                        white-space: nowrap;
                        color: transparent; }
                ul.index li a:hover + span,
                ul.index li a:focus + span {
                        color: #707070;
                }
        }
/** Index Tables *****************************************************/
        /* See also the data table styling section, which this effectively subclasses */
        table.index {
                font-size: small;
                border-collapse: collapse;
                border-spacing: 0;
                text-align: left;
                margin: 1em 0;
        }
        table.index td,
        table.index th {
                padding: 0.4em;
        }
        table.index tr:hover td:not([rowspan]),
        table.index tr:hover th:not([rowspan]) {
                background: #f7f8f9;
        }
        /* The link in the first column in the property table (formerly a TD) */
        table.index th:first-child a {
                font-weight: bold;
        }
/******************************************************************************/
/* Print */
/******************************************************************************/
        @media print {
                /* Pages have their own margins. */
                html {
                        margin: 0;
                }
                /* Serif for print. */
                body {
                        font-family: serif;
                }
        }
        @page {
                margin: 1.5cm 1.1cm;
        }
/******************************************************************************/
/* Legacy */
/******************************************************************************/
        /* This rule is inherited from past style sheets. No idea what it's for. */
        .hide { display: none }
/******************************************************************************/
/* Overflow Control */
/******************************************************************************/
        .figure .caption, .sidefigure .caption, figcaption {
                /* in case figure is overlarge, limit caption to 50em */
                max-width: 50rem;
                margin-left: auto;
                margin-right: auto;
        }
        .overlarge > table {
                /* limit preferred width of table */
                max-width: 50em;
                margin-left: auto;
                margin-right: auto;
        }
        @media (min-width: 55em) {
                .overlarge {
                        margin-left: calc(13px + 26.5rem - 50vw);
                        margin-right: calc(13px + 26.5rem - 50vw);
                        max-width: none;
                }
        }
        @media screen and (min-width: 78em) {
                body:not(.toc-inline) .overlarge {
                        /* 30.5em body padding 50em content area */
                        margin-left: calc(40em - 50vw) !important;
                        margin-right: calc(40em - 50vw) !important;
                }
        }
        @media screen and (min-width: 90em) {
                body:not(.toc-inline) .overlarge {
                        /* 4em html margin 30.5em body padding 50em content area */
                        margin-left: 0 !important;
                        margin-right: calc(84.5em - 100vw) !important;
                }
        }
        @media not print {
                .overlarge {
                        overflow-x: auto;
                        /* See Lea Verou's explanation background-attachment:
                         * http://lea.verou.me/2012/04/background-attachment-local/
                         *
                        background: top left / 4em 100% linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0)) local,
                         top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
                         top left / 1em 100% linear-gradient(to right, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
                         top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
                         white;
                        background-repeat: no-repeat;
                        */
                }
        }
</style>
<style type="text/css">
table, th, td {
border: 1px solid black;
border-collapse: collapse;
vertical-align: top;
}
th, td {
border-left: none;
border-right: none;
padding: 0px 10px;
}
th {
text-align: center;
}
</style>
<meta content="Bikeshed version 166744eb86a34dbc5493268ea410dc65275aa964" name="generator">
<link href="http://wg21.link/p0593r2" rel="canonical">
<style>/* style-md-lists */
/* This is a weird hack for me not yet following the commonmark spec
regarding paragraph and lists. */
[data-md] > :first-child {
margin-top: 0;
}
[data-md] > :last-child {
margin-bottom: 0;
}</style>
<style>/* style-counters */
body {
counter-reset: example figure issue;
}
.issue {
counter-increment: issue;
}
.issue:not(.no-marker)::before {
content: "Issue " counter(issue);
}
.example {
counter-increment: example;
}
.example:not(.no-marker)::before {
content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
content: "Invalid Example" counter(example);
}
figcaption {
counter-increment: figure;
}
figcaption:not(.no-marker)::before {
content: "Figure " counter(figure) " ";
}</style>
<style>/* style-syntax-highlighting */
.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
.highlight .c { color: #708090 } /* Comment */
.highlight .k { color: #990055 } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #0077aa } /* Name */
.highlight .o { color: #999999 } /* Operator */
.highlight .p { color: #999999 } /* Punctuation */
.highlight .cm { color: #708090 } /* Comment.Multiline */
.highlight .cp { color: #708090 } /* Comment.Preproc */
.highlight .c1 { color: #708090 } /* Comment.Single */
.highlight .cs { color: #708090 } /* Comment.Special */
.highlight .kc { color: #990055 } /* Keyword.Constant */
.highlight .kd { color: #990055 } /* Keyword.Declaration */
.highlight .kn { color: #990055 } /* Keyword.Namespace */
.highlight .kp { color: #990055 } /* Keyword.Pseudo */
.highlight .kr { color: #990055 } /* Keyword.Reserved */
.highlight .kt { color: #990055 } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #000000 } /* Literal.Number */
.highlight .s { color: #a67f59 } /* Literal.String */
.highlight .na { color: #0077aa } /* Name.Attribute */
.highlight .nc { color: #0077aa } /* Name.Class */
.highlight .no { color: #0077aa } /* Name.Constant */
.highlight .nd { color: #0077aa } /* Name.Decorator */
.highlight .ni { color: #0077aa } /* Name.Entity */
.highlight .ne { color: #0077aa } /* Name.Exception */
.highlight .nf { color: #0077aa } /* Name.Function */
.highlight .nl { color: #0077aa } /* Name.Label */
.highlight .nn { color: #0077aa } /* Name.Namespace */
.highlight .py { color: #0077aa } /* Name.Property */
.highlight .nt { color: #669900 } /* Name.Tag */
.highlight .nv { color: #222222 } /* Name.Variable */
.highlight .ow { color: #999999 } /* Operator.Word */
.highlight .mb { color: #000000 } /* Literal.Number.Bin */
.highlight .mf { color: #000000 } /* Literal.Number.Float */
.highlight .mh { color: #000000 } /* Literal.Number.Hex */
.highlight .mi { color: #000000 } /* Literal.Number.Integer */
.highlight .mo { color: #000000 } /* Literal.Number.Oct */
.highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
.highlight .sc { color: #a67f59 } /* Literal.String.Char */
.highlight .sd { color: #a67f59 } /* Literal.String.Doc */
.highlight .s2 { color: #a67f59 } /* Literal.String.Double */
.highlight .se { color: #a67f59 } /* Literal.String.Escape */
.highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
.highlight .si { color: #a67f59 } /* Literal.String.Interpol */
.highlight .sx { color: #a67f59 } /* Literal.String.Other */
.highlight .sr { color: #a67f59 } /* Literal.String.Regex */
.highlight .s1 { color: #a67f59 } /* Literal.String.Single */
.highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
.highlight .vc { color: #0077aa } /* Name.Variable.Class */
.highlight .vg { color: #0077aa } /* Name.Variable.Global */
.highlight .vi { color: #0077aa } /* Name.Variable.Instance */
.highlight .il { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-selflinks */
.heading, .issue, .note, .example, li, dt {
position: relative;
}
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;
}
a.self-link:hover {
opacity: 1;
}
.heading > a.self-link {
font-size: 83%;
}
li > a.self-link {
left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
top: auto;
left: auto;
opacity: 0;
width: 1.5em;
height: 1.5em;
background: gray;
color: white;
font-style: normal;
transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
opacity: 1;
}
dfn > a.self-link:hover {
color: black;
}
a.self-link::before { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before { content: "#"; }</style>
<style>/* style-autolinks */
.css.css, .property.property, .descriptor.descriptor {
color: #005a9c;
font-size: inherit;
font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
content: "‘";
}
.css::after, .property::after, .descriptor::after {
content: "’";
}
.property, .descriptor {
/* Don't wrap property and descriptor names */
white-space: nowrap;
}
.type { /* CSS value <type> */
font-style: italic;
}
pre .property::before, pre .property::after {
content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
content: "’";
}
[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
content: "";
}
[data-link-type=element],
[data-link-type=element-attr] {
font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after { content: ">" }
[data-link-type=biblio] {
white-space: pre;
}</style>
<body class="h-entry">
<div class="head">
<p data-fill-with="logo"></p>
<h1 class="p-name no-ref" id="title">d0593r2<br>Implicit creation of objects for low-level object manipulation</h1>
<h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Draft Proposal, <time class="dt-updated" datetime="2017-11-16">16 November 2017</time></span></h2>
<div data-fill-with="spec-metadata">
<dl>
<dt>This version:
<dd><a class="u-url" href="http://wg21.link/p0593r2">http://wg21.link/p0593r2</a>
<dt>Author:
<dd>
<dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:richard@metafoo.co.uk">Richard Smith</a> (<span class="p-org org">Google</span>)
<dt>Former Author:
<dd>
<dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a>
<dt>Audience:
<dd>SG12
<dt>Project:
<dd>ISO JTC1/SC22/WG21: Programming Language C++
</dl>
</div>
<div data-fill-with="warning"></div>
<hr title="Separator for header">
</div>
<div class="p-summary" data-fill-with="abstract">
<h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
<p>This paper proposes that objects of sufficiently trivial types be created on-demand as necessary to give programs defined behavior.</p>
</div>
<nav data-fill-with="table-of-contents" id="toc">
<h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
<ol class="toc" role="directory">
<li><a href="#change-history"><span class="secno">1</span> <span class="content">Change history</span></a>
<li>
<a href="#motivating-examples"><span class="secno">2</span> <span class="content">Motivating examples</span></a>
<ol class="toc">
<li><a href="#idiomatic-c-code-as-c"><span class="secno">2.1</span> <span class="content">Idiomatic C code as C++</span></a>
<li><a href="#objects-provided-as-byte-representation"><span class="secno">2.2</span> <span class="content">Objects provided as byte representation</span></a>
<li><a href="#dynamic-construction-of-arrays"><span class="secno">2.3</span> <span class="content">Dynamic construction of arrays</span></a>
</ol>
<li>
<a href="#approach"><span class="secno">3</span> <span class="content">Approach</span></a>
<ol class="toc">
<li><a href="#affected-types"><span class="secno">3.1</span> <span class="content">Affected types</span></a>
<li><a href="#when-to-create-objects"><span class="secno">3.2</span> <span class="content">When to create objects</span></a>
<li><a href="#type-punning"><span class="secno">3.3</span> <span class="content">Type punning</span></a>
<li><a href="#constant-expressions"><span class="secno">3.4</span> <span class="content">Constant expressions</span></a>
<li><a href="#pseudo-destructor-calls"><span class="secno">3.5</span> <span class="content">Pseudo-destructor calls</span></a>
<li><a href="#practical-examples"><span class="secno">3.6</span> <span class="content">Practical examples</span></a>
</ol>
<li><a href="#acknowledgements"><span class="secno">4</span> <span class="content">Acknowledgements</span></a>
<li>
<a href="#references"><span class="secno"></span> <span class="content">References</span></a>
<ol class="toc">
<li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
</ol>
</ol>
</nav>
<main>
<h2 class="heading settled" data-level="1" id="change-history"><span class="secno">1. </span><span class="content">Change history</span><a class="self-link" href="#change-history"></a></h2>
<p>Since <a data-link-type="biblio" href="#biblio-p0593r0">[P0593R0]</a>:</p>
<ul>
<li data-md="">
<p>Paper expanded from Ville’s original call for solutions to a description of
a proposed solution, based on SG12 discussion.</p>
</ul>
<p>Since <a data-link-type="biblio" href="#biblio-p0593r1">[P0593R1]</a>:</p>
<p>Incorporated further SG12 feedback:</p>
<ul>
<li data-md="">
<p>An explicit syntactic marker is required to indicate that objects should be
created. Existing obvious markers, such as the use of <code class="highlight"><span class="n">malloc</span></code>, or simply
performing member access on a union, suffice.</p>
<li data-md="">
<p>Expand set of implicit lifetime types to require <em>either</em> a trivial default
constructor <em>or</em> a trivial copy/move constructor, rather than requiring both.</p>
<ul>
<li data-md="">
<p>Types with only a trivial default constructor may be suitable for
member-by-member construction via class member access, even if the copy
or move constructor is non-trivial.</p>
<li data-md="">
<p>Types with only a trivial copy/move constructor may be suitable for
initialization by copying (for example) an on-disk representation into
memory, even if the default constructor is non-trivial.</p>
</ul>
<li data-md="">
<p>Define the C standard library <code class="highlight"><span class="n">memcpy</span></code> and <code class="highlight"><span class="n">memmove</span></code> functions as triggering
implicit object creation.</p>
</ul>
<h2 class="heading settled" data-level="2" id="motivating-examples"><span class="secno">2. </span><span class="content">Motivating examples</span><a class="self-link" href="#motivating-examples"></a></h2>
<h3 class="heading settled" data-level="2.1" id="idiomatic-c-code-as-c"><span class="secno">2.1. </span><span class="content">Idiomatic C code as C++</span><a class="self-link" href="#idiomatic-c-code-as-c"></a></h3>
<p>Consider the following natural C program:</p>
<pre class="highlight"><span class="k">struct</span> <span class="n">X</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span> <span class="p">};</span>
<span class="n">X</span> <span class="o">*</span><span class="nf">make_x</span><span class="p">()</span> <span class="p">{</span>
<span class="n">X</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="n">X</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">X</span><span class="p">));</span>
<span class="n">p</span><span class="o">-></span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">p</span><span class="o">-></span><span class="n">b</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
</pre>
<p>When compiled with a C++ compiler, this code has undefined behavior, because <code class="highlight"><span class="n">p</span><span class="o">-></span><span class="n">a</span></code> attempts to write to an <code class="highlight"><span class="kt">int</span></code> subobject of an <code class="highlight"><span class="n">X</span></code> object, and this
program never created either an <code class="highlight"><span class="n">X</span></code> object nor an <code class="highlight"><span class="kt">int</span></code> subobject.</p>
<p>Per [intro.object]p1,</p>
<blockquote> An <em>object</em> is created by a definition, by a <em>new-expression</em>, when
implicitly changing the active member of a union, or when a temporary
object is created. </blockquote>
<p>... and this program did none of these things.</p>
<h3 class="heading settled" data-level="2.2" id="objects-provided-as-byte-representation"><span class="secno">2.2. </span><span class="content">Objects provided as byte representation</span><a class="self-link" href="#objects-provided-as-byte-representation"></a></h3>
<p>Suppose a C++ program is given a sequence of bytes (perhaps from disk or from a
network), and it knows those bytes are a valid representation of type <code class="highlight"><span class="n">T</span></code>. How
can it efficiently obtain a <code class="highlight"><span class="n">T</span> <span class="o">*</span></code> that can be legitimately used to access the
object?</p>
<p>Example: (many details omitted for brevity)</p>
<pre class="highlight"><span class="kt">void</span> <span class="nf">process</span><span class="p">(</span><span class="n">Stream</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="p">{</span>
<span class="n">unique_ptr</span><span class="o"><</span><span class="kt">char</span><span class="p">[]</span><span class="o">></span> <span class="n">buffer</span> <span class="o">=</span> <span class="n">stream</span><span class="o">-></span><span class="n">read</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">buffer</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">FOO</span><span class="p">)</span>
<span class="n">process_foo</span><span class="p">(</span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="n">Foo</span><span class="o">*></span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">get</span><span class="p">()));</span> <span class="c1">// #1</span>
<span class="c1"></span> <span class="k">else</span>
<span class="n">process_bar</span><span class="p">(</span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="n">Bar</span><span class="o">*></span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">get</span><span class="p">()));</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<p>This code leads to undefined behavior today: within <code class="highlight"><span class="n">Stream</span><span class="o">::</span><span class="n">read</span></code>, no <code class="highlight"><span class="n">Foo</span></code> or <code class="highlight"><span class="n">Bar</span></code> object is created, and so any attempt to access a <code class="highlight"><span class="n">Foo</span></code> object through the <code class="highlight"><span class="n">Foo</span><span class="o">*</span></code> produced by the cast at #1 would result in undefined behavior.</p>
<h3 class="heading settled" data-level="2.3" id="dynamic-construction-of-arrays"><span class="secno">2.3. </span><span class="content">Dynamic construction of arrays</span><a class="self-link" href="#dynamic-construction-of-arrays"></a></h3>
<p>Consider this program that attempts to implement a type like <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span></code> (with many details omitted for brevity):</p>
<pre class="highlight"><span class="k">template</span><span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="k">struct</span> <span class="n">Vec</span> <span class="p">{</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">buf</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">,</span> <span class="o">*</span><span class="n">buf_end_size</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">,</span> <span class="o">*</span><span class="n">buf_end_capacity</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">reserve</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">newbuf</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="o">::</span><span class="k">operator</span> <span class="k">new</span><span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">T</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">align_val_t</span><span class="p">(</span><span class="k">alignof</span><span class="p">(</span><span class="n">T</span><span class="p">)));</span>
<span class="n">std</span><span class="o">::</span><span class="n">uninitialized_copy</span><span class="p">(</span><span class="n">begin</span><span class="p">(),</span> <span class="n">end</span><span class="p">(),</span> <span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">)</span><span class="n">newbuf</span><span class="p">);</span> <span class="c1">// #a</span>
<span class="c1"></span>
<span class="o">::</span><span class="k">operator</span> <span class="k">delete</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">align_val_t</span><span class="p">(</span><span class="k">alignof</span><span class="p">(</span><span class="n">T</span><span class="p">)));</span>
<span class="n">buf_end_size</span> <span class="o">=</span> <span class="n">newbuf</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">T</span><span class="p">)</span> <span class="o">*</span> <span class="n">size</span><span class="p">();</span> <span class="c1">// #b</span>
<span class="c1"></span> <span class="n">buf_end_capacity</span> <span class="o">=</span> <span class="n">newbuf</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">T</span><span class="p">)</span> <span class="o">*</span> <span class="n">n</span><span class="p">;</span> <span class="c1">// #c</span>
<span class="c1"></span> <span class="n">buf</span> <span class="o">=</span> <span class="n">newbuf</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">push_back</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">buf_end_size</span> <span class="o">==</span> <span class="n">buf_end_capacity</span><span class="p">)</span>
<span class="n">reserve</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">max</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">></span><span class="p">(</span><span class="n">size</span><span class="p">()</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">));</span>
<span class="k">new</span> <span class="p">(</span><span class="n">buf_end_size</span><span class="p">)</span> <span class="n">T</span><span class="p">(</span><span class="n">t</span><span class="p">);</span>
<span class="n">buf_end_size</span> <span class="o">+=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">T</span><span class="p">);</span> <span class="c1">// #d</span>
<span class="c1"></span> <span class="p">}</span>
<span class="n">T</span> <span class="o">*</span><span class="nf">begin</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="p">;</span> <span class="p">}</span>
<span class="n">T</span> <span class="o">*</span><span class="nf">end</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">)</span><span class="n">buf_end_size</span><span class="p">;</span> <span class="p">}</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">size</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="n">begin</span><span class="p">();</span> <span class="p">}</span> <span class="c1">// #e</span>
<span class="c1"></span><span class="p">};</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">Vec</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">v</span><span class="p">;</span>
<span class="n">v</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="n">v</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="n">v</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">n</span> <span class="p">:</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/*...*/</span> <span class="p">}</span> <span class="c1">// #f</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<p>In practice, this code works across a range of existing implementations, but
according to the C++ object model, undefined behavior occurs at points #a, #b,
#c, #d, and #e, because they attempt to perform pointer arithmetic on a region
of allocated storage that does not contain an array object.</p>
<p>At locations #b, #c, and #d, the arithmetic is performed on a <code class="highlight"><span class="kt">char</span><span class="o">*</span></code>, and at
locations #a, #e, and #f, the arithmetic is performed on a <code class="highlight"><span class="n">T</span><span class="o">*</span></code>. Ideally, a
solution to this problem would imbue both calculations with defined behavior.</p>
<h2 class="heading settled" data-level="3" id="approach"><span class="secno">3. </span><span class="content">Approach</span><a class="self-link" href="#approach"></a></h2>
<p>The above snippets have a common theme: they attempt to use objects that they
never created. Indeed, there is a family of types for which programmers assume
they do not need to explicitly create objects. We propose to identify these
types, and carefully carve out rules that remove the need to explicitly create
such objects, by instead creating them implicitly.</p>
<h3 class="heading settled" data-level="3.1" id="affected-types"><span class="secno">3.1. </span><span class="content">Affected types</span><a class="self-link" href="#affected-types"></a></h3>
<p>If we are going to create objects automatically, we need a bare minimum of the
following two properties for the type:</p>
<p>1) <em>Creating an instance of the type runs no code.</em> For class types, having a
trivially default constructible type is often the right constraint. However, we
should also consider cases where initially creating an object is non-trivial,
but copying it (for instance, from an on-disk representation) is trivial.</p>
<p>2) <em>Destroying an instance of the type runs no code.</em> If the type maintains
invariants, we should not be implicitly creating objects of that type.</p>
<p>Note that we’re only interested in properties of the object itself here, not
of its subobjects. In particular, the above two properties always hold for
array types. While creating or destroying array elements might run code,
creating the array object (without its elements) does not.</p>
<p>This suggests that the largest set of types we could apply this to is:</p>
<ul>
<li data-md="">
<p>Scalar types</p>
<li data-md="">
<p>Array types (with any element type)</p>
<li data-md="">
<p>Class types with a trivial destructor and a trivial constructor (of any kind)</p>
</ul>
<p>(Put another way, we can apply this to all types other than function type,
reference type, <code class="highlight"><span class="kt">void</span></code>, and class types where all constructors are non-trivial
or where the destructor is non-trivial.)</p>
<p>We will call types that satisfy the above constraints <em>implicit lifetime types</em>.</p>
<h3 class="heading settled" data-level="3.2" id="when-to-create-objects"><span class="secno">3.2. </span><span class="content">When to create objects</span><a class="self-link" href="#when-to-create-objects"></a></h3>
<p>In the above cases, it would be sufficient for <code class="highlight"><span class="n">malloc</span></code> / <code class="highlight"><span class="o">::</span><span class="k">operator</span> <span class="k">new</span></code> to implicitly create sufficient objects to make the examples work. Imagine
that <code class="highlight"><span class="n">malloc</span></code> could "look into the future" and see how its storage would be
used, and create the set of objects that the program would eventually need.
If we somehow specified that <code class="highlight"><span class="n">malloc</span></code> did this, the behavior of many C-style
use cases would be defined.</p>
<p>On typical implementations, we can argue that this is not only natural, it is
in some sense the status quo. Because the compiler typically does not make
assumptions about what objects are created within the implementation of <code class="highlight"><span class="n">malloc</span></code>, and because object creation itself typically has no effect on the
physical machine, the compiler must generate code that would be correct if <code class="highlight"><span class="n">malloc</span></code> did create that correct set of objects.</p>
<p>However, this is not always sufficient. An allocation from <code class="highlight"><span class="n">malloc</span></code> may be
sequentially used to store multiple different types, for instance by way
of a memory pool that recycles the same allocation for multiple objects of
the same size. It should be possible to grant such cases the same power to
implicitly create objects as is de facto granted to <code class="highlight"><span class="n">malloc</span></code>.</p>
<p>Therefore we propose the following rule:</p>
<blockquote>
<p>Some operations are described as implicitly creating objects within a
specified region of storage. The abstract machine creates objects of implicit
lifetime types within those regions of storage as needed to give the program
defined behavior. For each operation that is specified as implicitly creating
objects, that operation implicitly creates zero or more objects in its
specified region of storage if doing so would give the program defined
behavior. If no such sets of objects would give the program defined behavior,
the behavior of the program is undefined.</p>
</blockquote>
<p>The coherence of the above rule hinges on a key observation: changing the
set of objects that are implicitly created can only change whether a particular
program execution has defined behavior, not what the behavior is.</p>
<p>We propose that at minimum the following operations be specified as implicitly
creating objects:</p>
<ul>
<li data-md="">
<p>Creation of an array of <code class="highlight"><span class="kt">char</span></code>, <code class="highlight"><span class="kt">unsigned</span> <span class="kt">char</span></code>, or <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">byte</span></code> implicitly
creates objects within that array.</p>
<li data-md="">
<p>A call to <code class="highlight"><span class="n">malloc</span></code>, <code class="highlight"><span class="n">calloc</span></code>, <code class="highlight"><span class="n">realloc</span></code>, or any function named <code class="highlight"><span class="k">operator</span> <span class="k">new</span></code> or <code class="highlight"><span class="k">operator</span> <span class="k">new</span><span class="p">[]</span></code> implicitly creates objects in its returned storage.</p>
<li data-md="">
<p><code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o"><</span><span class="n">T</span><span class="o">>::</span><span class="n">allocate</span></code> likewise implicitly creates objects in its
returned storage; the allocator requirements should require other allocator
implementations to do the same.</p>
<li data-md="">
<p>A call to <code class="highlight"><span class="n">memmove</span></code> behaves as if it</p>
<ol>
<li data-md="">
<p>copies the source storage to a temporary area</p>
<li data-md="">
<p>implicitly creates objects in the destination storage, and then</p>
<li data-md="">
<p>copies the temporary storage to the destination storage.</p>
</ol>
<p>This permits <code class="highlight"><span class="n">memmove</span></code> to preserve the types of trivially-copyable objects,
or to be used to reinterpret a byte representation of one object as that of
another object.</p>
<li data-md="">
<p>A call to <code class="highlight"><span class="n">memcpy</span></code> behaves the same as a call to <code class="highlight"><span class="n">memmove</span></code> except that it
introduces an overlap restriction between the source and destination.</p>
<li data-md="">
<p>A class member access that nominates a union member triggers implicit object
creation within the storage occupied by the union member. Note that this is
not an entirely new rule: this permission already existed in <a data-link-type="biblio" href="#biblio-p0137r1">[P0137R1]</a> for
cases where the member access is on the left side of an assignment, but is
now generalized as part of this new framework. As explained below, this does
not permit type punning through unions; rather, it merely permits the active
union member to be changed by a class member access expression.</p>
<li data-md="">
<p>A new barrier operation (distinct from <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">launder</span></code>, which does not create
objects) should be introduced to the standard library, with semantics
equivalent to a <code class="highlight"><span class="n">memmove</span></code> with the same source and destination storage.
As a strawman, we suggest:</p>
<pre class="highlight"> <span class="c1">// Requires: [start, (char*)start + length) denotes a region of allocated</span>
<span class="c1"></span> <span class="c1">// storage that is a subset of the region of storage reachable through start.</span>
<span class="c1"></span> <span class="c1">// Effects: implicitly creates objects within the denoted region.</span>
<span class="c1"></span> <span class="kt">void</span> <span class="n">std</span><span class="o">::</span><span class="n">bless</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">start</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">length</span><span class="p">);</span>
</pre>
</ul>
<p>Note that a pointer <code class="highlight"><span class="k">reinterpret_cast</span></code> is not considered sufficient to trigger
implicit object creation.</p>
<h3 class="heading settled" data-level="3.3" id="type-punning"><span class="secno">3.3. </span><span class="content">Type punning</span><a class="self-link" href="#type-punning"></a></h3>
<p>We do not wish examples such as the following to become valid:</p>
<pre class="highlight"><span class="kt">float</span> <span class="nf">do_bad_things</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
<span class="k">alignof</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="k">alignof</span><span class="p">(</span><span class="kt">float</span><span class="p">)</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">max</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">))];</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span><span class="p">)</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span> <span class="c1">// #1</span>
<span class="c1"></span> <span class="n">std</span><span class="o">::</span><span class="n">bless</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span><span class="n">buffer</span><span class="p">;</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<pre class="highlight"><span class="kt">float</span> <span class="nf">do_bad_things</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
<span class="k">union</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span> <span class="kt">float</span> <span class="n">f</span><span class="p">;</span> <span class="p">}</span> <span class="n">u</span><span class="p">;</span>
<span class="n">u</span><span class="p">.</span><span class="n">n</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span> <span class="c1">// #1</span>
<span class="c1"></span> <span class="k">return</span> <span class="n">u</span><span class="p">.</span><span class="n">f</span><span class="p">;</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<p>The proposed rule would permit an <code class="highlight"><span class="kt">int</span></code> object to spring into existence
to make line #1 valid (in each case), and would permit a <code class="highlight"><span class="kt">float</span></code> object to
likewise spring into existence to make line #2 valid.</p>
<p>However, these examples still do not have defined behavior under the
proposed rule. The reason is a consequence of [basic.life]p4:</p>
<blockquote> The properties ascribed to objects and references throughout this document
apply for a given object or reference only during its lifetime. </blockquote>
<p>Specifically, the value held by an object is only stable throughout its
lifetime. When the lifetime of the <code class="highlight"><span class="kt">int</span></code> object in line #1 ends (when
its storage is reused by the <code class="highlight"><span class="kt">float</span></code> object in line #2), its value is
gone. Symmetrically, when the <code class="highlight"><span class="kt">float</span></code> object is created, the object has
an indeterminate value ([dcl.init]p12), and therefore any attempt to
load its value results in undefined behavior.</p>
<p>Thus we retain the property (essential to modern scalar type-based
alias analysis) that loads of some scalar type can be considered to
not alias earlier stores of unrelated scalar types.</p>
<h3 class="heading settled" data-level="3.4" id="constant-expressions"><span class="secno">3.4. </span><span class="content">Constant expressions</span><a class="self-link" href="#constant-expressions"></a></h3>
<p>Constant expression evaluation is currently very conservative with regard to
object creation. There is a tension here: on the one hand, constant expression
evaluation gives us an opportunity to disallow runtime program semantics that
we consider undesirable or problematic, and on the other hand, users strongly
desire a full compile-time evaluation mechanism with the same semantics as the
base language.</p>
<p>Following the existing conservatism in constant expression evaluation (eg, the
disallowance of changing the active member of a union), we propose that the
implicit creation of objects should <em>not</em> be performed during such evaluation.</p>
<h3 class="heading settled" data-level="3.5" id="pseudo-destructor-calls"><span class="secno">3.5. </span><span class="content">Pseudo-destructor calls</span><a class="self-link" href="#pseudo-destructor-calls"></a></h3>
<p>In the current C++ language rules, "pseudo-destructor" calls may be used in
generic code to allow such code to be ambivalent as to whether an object is of
class type:</p>
<pre class="highlight"><span class="k">template</span><span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="kt">void</span> <span class="n">destroy</span><span class="p">(</span><span class="n">T</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="n">p</span><span class="o">->~</span><span class="n">T</span><span class="p">();</span> <span class="p">}</span>
</pre>
<p>When <code class="highlight"><span class="n">T</span></code> is, say, <code class="highlight"><span class="kt">int</span></code>, the pseudo-destructor expression <code class="highlight"><span class="n">p</span><span class="o">->~</span><span class="n">T</span><span class="p">()</span></code> is specified
as having no effect. We believe this is an error: such an expression should have
a lifetime effect, ending the lifetime of the <code class="highlight"><span class="kt">int</span></code> object. Likewise, calling a
destructor of a class object should always end the lifetime of that object,
regardless of whether the destructor is trivial.</p>
<p>This change improves the abililty of static and dynamic analysis tools to reason
about the lifetimes of C++ objects.</p>
<h3 class="heading settled" data-level="3.6" id="practical-examples"><span class="secno">3.6. </span><span class="content">Practical examples</span><a class="self-link" href="#practical-examples"></a></h3>
<pre class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">vi</span><span class="p">;</span>
<span class="n">vi</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span>
<span class="n">vi</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&</span><span class="n">vi</span><span class="p">.</span><span class="n">back</span><span class="p">();</span>
<span class="n">vi</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="n">vi</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
</pre>
<p>Within the implementation of <code class="highlight"><span class="n">vector</span></code>, some storage is allocated to hold
an array of up to 5 <code class="highlight"><span class="kt">int</span></code>s. Ignoring minor differences, there are two ways
to create implicit objects to give the execution of this program defined
behavior: within the allocated storage, either an <code class="highlight"><span class="kt">int</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span></code> object or an <code class="highlight"><span class="kt">int</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span></code> object is created. Both are correct interpretations of the program,
and naturally both result in the same behavior. We can choose to view the
program as being in the superposition of those two states. If we add a fourth <code class="highlight"><span class="n">push_back</span></code> call to the program prior to the initialization of <code class="highlight"><span class="n">n</span></code>, then only
the <code class="highlight"><span class="kt">int</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span></code> interpretation remains valid.</p>
<pre class="highlight"><span class="n">unique_ptr</span><span class="o"><</span><span class="kt">char</span><span class="p">[]</span><span class="o">></span> <span class="n">Stream</span><span class="o">::</span><span class="n">read</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// ... determine data size ...</span>
<span class="c1"></span> <span class="n">unique_ptr</span><span class="o"><</span><span class="kt">char</span><span class="p">[]</span><span class="o">></span> <span class="n">buffer</span><span class="p">(</span><span class="k">new</span> <span class="kt">char</span><span class="p">[</span><span class="n">N</span><span class="p">]);</span>
<span class="c1">// ... copy data into buffer ...</span>
<span class="c1"></span> <span class="k">return</span> <span class="n">buffer</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">process</span><span class="p">(</span><span class="n">Stream</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="p">{</span>
<span class="n">unique_ptr</span><span class="o"><</span><span class="kt">char</span><span class="p">[]</span><span class="o">></span> <span class="n">buffer</span> <span class="o">=</span> <span class="n">stream</span><span class="o">-></span><span class="n">read</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">buffer</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">FOO</span><span class="p">)</span>
<span class="n">process_foo</span><span class="p">(</span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="n">Foo</span><span class="o">*></span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">get</span><span class="p">()));</span> <span class="c1">// #1</span>
<span class="c1"></span> <span class="k">else</span>
<span class="nf">process_bar</span><span class="p">(</span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="n">Bar</span><span class="o">*></span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">get</span><span class="p">()));</span> <span class="c1">// #2</span>
<span class="c1"></span><span class="p">}</span>
</pre>
<p>Note the <code class="highlight"><span class="k">new</span> <span class="kt">char</span><span class="p">[</span><span class="n">N</span><span class="p">]</span></code> implicitly creates objects within the allocated array.
In this case, the program would have defined behavior if an object of type <code class="highlight"><span class="n">Foo</span></code> or <code class="highlight"><span class="n">Bar</span></code> (as appropriate for the content of the incoming data) were
implicitly created <em>prior</em> to <code class="highlight"><span class="n">Stream</span><span class="o">::</span><span class="n">read</span></code> populating its buffer. Therefore,
regardless of which arm of the <code class="highlight"><span class="k">if</span></code> is taken, there is a set of implicit
objects sufficient to give the program defined behavior, and thus the behavior
of the program is defined.</p>
<h2 class="heading settled" data-level="4" id="acknowledgements"><span class="secno">4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
<p>Thanks to Ville Voutilainen for raising this problem, and to the members of
SG12 for discussing possible solutions.</p>
</main>
<script>
(function() {
"use strict";
var collapseSidebarText = '<span aria-hidden="true">←</span> '
+ '<span>Collapse Sidebar</span>';
var expandSidebarText = '<span aria-hidden="true">→</span> '
+ '<span>Pop Out Sidebar</span>';
var tocJumpText = '<span aria-hidden="true">↑</span> '
+ '<span>Jump to Table of Contents</span>';
var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
var autoToggle = function(e){ toggleSidebar(e.matches) };
if(sidebarMedia.addListener) {
sidebarMedia.addListener(autoToggle);
}
function toggleSidebar(on) {
if (on == undefined) {
on = !document.body.classList.contains('toc-sidebar');
}
/* Don’t scroll to compensate for the ToC if we’re above it already. */
var headY = 0;
var head = document.querySelector('.head');
if (head) {
// terrible approx of "top of ToC"
headY += head.offsetTop + head.offsetHeight;
}
var skipScroll = window.scrollY < headY;
var toggle = document.getElementById('toc-toggle');
var tocNav = document.getElementById('toc');
if (on) {
var tocHeight = tocNav.offsetHeight;
document.body.classList.add('toc-sidebar');
document.body.classList.remove('toc-inline');
toggle.innerHTML = collapseSidebarText;
if (!skipScroll) {
window.scrollBy(0, 0 - tocHeight);
}
tocNav.focus();
sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
}
else {
document.body.classList.add('toc-inline');
document.body.classList.remove('toc-sidebar');
toggle.innerHTML = expandSidebarText;
if (!skipScroll) {
window.scrollBy(0, tocNav.offsetHeight);
}
if (toggle.matches(':hover')) {
/* Unfocus button when not using keyboard navigation,
because I don’t know where else to send the focus. */
toggle.blur();
}
}
}
function createSidebarToggle() {
/* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
var toggle = document.createElement('a');
/* This should probably be a button, but appearance isn’t standards-track.*/
toggle.id = 'toc-toggle';
toggle.class = 'toc-toggle';
toggle.href = '#toc';
toggle.innerHTML = collapseSidebarText;
sidebarMedia.addListener(autoToggle);
var toggler = function(e) {
e.preventDefault();
sidebarMedia.removeListener(autoToggle); // persist explicit off states
toggleSidebar();
return false;
}
toggle.addEventListener('click', toggler, false);
/* Get <nav id=toc-nav>, or make it if we don’t have one. */
var tocNav = document.getElementById('toc-nav');
if (!tocNav) {
tocNav = document.createElement('p');
tocNav.id = 'toc-nav';
/* Prepend for better keyboard navigation */
document.body.insertBefore(tocNav, document.body.firstChild);
}
/* While we’re at it, make sure we have a Jump to Toc link. */
var tocJump = document.getElementById('toc-jump');
if (!tocJump) {
tocJump = document.createElement('a');
tocJump.id = 'toc-jump';
tocJump.href = '#toc';
tocJump.innerHTML = tocJumpText;
tocNav.appendChild(tocJump);
}
tocNav.appendChild(toggle);
}
var toc = document.getElementById('toc');
if (toc) {
createSidebarToggle();
toggleSidebar(sidebarMedia.matches);
/* If the sidebar has been manually opened and is currently overlaying the text
(window too small for the MQ to add the margin to body),
then auto-close the sidebar once you click on something in there. */
toc.addEventListener('click', function(e) {
if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
toggleSidebar(false);
}
}, false);
}
else {
console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
}
/* Wrap tables in case they overflow */
var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
var numTables = tables.length;
for (var i = 0; i < numTables; i++) {
var table = tables[i];
var wrapper = document.createElement('div');
wrapper.className = 'overlarge';
table.parentNode.insertBefore(wrapper, table);
wrapper.appendChild(table);
}
})();
</script>
<h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
<h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
<dl>
<dt id="biblio-p0137r1">[P0137R1]
<dd>Richard Smith. <a href="https://wg21.link/p0137r1">Core Issue 1776: Replacement of class objects containing reference members</a>. 23 June 2016. URL: <a href="https://wg21.link/p0137r1">https://wg21.link/p0137r1</a>
<dt id="biblio-p0593r0">[P0593R0]
<dd>Ville Voutilainen. <a href="https://wg21.link/p0593r0">What to do with buffers that are not arrays, and undefined behavior thereof?</a>. 5 February 2017. URL: <a href="https://wg21.link/p0593r0">https://wg21.link/p0593r0</a>
<dt id="biblio-p0593r1">[P0593R1]
<dd>Richard Smith, Ville Voutilainen. <a href="https://wg21.link/p0593r1">Implicit creation of objects for low-level object manipulation</a>. URL: <a href="https://wg21.link/p0593r1">https://wg21.link/p0593r1</a>
</dl>