<!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>P1153R0: Copying volatile subobjects is not trivial</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 .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.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 {
			clear: both;
		}

		: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; }
		}
	/* } */

	@supports (display:grid) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** 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 dff342f4b23fb230b71436fb31b55f5f169715bd" name="generator">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
<style>
ins  {background-color: #CCFFCC; text-decoration: underline;}
del  {background-color: #FFCACA; text-decoration: line-through;}
</style>
<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; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[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">P1153R0<br>Copying volatile subobjects is not trivial</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2018-10-04">2018-10-04</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>Issue Tracking:
     <dd><a href="#issues-index">Inline In Spec</a>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:arthur.j.odwyer@gmail.com">Arthur O'Dwyer</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:cxx@jfbastien.com">JF Bastien</a>
     <dt>Audience:
     <dd>EWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Current Source:
     <dd><a href="https://github.com/Quuxplusone/draft/blob/gh-pages/d1153-volatile-subobjects.bs">github.com/Quuxplusone/draft/blob/gh-pages/d1153-volatile-subobjects.bs</a>
     <dt>Current:
     <dd><a href="https://rawgit.com/Quuxplusone/draft/gh-pages/d1153-volatile-subobjects.html">rawgit.com/Quuxplusone/draft/gh-pages/d1153-volatile-subobjects.html</a>
    </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>In C++11, if a class type had both a volatile subobject and defaulted special members, it was trivially copyable.

CWG issue 496 (2004–2012) changed this so that if a class type had both a volatile subobject and defaulted special members, it was
non-trivially copyable.
CWG issues 1746 and 2094 (2013–2016) changed it back, so that if a class type had both a volatile subobject and defaulted
special members, it was trivially copyable.
This is where we stand today.
This paper proposes that class types with volatile subobjects should have their copy and move operations default to deleted.
We propose this change because the authors do not know of any correct usage of copying structs with volatile subobjects.</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="#motivation"><span class="secno">1</span> <span class="content">Motivation for volatile subobjects</span></a>
    <li>
     <a href="#history"><span class="secno">2</span> <span class="content">History</span></a>
     <ol class="toc">
      <li><a href="#cwg496"><span class="secno">2.1</span> <span class="content">CWG 496: Is a volatile-qualified type really a POD?</span></a>
      <li><a href="#cwg1746"><span class="secno">2.2</span> <span class="content">CWG 1746: Are volatile scalar types trivially copyable?</span></a>
      <li><a href="#cwg2094"><span class="secno">2.3</span> <span class="content">CWG 2094: Trivial move/copy constructor for class with volatile member</span></a>
     </ol>
    <li><a href="#problem"><span class="secno">3</span> <span class="content">The problem</span></a>
    <li><a href="#solution"><span class="secno">4</span> <span class="content">The proposed solution</span></a>
    <li><a href="#wording"><span class="secno">5</span> <span class="content">Proposed wording</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
    <li><a href="#issues-index"><span class="secno"></span> <span class="content">Issues Index</span></a>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="motivation"><span class="secno">1. </span><span class="content">Motivation for volatile subobjects</span><a class="self-link" href="#motivation"></a></h2>
   <p>Volatile-qualifying a specific non-static data member (NSDM) of a class doesn’t sound like a very useful thing to do.
But it does have at least one use, in the embedded-systems niche:</p>
<pre class="language-c++ highlight">    <c- k>struct</c-> <c- n>MemoryMappedRegisters</c-> <c- p>{</c->
        <c- k>volatile</c-> <c- b>uint32_t</c-> <c- n>r0</c-><c- p>;</c->
        <c- k>volatile</c-> <c- b>uint32_t</c-> <c- n>r1</c-><c- p>;</c->
        <c- k>volatile</c-> <c- b>uint32_t</c-> <c- n>r2</c-><c- p>;</c->
        <c- k>volatile</c-> <c- b>uint32_t</c-> <c- n>r3</c-><c- p>;</c->
    <c- p>};</c->

    <c- n>MemoryMappedRegisters</c-><c- o>&amp;</c-> <c- n>g_registers</c-> <c- o>=</c-> <c- o>*</c-><c- p>(</c-><c- n>MemoryMappedRegisters</c-><c- o>*</c-><c- p>)</c-><c- mh>0x4200</c-><c- p>;</c->

    <c- b>void</c-> <c- nf>foo</c-><c- p>(</c-><c- n>MemoryMappedRegisters</c-><c- o>&amp;</c-> <c- n>regs</c-><c- p>)</c-> <c- p>{</c->
        <c- p>...</c->
        <c- c1>// This access is defined by our implementation to perform a 4-byte store</c->
        <c- c1>// followed by two 4-byte loads.</c->
        <c- n>regs</c-><c- p>.</c-><c- n>r0</c-> <c- o>=</c-> <c- mh>0x1234</c-><c- p>;</c->
        <c- k>auto</c-> <c- n>x</c-> <c- o>=</c-> <c- n>regs</c-><c- p>.</c-><c- n>r1</c-><c- p>;</c->
        <c- k>auto</c-> <c- n>y</c-> <c- o>=</c-> <c- n>regs</c-><c- p>.</c-><c- n>r1</c-><c- p>;</c->  <c- c1>// re-load from the same register</c->
        <c- p>...</c->
    <c- p>}</c->
</pre>
   <p>This example motivates classes with volatile-qualified NSDMs. It does not motivate <em>copying</em> those classes.</p>
   <p>In some rare cases the programmer might actually want to copy all of <code class="highlight"><c- n>regs</c-></code> at once. In that case, the status quo
is harmful, rather than helpful. The status quo is to generate a defaulted copy constructor that copies bytes
out of the source object in an unspecified manner, ignoring whatever system-specific concerns led the
programmer to mark the members <code class="highlight"><c- k>volatile</c-></code> in the first place.</p>
   <p>Further, placing a struct with volatile members on the stack is nonsensical.</p>
   <h2 class="heading settled" data-level="2" id="history"><span class="secno">2. </span><span class="content">History</span><a class="self-link" href="#history"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="cwg496"><span class="secno">2.1. </span><span class="content">CWG 496: Is a volatile-qualified type really a POD?</span><a class="self-link" href="#cwg496"></a></h3>
   <p>In December 2004, John Maddock <a data-link-type="biblio" href="#biblio-cwg496">writes</a>:</p>
   <blockquote>
    <p>In 6.9 [basic.types] paragraph 10, the standard makes it quite clear that volatile qualified types are PODs:</p>
    <blockquote>
     <p>Arithmetic types (6.9.1 [basic.fundamental]), enumeration types, pointer types, and pointer to member types
(6.9.2 [basic.compound]), and cv-qualified versions of these types (6.9.3 [basic.type.qualifier]) are
collectively called <b><i>scalar types</i></b>. Scalar types, POD-struct types, POD-union types (clause 12 [class]),
arrays of such types and cv-qualified versions of these types (6.9.3 [basic.type.qualifier]) are
collectively called <b><i>POD types</i></b>.</p>
    </blockquote>
    <p>However in 6.9 [basic.types] paragraph 3, the standard makes it clear that PODs can be copied “as if” they
were a collection of bytes by memcpy:</p>
    <blockquote>
     <p>For any POD type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1
nor obj2 is a base-class subobject, if the value of obj1 is copied into obj2, using the std::memcpy
library function, obj2 shall subsequently hold the same value as obj1.</p>
    </blockquote>
    <p>The problem with this is that a volatile qualified type may need to be copied in a specific way
(by copying using only atomic operations on multithreaded platforms, for example) in order to avoid
the “memory tearing” that may occur with a byte-by-byte copy.</p>
   </blockquote>
   <p>Proposed resolution, October 2012:</p>
   <p>Change 6.9 [basic.types] paragraph 9 as follows:</p>
   <blockquote>
    <p>...Scalar types, trivially copyable class types, arrays of such types, and</p>
    <del>cv-qualified</del>
    <ins>non-volatile const-qualified</ins>
     versions of these types are collectively called <i>trivially copyable types</i>. Scalar types, trivial class types... 
   </blockquote>
   <p>Change 10.1.7.1 [dcl.type.cv] paragraphs 6-7 as follows:</p>
   <blockquote>
    <ins>What constitutes an access to an object that has volatile-qualified type is implementation-defined.</ins>
     If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue
with a non-volatile-qualified type, the program behavior is undefined. 
    <p>
     [<em>Note:</em> <code class="highlight"><c- k>volatile</c-></code> is a hint to the implementation to avoid aggressive optimization involving the object because
the value of the object might be changed by means undetectable by an implementation. 
     <ins>Furthermore, for some implementations, <code class="highlight"><c- k>volatile</c-></code> might indicate that special hardware instructions are required to access the object.</ins>
      See 4.6 [intro.execution] for detailed semantics. In general, the semantics of <code class="highlight"><c- k>volatile</c-></code> are intended to be the same
in C++ as they are in C. <em>—end note</em>]
    </p>
   </blockquote>
   <p>Change 15.8 [class.copy] paragraph 12 as follows:</p>
   <blockquote>
    <p>A copy/move constructor for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided, its declared parameter type is
the same as if it had been implicitly declared, and if</p>
    <ul>
     <li data-md>
      <p>class <code class="highlight"><c- n>X</c-></code> has no virtual functions and no virtual base classes, and</p>
     <li data-md>
      <ins>class <code class="highlight"><c- n>X</c-></code> has no non-static data members of volatile-qualified type, and</ins>
    </ul>
    <p>...</p>
   </blockquote>
   <p>Change 15.8 [class.copy] paragraph 25 as follows:</p>
   <blockquote>
    <p>A copy/move assignment operator for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided, its declared
parameter type is the same as if it had been implicitly declared, and if</p>
    <ul>
     <li data-md>
      <p>class <code class="highlight"><c- n>X</c-></code> has no virtual functions and no virtual base classes, and</p>
     <li data-md>
      <ins>class <code class="highlight"><c- n>X</c-></code> has no non-static data members of volatile-qualified type, and</ins>
    </ul>
    <p>...</p>
   </blockquote>
   <h3 class="heading settled" data-level="2.2" id="cwg1746"><span class="secno">2.2. </span><span class="content">CWG 1746: Are volatile scalar types trivially copyable?</span><a class="self-link" href="#cwg1746"></a></h3>
   <p>In September 2013, Walter Brown <a data-link-type="biblio" href="#biblio-cwg1746">writes</a>:</p>
   <blockquote>
    <p>According to 6.9 [basic.types] paragraph 9,</p>
    <blockquote>
     <p>Arithmetic types (6.9.1 [basic.fundamental]), enumeration types, pointer types, pointer to member types
(6.9.2 [basic.compound]), std::nullptr_t, and cv-qualified versions of these types
(6.9.3 [basic.type.qualifier]) are collectively called <i>scalar types</i>... Scalar types, trivially
copyable class types (Clause 12 [class]), arrays of such types, and non-volatile const-qualified versions
of these types (6.9.3 [basic.type.qualifier]) are collectively called <i>trivially copyable types</i>.</p>
    </blockquote>
    <p>This is confusing, because “scalar types” include volatile-qualified types, but the intent of the
definition of “trivially copyable type” appears to be to exclude volatile-qualified types.
Perhaps the second quoted sentence should read something like,</p>
    <blockquote>
     <p>A non-volatile type <code class="highlight"><c- n>T</c-></code> or an array of such <code class="highlight"><c- n>T</c-></code> is called a <i>trivially copyable type</i> if <code class="highlight"><c- n>T</c-></code> is either a
scalar type or a trivially copyable class type.</p>
    </blockquote>
    <p>(Note that the following sentence, defining “trivial type,” has a similar formal issue, although it
has no actual significance because all cv-qualifiers are permitted.)</p>
   </blockquote>
   <p>Proposed resolution, January 2014:</p>
   <p>Change 6.9 [basic.types] paragraph 10 as follows:</p>
   <blockquote>
    <p>
     ...
     <del>Scalar</del>
     <ins>Cv-unqualified scalar</ins>
      types, trivially copyable class types,
arrays of such types, and non-volatile const-qualified versions of these
types are collectively called <i>trivially copyable types</i>...
    </p>
   </blockquote>
   <h3 class="heading settled" data-level="2.3" id="cwg2094"><span class="secno">2.3. </span><span class="content">CWG 2094: Trivial move/copy constructor for class with volatile member</span><a class="self-link" href="#cwg2094"></a></h3>
   <p>In March 2015, Daveed Vandevoorde <a data-link-type="biblio" href="#biblio-cwg2094">writes</a>:</p>
   <blockquote>
    <p>The resolution of issue 496 included the addition of 15.8 [class.copy] paragraph 25.2, making a class’s
copy/move constructor non-trivial if it has a non-static data member of volatile-qualified type.
This change breaks the IA-64 ABI, so it has been requested that CWG reconsider this aspect of the resolution.</p>
    <p>On a related note, the resolution of issue 496 also changed 6.9 [basic.types] paragraph 9, which makes
volatile-qualified scalar types “trivial” but not “trivially copyable.” It is not clear why there is
a distinction made here; the only actual use of “trivial type” in the Standard appears to be in the
description of <code class="highlight"><c- n>qsort</c-></code>, which should probably use “trivially copyable.” (See also issue 1746.)</p>
   </blockquote>
   <p>Notes from the February 2016 meeting:</p>
   <blockquote>
    <p>CWG agreed with the suggested direction for the changes in 15.8 [class.copy]; the use of “trivial”
will be dealt with separately and not as part of the resolution of this issue.</p>
   </blockquote>
   <p>Proposed resolution, June 2016:</p>
   <p>Change 6.9 [basic.types] paragraph 9 as follows:</p>
   <blockquote>
    <p>
     ...called <i>POD types</i>. Cv-unqualified scalar types, trivially copyable class types,
arrays of such types, and 
     <del>non-volatile const-qualified</del>
     <ins>cv-qualified</ins>
      versions of these
types are collectively called <i>trivially copyable types</i>. Scalar types...
    </p>
   </blockquote>
   <p>Delete bullet 12.2 of 15.8 [class.copy]:</p>
   <blockquote>
    <p>A copy/move constructor for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided,
its parameter-type-list is equivalent to the parameter-type-list of an implicit declaration, and if</p>
    <p>...</p>
    <ul>
     <li data-md>
      <del>class <code class="highlight"><c- n>X</c-></code> has no non-static data members of volatile-qualified type, and</del>
    </ul>
    <p>...</p>
   </blockquote>
   <p>Delete bullet 25.2 of 15.8 [class.copy]:</p>
   <blockquote>
    <p>A copy/move assignment operator for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided,
its parameter-type-list is equivalent to the parameter-type-list of an implicit
declaration, and if</p>
    <p>...</p>
    <ul>
     <li data-md>
      <del>class <code class="highlight"><c- n>X</c-></code> has no non-static data members of volatile-qualified type, and</del>
    </ul>
   </blockquote>
   <h2 class="heading settled" data-level="3" id="problem"><span class="secno">3. </span><span class="content">The problem</span><a class="self-link" href="#problem"></a></h2>
   <p>Library vendors use <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_copyable</c-></code> to detect object types that can be copied
via <code class="highlight"><c- n>memcpy</c-></code>/<code class="highlight"><c- n>memmove</c-></code>. This idiom does not work when volatile NSDMs are in play.</p>
<pre class="language-c++ highlight">    <c- cp>#include</c-> &lt;algorithm>
    <c- k>struct</c-> <c- n>S</c-> <c- p>{</c->
        <c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c->
    <c- p>};</c->
    <c- b>void</c-> <c- nf>foo</c-><c- p>(</c-><c- n>S</c-> <c- o>*</c-><c- n>dst</c-><c- p>,</c-> <c- n>S</c-> <c- o>*</c-><c- n>src</c-><c- p>,</c-> <c- b>int</c-> <c- n>n</c-><c- p>)</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>copy_n</c-><c- p>(</c-><c- n>src</c-><c- p>,</c-> <c- n>n</c-><c- p>,</c-> <c- n>dst</c-><c- p>);</c->
    <c- p>}</c->
</pre>
   <p>Today, both libc++ and libstdc++ generate a single <code class="highlight"><c- n>memmove</c-></code> to perform the copy of <code class="highlight"><c- n>src</c-></code> to <code class="highlight"><c- n>dst</c-></code>,
even though the copying is happening between many discrete (sub)objects that are each
volatile-qualified.</p>
   <p>Library vendors also have no incentive to change their behavior here; it seems to be
strictly non-conforming, but the optimization for <em>non</em>-volatile NSDMs is too valuable to
give up, and there is currently no way for a library to detect the presence of volatile NSDMs
nested within a class.</p>
   <h2 class="heading settled" data-level="4" id="solution"><span class="secno">4. </span><span class="content">The proposed solution</span><a class="self-link" href="#solution"></a></h2>
   <p>Whereas</p>
   <ul>
    <li data-md>
     <p>the current semantics by which volatile NSDMs are copied (trivially) are untenable for library vendors,</p>
    <li data-md>
     <p><a data-link-type="biblio" href="#biblio-cwg496">[CWG496]</a> and <a data-link-type="biblio" href="#biblio-cwg2094">[CWG2094]</a> show there is no consensus to <em>change</em> the semantics by which volatile NSDMs are copied (to make it non-trivial),</p>
    <li data-md>
     <p>nobody has yet presented a use-case for wanting to copy volatile NSDMs at all,</p>
   </ul>
   <p>we propose that</p>
   <ul>
    <li data-md>
     <p>volatile NSDMs should not be copyable.</p>
   </ul>
   <p>That is, the presence of a <code class="highlight"><c- k>volatile</c-></code>-qualified NSDM in a class should cause the class’s copy constructor
and copy assignment operator to be defaulted as deleted. The library would continue to detect a Rule-of-Zero-following,
volatile-NSDM-having class as <code class="highlight"><c- n>is_trivially_copyable</c-></code>; but it would also detect it as <code class="highlight"><c- n>not</c-> <c- n>is_copy_constructible</c-></code> and <code class="highlight"><c- n>not</c-> <c- n>is_move_constructible</c-></code>, so it wouldn’t try to <code class="highlight"><c- n>memcpy</c-></code> its bytes, and so our tearing problem would be solved.</p>
   <p>This solution does not change any ABI, because it merely removes (useless, dangerous) functions that were generated before.
In particular, this proposal preserves the <i>trivial copyability</i> of structs with volatile members, so that it
preserves the calling convention by which they may be returned in registers on IA64.</p>
   <div class="issue" id="issue-2bb6e0ec">
    <a class="self-link" href="#issue-2bb6e0ec"></a> Hmm, I now think this is wrong. Trivial copyability
(<a href="https://timsong-cpp.github.io/cppwp/class#prop-1">[class.prop]/1</a>) requires at least one non-deleted
copy-or-move constructor-or-assignment-operator; and our struct will no longer have that. Also, tcanens points
to special wording in <a href="https://timsong-cpp.github.io/cppwp/class.temporary#3">[class.temporary]/3</a> that permits returning our struct in registers only if it has a non-deleted copy-or-move constructor.
Specifically: 
<pre class="language-c++ highlight"><c- k>struct</c-> <c- n>S</c-> <c- p>{</c-> <c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- p>};</c->
<c- n>S</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>S</c-><c- p>{</c-><c- mi>42</c-><c- p>};</c-> <c- p>}</c->  <c- c1>// returns in %eax today</c->
</pre>
    Whereas if we delete all the constructors: 
<pre class="language-c++ highlight"><c- k>struct</c-> <c- n>S</c-> <c- p>{</c-> <c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- n>S</c-><c- p>(</c-><c- k>const</c-> <c- n>S</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- n>delete</c-><c- p>;</c-> <c- p>};</c->
<c- n>S</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>S</c-><c- p>{</c-><c- mi>42</c-><c- p>};</c-> <c- p>}</c->  <c- c1>// returns on the stack today</c->
</pre>
    This means we might have no choice but to break ABI. 
   </div>
   <h2 class="heading settled" data-level="5" id="wording"><span class="secno">5. </span><span class="content">Proposed wording</span><a class="self-link" href="#wording"></a></h2>
   <p>The wording in this section is relative to <a data-link-type="biblio" href="#biblio-n4750">WG21 draft N4750</a>,
that is, the current draft of the C++17 standard. We quote many unchanged
passages here for reference.</p>
   <p>[basic.types] #3 is unchanged:</p>
   <blockquote>
    <p>For any trivially copyable type <code class="highlight"><c- n>T</c-></code>, if two pointers to <code class="highlight"><c- n>T</c-></code> point to distinct <code class="highlight"><c- n>T</c-></code> objects <code class="highlight"><c- n>obj1</c-></code> and <code class="highlight"><c- n>obj2</c-></code>,
where neither <code class="highlight"><c- n>obj1</c-></code> nor <code class="highlight"><c- n>obj2</c-></code> is a potentially-overlapping subobject, if the underlying bytes making up <code class="highlight"><c- n>obj1</c-></code> are copied into <code class="highlight"><c- n>obj2</c-></code>, <code class="highlight"><c- n>obj2</c-></code> shall subsequently hold the same value as <code class="highlight"><c- n>obj1</c-></code>.</p>
   </blockquote>
   <p>[basic.types] #9 is unchanged (after editorial clarification <a data-link-type="biblio" href="#biblio-pr2255">[PR2255]</a>):</p>
   <blockquote>
    <p>Arithmetic types, enumeration types, pointer types, pointer-to-member types, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>nullptr_t</c-></code>, and
cv-qualified versions of these types are collectively called <i>scalar types</i>. Scalar types,
trivially copyable class types, arrays of such types, and cv-qualified versions of these types are
collectively called <i>trivially copyable types</i>. Scalar types, trivial class types, arrays of such types
and cv-qualified versions of these types are collectively called <i>trivial types</i>. Scalar types,
standard-layout class types, arrays of such types and cv-qualified versions of these types
are collectively called <i>standard-layout types</i>.</p>
   </blockquote>
   <p>[class.prop] #1 is unchanged:</p>
   <blockquote>
    <p>A <i>trivially copyable class</i> is a class:</p>
    <ul>
     <li data-md>
      <p>where each copy constructor, move constructor, copy assignment operator, and move
assignment operator is either deleted or trivial,</p>
     <li data-md>
      <p>that has at least one non-deleted copy constructor, move constructor, copy assignment
operator, or move assignment operator, and</p>
     <li data-md>
      <p>that has a trivial, non-deleted destructor.</p>
    </ul>
   </blockquote>
   <p>[class.temporary] #3 is unchanged:</p>
   <blockquote>
    <p>When an object of class type <code class="highlight"><c- n>X</c-></code> is passed to or returned from a function, if each copy constructor,
move constructor, and destructor of <code class="highlight"><c- n>X</c-></code> is either trivial or deleted, and <code class="highlight"><c- n>X</c-></code> has at least one
non-deleted copy or move constructor, implementations are permitted to create a temporary object
to hold the function parameter or result object. The temporary object is constructed from the function
argument or return value, respectively, and the function’s parameter or return object is
initialized as if by using the non-deleted trivial constructor to copy the temporary (even if
that constructor is inaccessible or would not be selected by overload resolution to perform a
copy or move of the object). [<em>Note:</em> This latitude is granted to allow objects of class type
to be passed to or returned from functions in registers. <em>—end note</em>]</p>
   </blockquote>
   <p>[class.copy.ctor] #6 is unchanged:</p>
   <blockquote>
    <p>If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared <i>implicitly</i>.
If the class definition declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is defined as defaulted. The latter case is deprecated
if the class has a user-declared copy assignment operator or a user-declared destructor.</p>
   </blockquote>
   <p>[class.copy.ctor] #7 is unchanged:</p>
   <blockquote>
    <p>The implicitly-declared copy constructor for a class <code class="highlight"><c- n>X</c-></code> will have the form</p>
<pre class="highlight"><c- n>X</c-><c- o>::</c-><c- n>X</c-><c- p>(</c-><c- k>const</c-> <c- n>X</c-><c- o>&amp;</c-><c- p>)</c->
</pre>
    if each potentially constructed subobject of a class type <code class="highlight"><c- n>M</c-></code> (or array thereof) has a copy constructor
whose first parameter is of type <code class="highlight"><c- k>const</c-> <c- n>M</c-><c- o>&amp;</c-></code> or <code class="highlight"><c- k>const</c-> <c- k>volatile</c-> <c- n>M</c-><c- o>&amp;</c-></code>. Otherwise, the implicitly-declared
copy constructor will have the form 
<pre class="highlight"><c- n>X</c-><c- o>::</c-><c- n>X</c-><c- p>(</c-><c- n>X</c-><c- o>&amp;</c-><c- p>)</c->
</pre>
   </blockquote>
   <p>[class.copy.ctor] #8 is unchanged:</p>
   <blockquote>
    <p>If the definition of a class <code class="highlight"><c- n>X</c-></code> does not explicitly declare a move constructor, a non-explicit one will
be implicitly declared as defaulted if and only if</p>
    <ul>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared copy constructor,</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared copy assignment operator,</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared move assignment operator, and</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared destructor.</p>
    </ul>
    <p>[<em>Note:</em> When the move constructor is not implicitly declared or explicitly supplied, expressions that
otherwise would have invoked the move constructor may instead invoke a copy constructor. <em>—end note</em>]</p>
   </blockquote>
   <p>Change [class.copy.ctor] #10:</p>
   <blockquote>
    <p>An implicitly-declared copy/move constructor is an inline public member of its class.
A defaulted copy/move constructor for a class <code class="highlight"><c- n>X</c-></code> is defined as deleted if <code class="highlight"><c- n>X</c-></code> has:</p>
    <ul>
     <li data-md>
      <p>a potentially constructed subobject type <code class="highlight"><c- n>M</c-></code> (or array thereof) that cannot be copied/moved
because overload resolution, as applied to find <code class="highlight"><c- n>M</c-></code>’s corresponding constructor, results
in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,</p>
     <li data-md>
      <p>a variant member whose corresponding constructor as selected by overload resolution is non-trivial,</p>
     <li data-md>
      <ins>a non-static data member of <code class="highlight"><c- k>volatile</c-></code> type (or array thereof), or</ins>
     <li data-md>
      <p>any potentially constructed subobject of a type with a destructor that is deleted or inaccessible
from the defaulted constructor, or,</p>
     <li data-md>
      <p>for the copy constructor, a non-static data member of rvalue reference type.</p>
    </ul>
    <p>A defaulted move constructor that is defined as deleted is ignored by overload resolution.
[<em>Note:</em> A deleted move constructor would otherwise interfere with initialization from an rvalue
which can use the copy constructor instead. <em>—end note</em>]</p>
   </blockquote>
   <p>[class.copy.ctor] #11 is unchanged:</p>
   <blockquote>
    <p>A copy/move constructor for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided and if:</p>
    <ul>
     <li data-md>
      <p>class X has no virtual functions and no virtual base classes, and</p>
     <li data-md>
      <p>the constructor selected to copy/move each direct base class subobject is trivial, and</p>
     <li data-md>
      <p>for each non-static data member of <code class="highlight"><c- n>X</c-></code> that is of class type (or array thereof),
the constructor selected to copy/move that member is trivial;</p>
    </ul>
    <p>otherwise the copy/move constructor is <i>non-trivial</i>.</p>
   </blockquote>
   <p>[class.copy.assign] #2 is unchanged:</p>
   <blockquote>
    <p>If the class definition does not explicitly declare a copy assignment operator, one is
declared <i>implicitly</i>. If the class definition declares a move constructor or move
assignment operator, the implicitly declared copy assignment operator is defined as deleted;
otherwise, it is defined as defaulted. The latter case is deprecated if the class has
a user-declared copy constructor or a user-declared destructor.</p>
    <p>The implicitly-declared copy assignment operator for a class <code class="highlight"><c- n>X</c-></code> will have the form</p>
<pre class="highlight"><c- n>X</c-><c- o>&amp;</c-> <c- n>X</c-><c- o>::</c-><c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>X</c-><c- o>&amp;</c-><c- p>)</c->
</pre>
    if 
    <ul>
     <li data-md>
      <p>each direct base class <code class="highlight"><c- n>B</c-></code> of <code class="highlight"><c- n>X</c-></code> has a copy assignment operator whose parameter is
of type <code class="highlight"><c- k>const</c-> <c- n>B</c-><c- o>&amp;</c-></code>, <code class="highlight"><c- k>const</c-> <c- k>volatile</c-> <c- n>B</c-><c- o>&amp;</c-></code>, or <code class="highlight"><c- n>B</c-></code>, and</p>
     <li data-md>
      <p>for all the non-static data members of <code class="highlight"><c- n>X</c-></code> that are of a class type <code class="highlight"><c- n>M</c-></code> (or array thereof),
each such class type has a copy assignment operator whose parameter is of type <code class="highlight"><c- k>const</c-> <c- n>M</c-><c- o>&amp;</c-></code>, <code class="highlight"><c- k>const</c-> <c- k>volatile</c-> <c- n>M</c-><c- o>&amp;</c-></code>, or <code class="highlight"><c- n>M</c-></code>.</p>
    </ul>
    <p>Otherwise, the implicitly-declared copy assignment operator will have the form</p>
<pre class="highlight"><c- n>X</c-><c- o>&amp;</c-> <c- n>X</c-><c- o>::</c-><c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>X</c-><c- o>&amp;</c-><c- p>)</c->
</pre>
   </blockquote>
   <p>[class.copy.assign] #4 is unchanged:</p>
   <blockquote>
    <p>If the definition of a class <code class="highlight"><c- n>X</c-></code> does not explicitly declare a move assignment operator,
one will be implicitly declared as defaulted if and only if</p>
    <ul>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared copy constructor,</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared move constructor,</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared copy assignment operator, and</p>
     <li data-md>
      <p><code class="highlight"><c- n>X</c-></code> does not have a user-declared destructor.</p>
    </ul>
   </blockquote>
   <p>Change [class.copy.assign] #7:</p>
   <blockquote>
    <p>A defaulted copy/move assignment operator for class <code class="highlight"><c- n>X</c-></code> is defined as deleted if <code class="highlight"><c- n>X</c-></code> has:</p>
    <ul>
     <li data-md>
      <p>a variant member with a non-trivial corresponding assignment operator and <code class="highlight"><c- n>X</c-></code> is a union-like class, or</p>
     <li data-md>
      <p>a non-static data member of <code class="highlight"><c- k>const</c-></code> non-class type (or array thereof), or</p>
     <li data-md>
      <ins>a non-static data member of <code class="highlight"><c- k>volatile</c-></code> type (or array thereof), or</ins>
     <li data-md>
      <p>a non-static data member of reference type, or</p>
     <li data-md>
      <p>a direct non-static data member of class type <code class="highlight"><c- n>M</c-></code> (or array thereof) or a direct base class <code class="highlight"><c- n>M</c-></code> that cannot be copied/moved because overload resolution, as applied to find <code class="highlight"><c- n>M</c-></code>’s corresponding
assignment operator, results in an ambiguity or a function that is deleted or inaccessible
from the defaulted assignment operator.</p>
    </ul>
    <p>A defaulted move assignment operator that is defined as deleted is ignored by overload resolution.</p>
   </blockquote>
   <p>[class.copy.assign] #9 is unchanged:</p>
   <blockquote>
    <p>A copy/move assignment operator for class <code class="highlight"><c- n>X</c-></code> is <i>trivial</i> if it is not user-provided and if:</p>
    <ul>
     <li data-md>
      <p>class <code class="highlight"><c- n>X</c-></code> has no virtual functions and no virtual base classes, and</p>
     <li data-md>
      <p>the assignment operator selected to copy/move each direct base class subobject is trivial, and</p>
     <li data-md>
      <p>for each non-static data member of <code class="highlight"><c- n>X</c-></code> that is of class type (or array thereof), the assignment
operator selected to copy/move that member is trivial;</p>
    </ul>
    <p>otherwise the copy/move assignment operator is <i>non-trivial</i>.</p>
   </blockquote>
  </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="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
  <dl>
   <dt id="biblio-n4750">[N4750]
   <dd>Richard Smith. <a href="https://wg21.link/n4750">Working Draft, Standard for Programming Language C++</a>. 7 May 2018. URL: <a href="https://wg21.link/n4750">https://wg21.link/n4750</a>
  </dl>
  <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-cwg1746">[CWG1746]
   <dd>Walter Brown. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1746">Are volatile scalar types trivially copyable?</a>. September 2013–January 2014. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1746">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1746</a>
   <dt id="biblio-cwg2094">[CWG2094]
   <dd>Daveed Vandevoorde. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094">Trivial copy/move constructor for class with volatile member</a>. March 2015–June 2016. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094</a>
   <dt id="biblio-cwg496">[CWG496]
   <dd>John Maddock. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#496">Is a volatile-qualified type really a POD?</a>. December 2004–October 2012. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#496">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#496</a>
   <dt id="biblio-pr2255">[PR2255]
   <dd>Arthur O'Dwyer. <a href="https://github.com/cplusplus/draft/pull/2255">'cv-qualified versions of cv-unqualified scalar types' are just 'scalar types'</a>. July 2018. URL: <a href="https://github.com/cplusplus/draft/pull/2255">https://github.com/cplusplus/draft/pull/2255</a>
  </dl>
  <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content">Issues Index</span><a class="self-link" href="#issues-index"></a></h2>
  <div style="counter-reset:issue">
   <div class="issue">
     Hmm, I now think this is wrong. Trivial copyability
(<a href="https://timsong-cpp.github.io/cppwp/class#prop-1">[class.prop]/1</a>) requires at least one non-deleted
copy-or-move constructor-or-assignment-operator; and our struct will no longer have that. Also, tcanens points
to special wording in <a href="https://timsong-cpp.github.io/cppwp/class.temporary#3">[class.temporary]/3</a> that permits returning our struct in registers only if it has a non-deleted copy-or-move constructor.
Specifically: 
<pre class="language-c++ highlight"><c- k>struct</c-> <c- n>S</c-> <c- p>{</c-> <c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- p>};</c->
<c- n>S</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>S</c-><c- p>{</c-><c- mi>42</c-><c- p>};</c-> <c- p>}</c->  <c- c1>// returns in %eax today</c->
</pre>
    Whereas if we delete all the constructors: 
<pre class="language-c++ highlight"><c- k>struct</c-> <c- n>S</c-> <c- p>{</c-> <c- k>volatile</c-> <c- b>int</c-> <c- n>i</c-><c- p>;</c-> <c- n>S</c-><c- p>(</c-><c- k>const</c-> <c- n>S</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- n>delete</c-><c- p>;</c-> <c- p>};</c->
<c- n>S</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>S</c-><c- p>{</c-><c- mi>42</c-><c- p>};</c-> <c- p>}</c->  <c- c1>// returns on the stack today</c->
</pre>
    This means we might have no choice but to break ABI. <a href="#issue-2bb6e0ec"> ↵ </a>
   </div>
  </div>