<!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>P1144R5: Object relocation in terms of move plus destroy</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) and (display:contents) {
		/* 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 {
		/* Magic to create good table positioning:
		   "content column" is 50ems wide at max; less on smaller screens.
		   Extra space (after ToC + content) is empty on the right.

		   1. When table < content column, centers table in column.
		   2. When content < table < available, left-aligns.
		   3. When table > available, fills available + scroll bar.
		*/ 
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			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-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-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;
    }

    del { background: #fcc; color: #000; text-decoration: line-through; }
    ins { background: #cfc; color: #000; }
    blockquote .highlight:not(.idl) { background: initial; margin: initial; padding: 0.5em }
    blockquote ul { background: inherit; }
    blockquote code.highlight:not(.idl) { padding: initial; }
    blockquote c-[a] { color: inherit; } /* Keyword.Declaration */
    blockquote c-[b] { color: inherit; } /* Keyword.Type */
    blockquote c-[c] { color: inherit; } /* Comment */
    blockquote c-[d] { color: inherit; } /* Comment.Multiline */
    blockquote c-[e] { color: inherit; } /* Name.Attribute */
    blockquote c-[f] { color: inherit; } /* Name.Tag */
    blockquote c-[g] { color: inherit; } /* Name.Variable */
    blockquote c-[k] { color: inherit; } /* Keyword */
    blockquote c-[l] { color: inherit; } /* Literal */
    blockquote c-[m] { color: inherit; } /* Literal.Number */
    blockquote c-[n] { color: inherit; } /* Name */
    blockquote c-[o] { color: inherit; } /* Operator */
    blockquote c-[p] { color: inherit; } /* Punctuation */
    blockquote c-[s] { color: inherit; } /* Literal.String */
    blockquote c-[t] { color: inherit; } /* Literal.String.Single */
    blockquote c-[u] { color: inherit; } /* Literal.String.Double */
    blockquote c-[cp] { color: inherit; } /* Comment.Preproc */
    blockquote c-[c1] { color: inherit; } /* Comment.Single */
    blockquote c-[cs] { color: inherit; } /* Comment.Special */
    blockquote c-[kc] { color: inherit; } /* Keyword.Constant */
    blockquote c-[kn] { color: inherit; } /* Keyword.Namespace */
    blockquote c-[kp] { color: inherit; } /* Keyword.Pseudo */
    blockquote c-[kr] { color: inherit; } /* Keyword.Reserved */
    blockquote c-[ld] { color: inherit; } /* Literal.Date */
    blockquote c-[nc] { color: inherit; } /* Name.Class */
    blockquote c-[no] { color: inherit; } /* Name.Constant */
    blockquote c-[nd] { color: inherit; } /* Name.Decorator */
    blockquote c-[ni] { color: inherit; } /* Name.Entity */
    blockquote c-[ne] { color: inherit; } /* Name.Exception */
    blockquote c-[nf] { color: inherit; } /* Name.Function */
    blockquote c-[nl] { color: inherit; } /* Name.Label */
    blockquote c-[nn] { color: inherit; } /* Name.Namespace */
    blockquote c-[py] { color: inherit; } /* Name.Property */
    blockquote c-[ow] { color: inherit; } /* Operator.Word */
    blockquote c-[mb] { color: inherit; } /* Literal.Number.Bin */
    blockquote c-[mf] { color: inherit; } /* Literal.Number.Float */
    blockquote c-[mh] { color: inherit; } /* Literal.Number.Hex */
    blockquote c-[mi] { color: inherit; } /* Literal.Number.Integer */
    blockquote c-[mo] { color: inherit; } /* Literal.Number.Oct */
    blockquote c-[sb] { color: inherit; } /* Literal.String.Backtick */
    blockquote c-[sc] { color: inherit; } /* Literal.String.Char */
    blockquote c-[sd] { color: inherit; } /* Literal.String.Doc */
    blockquote c-[se] { color: inherit; } /* Literal.String.Escape */
    blockquote c-[sh] { color: inherit; } /* Literal.String.Heredoc */
    blockquote c-[si] { color: inherit; } /* Literal.String.Interpol */
    blockquote c-[sx] { color: inherit; } /* Literal.String.Other */
    blockquote c-[sr] { color: inherit; } /* Literal.String.Regex */
    blockquote c-[ss] { color: inherit; } /* Literal.String.Symbol */
    blockquote c-[vc] { color: inherit; } /* Name.Variable.Class */
    blockquote c-[vg] { color: inherit; } /* Name.Variable.Global */
    blockquote c-[vi] { color: inherit; } /* Name.Variable.Instance */
    blockquote c-[il] { color: inherit; } /* Literal.Number.Integer.Long */
  </style>
  <meta content="Bikeshed version 5721fde7f6b8111f662b83b678f9e181a9838206" 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-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-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-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>
<style>/* style-dfn-panel */

.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: #DDDDDD;
    color: black;
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: black; }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</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>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1144R5<br>Object relocation in terms of move plus destroy</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2020-03-01">2020-03-01</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>Issue Tracking:
     <dd><a href="#issues-index">Inline In Spec</a>
     <dt>Author:
     <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>
     <dt>Audience:
     <dd>LEWG, 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/d1144-object-relocation.bs">github.com/Quuxplusone/draft/blob/gh-pages/d1144-object-relocation.bs</a>
     <dt>Current:
     <dd><a href="https://rawgit.com/Quuxplusone/draft/gh-pages/d1144-object-relocation.html">rawgit.com/Quuxplusone/draft/gh-pages/d1144-object-relocation.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>We define a new verb, "relocate," which is equivalent to a move and a destroy.

  For many C++ types, the "relocate" operation is implementable as a single <code class="highlight"><c- n>memcpy</c-></code>.
  We provide a standard trait to detect types which are trivially relocatable, for the benefit of library writers.
  We provide a rule that correctly propagates trivial relocatability among Rule-of-Zero types.
  Finally, we provide a portable way for a user-defined type (e.g. <code class="highlight"><c- n>boost</c-><c- o>::</c-><c- n>shared_ptr</c-></code>) to warrant
  that it is trivially relocatable.
  This paper was presented at C++Now 2019 as a 90-minute talk titled <a href="https://www.youtube.com/watch?v=SGdfPextuAU">"Trivially Relocatable."</a></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="#changelog"><span class="secno">1</span> <span class="content">Changelog</span></a>
    <li>
     <a href="#intro"><span class="secno">2</span> <span class="content">Introduction and motivation</span></a>
     <ol class="toc">
      <li>
       <a href="#applications"><span class="secno">2.1</span> <span class="content">Optimizations enabled by trivial relocatability</span></a>
       <ol class="toc">
        <li><a href="#benefit-resize"><span class="secno">2.1.1</span> <span class="content">Vector resize</span></a>
        <li><a href="#benefit-swap"><span class="secno">2.1.2</span> <span class="content">Swap</span></a>
        <li><a href="#benefit-type-erasure"><span class="secno">2.1.3</span> <span class="content">More efficient small-buffer type-erasure</span></a>
        <li><a href="#benefit-fixed-capacity"><span class="secno">2.1.4</span> <span class="content">More efficient fixed-capacity containers</span></a>
        <li><a href="#benefit-assertions"><span class="secno">2.1.5</span> <span class="content">Assertions, not assumptions</span></a>
       </ol>
      <li><a href="#doing-it-wrong"><span class="secno">2.2</span> <span class="content">The most important benefit</span></a>
     </ol>
    <li>
     <a href="#design-goals"><span class="secno">3</span> <span class="content">Design goals</span></a>
     <ol class="toc">
      <li><a href="#use1"><span class="secno">3.1</span> <span class="content">Standard library types such as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>string</c-></code></span></a>
      <li><a href="#use2"><span class="secno">3.2</span> <span class="content">Program-defined types that follow the Rule of Zero</span></a>
      <li><a href="#use3"><span class="secno">3.3</span> <span class="content">Program-defined types with non-defaulted special members</span></a>
     </ol>
    <li><a href="#proposal"><span class="secno">4</span> <span class="content">Proposed language and library features</span></a>
    <li>
     <a href="#wording"><span class="secno">5</span> <span class="content">Proposed wording for C++2b</span></a>
     <ol class="toc">
      <li><a href="#wording-operation"><span class="secno">5.1</span> <span class="content">Relocation operation</span></a>
      <li><a href="#wording-relocate-at"><span class="secno">5.2</span> <span class="content">Algorithm <code class="highlight"><c- n>relocate_at</c-></code></span></a>
      <li><a href="#wording-uninit-relocate"><span class="secno">5.3</span> <span class="content">Algorithm <code class="highlight"><c- n>uninitialized_relocate</c-></code></span></a>
      <li><a href="#wording-uninit-relocate-n"><span class="secno">5.4</span> <span class="content">Algorithm <code class="highlight"><c- n>uninitialized_relocate_n</c-></code></span></a>
      <li><a href="#wording-inheritance"><span class="secno">5.5</span> <span class="content">Trivially relocatable type</span></a>
      <li><a href="#wording-attribute"><span class="secno">5.6</span> <span class="content"><code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute</span></a>
      <li><a href="#wording-traits"><span class="secno">5.7</span> <span class="content">Type traits <code class="highlight"><c- n>is_relocatable</c-></code> etc.</span></a>
      <li><a href="#wording-concept"><span class="secno">5.8</span> <span class="content"><code class="highlight"><c- n>Relocatable</c-></code> concept</span></a>
     </ol>
    <li>
     <a href="#alternatives"><span class="secno">6</span> <span class="content">Rationale and alternatives</span></a>
     <ol class="toc">
      <li><a href="#destructive-move"><span class="secno">6.1</span> <span class="content">Why not destructive move?</span></a>
      <li><a href="#bool-parameter"><span class="secno">6.2</span> <span class="content">Why <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code>?</span></a>
      <li><a href="#maybe-trivially-relocatable"><span class="secno">6.3</span> <span class="content">Attribute <code class="highlight"><c- p>[[</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code></span></a>
      <li><a href="#relocatable-list"><span class="secno">6.4</span> <span class="content">Should <code class="highlight"><c- n>relocate_at</c-></code> be a customization point?</span></a>
      <li><a href="#nothrow-relocatable"><span class="secno">6.5</span> <span class="content">Unintuitive <code class="highlight"><c- n>is_nothrow_relocatable</c-></code></span></a>
      <li><a href="#relocate-function"><span class="secno">6.6</span> <span class="content">Provide <code class="highlight"><c- n>T</c-> <c- n>relocate</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- p>)</c-></code>?</span></a>
      <li><a href="#pmr-concerns"><span class="secno">6.7</span> <span class="content">Confusing interactions with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-></code> and <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code></span></a>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">7</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#polls"><span class="secno"></span> <span class="content">Appendix A: Straw polls</span></a>
     <ol class="toc">
      <li><a href="#taken-polls-2020-02-13"><span class="secno"></span> <span class="content">Polls taken at EWGI at Prague on 2020-02-13</span></a>
      <li><a href="#taken-polls-2018-11-12"><span class="secno"></span> <span class="content">Polls taken of the Internet between 2018-11-12 and 2018-11-21</span></a>
      <li><a href="#taken-polls-2018-11-07"><span class="secno"></span> <span class="content">Poll taken of EWGI at San Diego on 2018-11-07</span></a>
      <li><a href="#taken-polls-2018-09-26"><span class="secno"></span> <span class="content">Polls taken of SG14 at CppCon on 2018-09-26</span></a>
     </ol>
    <li>
     <a href="#samples"><span class="secno"></span> <span class="content">Appendix B: Sample code</span></a>
     <ol class="toc">
      <li><a href="#sample-uninit-relocate"><span class="secno"></span> <span class="content">Reference implementation of <code class="highlight"><c- n>relocate_at</c-></code> and <code class="highlight"><c- n>uninitialized_relocate</c-></code></span></a>
      <li><a href="#sample-conditional"><span class="secno"></span> <span class="content">Conditionally trivial relocation</span></a>
     </ol>
    <li>
     <a href="#non-trivial-samples"><span class="secno"></span> <span class="content">Appendix C: Examples of non-trivially relocatable class types</span></a>
     <ol class="toc">
      <li><a href="#non-trivial-sample-string"><span class="secno"></span> <span class="content">Class contains pointer to self</span></a>
      <li><a href="#non-trivial-sample-list"><span class="secno"></span> <span class="content">Allocated memory contains pointer to self</span></a>
      <li><a href="#non-trivial-sample-offset-ptr"><span class="secno"></span> <span class="content">Class invariant depends on <code class="highlight"><c- k>this</c-></code></span></a>
      <li><a href="#non-trivial-sample-registry"><span class="secno"></span> <span class="content">Program invariant depends on <code class="highlight"><c- k>this</c-></code></span></a>
      <li><a href="#non-trivial-sample-polymorphic"><span class="secno"></span> <span class="content">Polymorphic downcast effectively relies on offset-into-self</span></a>
     </ol>
    <li><a href="#implementation"><span class="secno"></span> <span class="content">Appendix D: Implementation experience</span></a>
    <li>
     <a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
     </ol>
    <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="changelog"><span class="secno">1. </span><span class="content">Changelog</span><a class="self-link" href="#changelog"></a></h2>
   <ul>
    <li data-md>
     <p>R5 (post-Prague):</p>
     <ul>
      <li data-md>
       <p>Polymorphic types (those with any vptr at all) inhibit "natural" trivial relocatability.
    David Stone gave the motivating example. See <a href="#non-trivial-sample-polymorphic">Polymorphic downcast effectively relies on offset-into-self</a>.</p>
      <li data-md>
       <p>Updated <code class="highlight"><c- n>concept</c-> <c- n>relocatable</c-></code>. Added semantic requirements on assignment and some discussion
    of the issue with <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code>.</p>
      <li data-md>
       <p>Added many direct links to sections of <a href="https://www.youtube.com/watch?v=SGdfPextuAU">my C++Now 2019 talk</a> covering particular motivations, design decisions, and implementation details.</p>
     </ul>
    <li data-md>
     <p>R3 (post-Kona):</p>
     <ul>
      <li data-md>
       <p>User-provided copy/move assignment operators inhibit "natural" trivial relocatability, just like
    user-provided move constructors and destructors. This is intended to permit us
    to optimize <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code>.</p>
      <li data-md>
       <p>User-provided copy constructors inhibit "natural" trivial relocatability, just like
    user-provided move constructors and destructors.</p>
      <li data-md>
       <p>Adopted <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code>. The attribute-argument is optional.</p>
      <li data-md>
       <p>Added <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>source</c-><c- p>,</c-> <c- n>dest</c-><c- p>)</c-></code>. Note that this is <em>not</em> a customization point.</p>
      <li data-md>
       <p>Removed the core-language blanket wording that permitted "the implementation" to eliminate
    moves and destroys of trivially relocatable types. Instead, the existence of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>relocate_at</c-></code> and handwaviness of e.g. <a href="http://eel.is/c++draft/vector#capacity-4"> [vector.capacity</a>] combine to strongly imply
    (but still not to mandate) that library vendors will use <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>relocate_at</c-></code> wherever
    it helps with performance. We no longer propose to permit eliminating
    moves and destroys in e.g. <code class="highlight"><c- k>return</c-></code> statements, except as already permitted under the as-if rule.</p>
     </ul>
   </ul>
   <h2 class="heading settled" data-level="2" id="intro"><span class="secno">2. </span><span class="content">Introduction and motivation</span><a class="self-link" href="#intro"></a></h2>
   <p>C++17 knows the verbs "move," "copy," "destroy," and "swap," where "swap" is a higher-level operation
composed of several lower-level operations. To this list we propose to add the verb "relocate,"
which is a higher-level operation composed of exactly two lower-level operations.
Given an object type <code class="highlight"><c- n>T</c-></code> and memory addresses <code class="highlight"><c- n>src</c-></code> and <code class="highlight"><c- n>dst</c-></code>,
the phrase "<b><i>relocate</i></b> a <code class="highlight"><c- n>T</c-></code> from <code class="highlight"><c- n>src</c-></code> to <code class="highlight"><c- n>dst</c-></code>" means no more and no
less than "<em>move-construct</em> <code class="highlight"><c- n>dst</c-></code> from <code class="highlight"><c- n>src</c-></code>, and then immediately <em>destroy</em> the object at <code class="highlight"><c- n>src</c-></code>."</p>
   <p>Any type which is both move-constructible and destructible is <b><i>relocatable</i></b>.
The notion can be modified by adverbs: we say that a type
is <b><i>nothrow relocatable</i></b> if its relocation operation is noexcept, and we say that a type
is <b><i><a data-link-type="abstract-op" href="#abstract-opdef-trivially-relocatable" id="ref-for-abstract-opdef-trivially-relocatable">trivially relocatable</a></i></b> if its relocation operation is trivial (which,
just like trivial move-construction and trivial copy-construction, means
"tantamount to <code class="highlight"><c- n>memcpy</c-></code>").</p>
   <p>In practice, almost all relocatable types are trivially relocatable: <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code>, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>string</c-></code>. Non-trivially relocatable types
exist but are rare; one example is <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>list</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code>. See <a href="#non-trivial-samples">Appendix C: Examples of non-trivially relocatable class types</a>.</p>
   <p>P1144 provides a way for the programmer
to warrant to the compiler that a resource-managing type is trivially relocatable,
and provides an algorithm by which the compiler can recursively <em>infer</em> that a Rule-of-Zero type
is trivially relocatable.</p>
   <p>The most important thing about P1144 relocation is that it is backward compatible and does not
break either API or ABI. My intention is simply to legalize the well-understood tricks
that every industry codebase is already doing in practice (see <a data-link-type="biblio" href="#biblio-bsl">[BSL]</a>, <a data-link-type="biblio" href="#biblio-eastl">[EASTL]</a>, <a data-link-type="biblio" href="#biblio-folly">[Folly]</a>).
P1144 is not intended to change the behavior of any existing source code (except to speed it up).
P1144 is not intended to require any major work from standard library vendors.</p>
   <p>As observed in <a data-link-type="biblio" href="#biblio-cppchat">[CppChat]</a> (<a href="https://www.youtube.com/watch?v=8u5Qi4FgTP8&amp;t=21m57s">@21:57</a>):
Just as with C++11 move semantics, you can write benchmarks to show whatever speedup you like.
The more complicated your types' move-constructors and destructors, the more time you save
by eliminating calls to them.</p>
   <h3 class="heading settled" data-level="2.1" id="applications"><span class="secno">2.1. </span><span class="content">Optimizations enabled by trivial relocatability</span><a class="self-link" href="#applications"></a></h3>
   <h4 class="heading settled" data-level="2.1.1" id="benefit-resize"><span class="secno">2.1.1. </span><span class="content">Vector resize</span><a class="self-link" href="#benefit-resize"></a></h4>
   <p>If we have a reliable way of detecting "trivial relocatability,"
we can optimize any routine that performs the moral equivalent of <code class="highlight"><c- n>realloc</c-></code>, including</p>
<pre class="language-c++ highlight">    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>::</c-><c- n>resize</c->
    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>::</c-><c- n>reserve</c->
    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>::</c-><c- n>emplace_back</c->
    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>::</c-><c- n>push_back</c->
</pre>
   <p><a data-link-type="biblio" href="#biblio-bench">[Bench]</a> (presented at C++Now 2018) shows a 3x speedup on <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>>::</c-><c- n>resize</c-></code>. <a href="https://www.reddit.com/r/cpp/comments/9wj4vt/trivially_relocatable_in_san_diego_call_for/e9p76i4/">This Reddit thread</a> demonstrates a similar 3x speedup using the online tool Quick-Bench.</p>
   <h4 class="heading settled" data-level="2.1.2" id="benefit-swap"><span class="secno">2.1.2. </span><span class="content">Swap</span><a class="self-link" href="#benefit-swap"></a></h4>
   <p>Given a reliable way of detecting trivial relocatability,
we can optimize any routine that uses the moral equivalent of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>swap</c-></code>, such as</p>
<pre class="language-c++ highlight">    <c- n>std</c-><c- o>::</c-><c- n>swap</c->
    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>::</c-><c- n>insert</c->
</pre>
   <p>Optimizing <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>swap</c-></code> produces massive code-size improvements for all swap-based
algorithms, including <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>sort</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>rotate</c-></code>. See <a href="https://www.youtube.com/watch?v=SGdfPextuAU&amp;t=19m56s">@19:56–21:22</a> in my C++Now 2019 talk.</p>
   <p>However, see <a href="#pmr-concerns">§ 6.7 Confusing interactions with std::pmr and vector::insert</a> for further discussion of <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code>.</p>
   <h4 class="heading settled" data-level="2.1.3" id="benefit-type-erasure"><span class="secno">2.1.3. </span><span class="content">More efficient small-buffer type-erasure</span><a class="self-link" href="#benefit-type-erasure"></a></h4>
   <p>Given a reliable way of detecting trivial relocatability,
we can de-duplicate the code generated by small-buffer-optimized (SBO) type-erasing wrappers
such as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>function</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>any</c-></code>.
For these types, a <em>move</em> of the wrapper object is implemented in terms of a <em>relocation</em> of the contained object. (See for example <a data-link-type="biblio" href="#biblio-libcxxany">libc++'s std::any</a>,
where the function that performs the relocation operation is confusingly named <code class="highlight"><c- n>__move</c-></code>.)
In general, the <em>relocate</em> operation for a contained type <code class="highlight"><c- n>C</c-></code> must be uniquely codegenned for each
different <code class="highlight"><c- n>C</c-></code>, leading to code bloat. But a single instantiation suffices to relocate every <em>trivially</em> relocatable <code class="highlight"><c- n>C</c-></code> in the program. A smaller number of instantiations means faster compile times,
a smaller text section, and "hotter" code (because a relatively higher proportion of your
code now fits in icache).</p>
   <h4 class="heading settled" data-level="2.1.4" id="benefit-fixed-capacity"><span class="secno">2.1.4. </span><span class="content">More efficient fixed-capacity containers</span><a class="self-link" href="#benefit-fixed-capacity"></a></h4>
   <p>Given a reliable way of detecting trivial relocatability,
we can optimize the move-constructor of <code class="highlight"><c- n>fixed_capacity_vector</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-><c- n>N</c-><c- o>></c-></code>,
which can be implemented naïvely as an element-by-element <em>move</em> (leaving the source vector’s elements in their moved-from state),
or can be implemented efficiently as an element-by-element <em>relocate</em> (leaving the source vector empty).</p>
   <p>For a detailed analysis of this case, see <a data-link-type="biblio" href="#biblio-fixedcapacityvector">[FixedCapacityVector]</a>.</p>
   <p class="note" role="note"><span>Note:</span> <code class="highlight"><c- n>boost</c-><c- o>::</c-><c- n>container</c-><c- o>::</c-><c- n>static_vector</c-><c- o>&lt;</c-><c- n>R</c-><c- p>,</c-><c- n>N</c-><c- o>></c-></code> currently implements the
naïve element-by-element-move strategy.</p>
   <h4 class="heading settled" data-level="2.1.5" id="benefit-assertions"><span class="secno">2.1.5. </span><span class="content">Assertions, not assumptions</span><a class="self-link" href="#benefit-assertions"></a></h4>
   <p>Some concurrent data structures might reasonably assert the trivial relocatability of
their elements, just as they sometimes assert the stronger property of trivial <em>copyability</em> today.</p>
   <h3 class="heading settled" data-level="2.2" id="doing-it-wrong"><span class="secno">2.2. </span><span class="content">The most important benefit</span><a class="self-link" href="#doing-it-wrong"></a></h3>
   <p>Many real-world codebases already contain templates which require
trivial relocatability of their template parameters, but currently have no way to <em>verify</em> trivial relocatability. For example, <a data-link-type="biblio" href="#biblio-folly">[Folly]</a> requires the programmer to warrant the trivial
relocatability of any type stored in a <code class="highlight"><c- n>folly</c-><c- o>::</c-><c- n>fbvector</c-></code>:</p>
<pre class="language-c++ highlight">    <c- n>class</c-> <c- n>Widget</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>lst_</c-><c- p>;</c->
    <c- p>};</c->

    <c- n>folly</c-><c- o>::</c-><c- n>fbvector</c-><c- o>&lt;</c-><c- n>Widget</c-><c- o>></c-> <c- n>vec</c-><c- p>;</c->  <c- c1>// FAILS AT COMPILE TIME for lack of warrant</c->
</pre>
   <p>But this merely encourages the programmer to add the warrant and continue. An incorrect
warrant will be discovered only at runtime, via undefined behavior. See <a href="#non-trivial-sample-list">Allocated memory contains pointer to self</a>, <a data-link-type="biblio" href="#biblio-follyissue889">[FollyIssue889]</a>, and (most importantly) <a href="https://www.youtube.com/watch?v=SGdfPextuAU&amp;t=27m26s">@27:26–31:47</a> in my C++Now 2019 talk.</p>
<pre class="language-c++ highlight">    <c- n>class</c-> <c- n>Gadget</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>list</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>lst_</c-><c- p>;</c->
    <c- p>};</c->
    <c- c1>// sigh, add the warrant on autopilot</c->
    <c- n>template</c-><c- o>&lt;></c-> <c- k>struct</c-> <c- n>folly</c-><c- o>::</c-><c- n>IsRelocatable</c-><c- o>&lt;</c-><c- n>Gadget</c-><c- o>></c-> <c- o>:</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-> <c- p>{};</c->

    <c- n>folly</c-><c- o>::</c-><c- n>fbvector</c-><c- o>&lt;</c-><c- n>Gadget</c-><c- o>></c-> <c- n>vec</c-><c- p>;</c->  <c- c1>// CRASHES AT RUNTIME due to fraudulent warrant</c->
</pre>
   <p>If this proposal is adopted, then Folly can start using <code class="highlight"><c- k>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>)</c-></code> in the implementation of <code class="highlight"><c- n>fbvector</c-></code>, and the programmer can stop writing explicit warrants.
Finally, the programmer can start writing assertions of correctness, which aids maintainability and
can even find real bugs. <a href="https://p1144.godbolt.org/z/dax9BR">Example:</a></p>
<pre class="language-c++ highlight">    <c- n>class</c-> <c- n>Widget</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>lst_</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>Widget</c-><c- o>></c-><c- p>);</c->  <c- c1>// correctly SUCCEEDS</c->

    <c- n>class</c-> <c- n>Gadget</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>list</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>lst_</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>Gadget</c-><c- o>></c-><c- p>);</c->  <c- c1>// correctly ERRORS OUT</c->
</pre>
   <p>The improvement in user experience for real-world codebases (such as <a data-link-type="biblio" href="#biblio-folly">[Folly]</a>, <a data-link-type="biblio" href="#biblio-eastl">[EASTL]</a>, BDE, Qt, etc.)
is the most important benefit to be gained by this proposal.</p>
   <h2 class="heading settled" data-level="3" id="design-goals"><span class="secno">3. </span><span class="content">Design goals</span><a class="self-link" href="#design-goals"></a></h2>
   <p>Every C++ type already <em>is</em> or <em>is not</em> trivially relocatable. This proposal does not require any
library vendor to make any library type trivially relocatable. (We assume that quality implementations
will do so on their own.)</p>
   <p>The optimizations discussed above are purely in the domain of library writers. If you’re writing
a vector, and you detect that your element type <code class="highlight"><c- n>T</c-></code> is trivially relocatable, then
whether you do any special optimization in that case is up to you.
This proposal does not require any library vendor to guarantee that any particular optimization
happens. (But we assume that quality implementations will do so on their own.)</p>
   <p>What C++ lacks is a standard way for library writers to <em>detect</em> the (existing) trivial relocatability
of a type <code class="highlight"><c- n>T</c-></code>, so that they can reliably apply their (existing) optimizations.
All we really need is to add <em>detection</em>, and then all the optimizations described above will naturally
emerge without any further special effort by WG21.</p>
   <p>There are three kinds of object types that we want to make sure are correctly detected as
trivially relocatable. These three cases are important for improving the performance of
the standard library, and for improving the correctness of programs using libraries such as <a data-link-type="biblio" href="#biblio-folly">[Folly]</a>'s <code class="highlight"><c- n>fbvector</c-></code>.</p>
   <h3 class="heading settled" data-level="3.1" id="use1"><span class="secno">3.1. </span><span class="content">Standard library types such as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>string</c-></code></span><a class="self-link" href="#use1"></a></h3>
   <p>In order to optimize <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>>::</c-><c- n>resize</c-></code>, we must come up with a way to achieve</p>
<pre class="language-c++ highlight">    <c- cp>#include</c-> &lt;string>
    <c- n>static_assert</c-><c- p>(</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- o>>::</c-><c- n>value</c-><c- p>);</c->
</pre>
   This could be done unilaterally by the library vendor — via a non-standard attribute
(<code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>), or a member typedef with a reserved name,
or simply a vendor-provided specialization of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-></code>. 
   <p>That is, we can in principle solve §2.1 while confining our "magic" to the headers
of the implementation itself. The programmer doesn’t have to learn anything new, so far.</p>
   <h3 class="heading settled" data-level="3.2" id="use2"><span class="secno">3.2. </span><span class="content">Program-defined types that follow the Rule of Zero</span><a class="self-link" href="#use2"></a></h3>
   <p>In order to optimize the SBO <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>function</c-></code> in any meaningful sense,
we must come up with a way to achieve</p>
<pre class="language-c++ highlight">    <c- cp>#include</c-> &lt;string>
    <c- k>auto</c-> <c- n>lam2</c-> <c- o>=</c-> <c- p>[</c-><c- n>x</c-><c- o>=</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- p>(</c-><c- s>"hello"</c-><c- p>)]{};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>decltype</c-><c- p>(</c-><c- n>lam2</c-><c- p>)</c-> <c- o>>::</c-><c- n>value</c-><c- p>);</c->
</pre>
   Lambdas are not a special case in C++; they are simply class types with all their special members defaulted.
Therefore, presumably we should be able to use the same solution for lambdas as for 
<pre class="language-c++ highlight">    <c- cp>#include</c-> &lt;string>
    <c- k>struct</c-> <c- n>A</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- n>s</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>A</c-> <c- o>>::</c-><c- n>value</c-><c- p>);</c->
</pre>
   Here <code class="highlight"><c- k>struct</c-> <c- n>A</c-></code> follows the Rule of Zero: its move-constructor and destructor are both defaulted.
If they were also <em>trivial</em>, then we’d be done. In fact they are non-trivial; and yet, because the type’s
bases and members are all of trivially relocatable types, the type as a whole <em>is</em> trivially relocatable. 
   <p>§2.2 asks that we make the <code class="highlight"><c- k>static_assert</c-></code> succeed without breaking the "Rule of Zero."
We do not want to require the programmer to annotate <code class="highlight"><c- k>struct</c-> <c- n>A</c-></code> with a special attribute, or
a special member typedef, or anything like that. We want it to Just Work. Even for lambda types.
This is a much harder problem than §2.1; it requires standard support in the core language.
But it still does not require any new <em>syntax</em>.</p>
   <h3 class="heading settled" data-level="3.3" id="use3"><span class="secno">3.3. </span><span class="content">Program-defined types with non-defaulted special members</span><a class="self-link" href="#use3"></a></h3>
   <p>In order to optimize <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>boost</c-><c- o>::</c-><c- n>shared_ptr</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>>::</c-><c- n>resize</c-></code>,
we must come up with a way to achieve</p>
<pre class="language-c++ highlight">    <c- k>struct</c-> <c- n>B</c-> <c- p>{</c->
        <c- n>B</c-><c- p>(</c-><c- n>B</c-><c- o>&amp;&amp;</c-><c- p>);</c->  <c- c1>// non-trivial</c->
        <c- o>~</c-><c- n>B</c-><c- p>();</c->  <c- c1>// non-trivial</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>B</c-> <c- o>>::</c-><c- n>value</c-><c- p>);</c->
</pre>
   via some standard annotation applied to class type <code class="highlight"><c- n>B</c-></code> (which in this example is standing in for <code class="highlight"><c- n>boost</c-><c- o>::</c-><c- n>shared_ptr</c-></code>). 
   <p class="note" role="note"><span>Note:</span> We cannot possibly do it without annotation, because there exist
examples of types that look just like <code class="highlight"><c- n>B</c-></code> and <em>are</em> trivially relocatable (for example, <a data-link-type="biblio" href="#biblio-libstdcxxfunction">libstdc++'s std::function</a>) and there exist types that look just like <code class="highlight"><c- n>B</c-></code> and are <em>not</em> trivially relocatable (for example, <a data-link-type="biblio" href="#biblio-libcxxfunction">libc++'s std::function</a>).
The compiler cannot "crack open" the definitions of <code class="highlight"><c- n>B</c-><c- p>(</c-><c- n>B</c-><c- o>&amp;&amp;</c-><c- p>)</c-></code> and <code class="highlight"><c- o>~</c-><c- n>B</c-><c- p>()</c-></code> to see if
they combine to form a trivial operation:
the definitions of <code class="highlight"><c- n>B</c-><c- p>(</c-><c- n>B</c-><c- o>&amp;&amp;</c-><c- p>)</c-></code> and <code class="highlight"><c- o>~</c-><c- n>B</c-><c- p>()</c-></code> might not even be available in the current translation unit.
So, without some kind of opt-in annotation, we cannot achieve our goal.</p>
   <p>This use-case is the only one that requires us to design the "opt-in" syntax.
In <a href="#use1">§2.1</a>, any special syntax is hidden inside the
implementation’s own headers. In <a href="#use2">§2.2</a>, our design goal is to <em>avoid</em> special syntax.
In <a href="#use3">§2.3</a>, WG21 must actually design user-facing syntax.</p>
   <p>Therefore, I believe it would be acceptable to punt on §2.3 and come back to it later.
We say, "Sure, that would be nice, but there’s no syntax for it. Be glad that it works for
core-language and library types. Ask again in three years."  As long as we leave the design
space open, I believe we wouldn’t lose much by delaying a solution to §2.3.</p>
   <p>This paper does propose a standard syntax for §2.3 — an attribute — which in turn
provides a <em>simple and portable</em> way for library vendors to implement §2.1.</p>
   <h2 class="heading settled" data-level="4" id="proposal"><span class="secno">4. </span><span class="content">Proposed language and library features</span><a class="self-link" href="#proposal"></a></h2>
   <p>This paper proposes five separate additions to the C++ Standard. These additions introduce
"relocate" as a well-supported C++ notion on par with "swap," and furthermore, successfully
communicate trivial relocatability in each of the three use-cases above.</p>
   <ul>
    <li data-md>
     <p>New standard algorithms, including <code class="highlight"><c- n>relocate_at</c-><c- p>(</c-><c- n>source</c-><c- p>,</c-> <c- n>dest</c-><c- p>)</c-></code> and <code class="highlight"><c- n>uninitialized_relocate</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>,</c-> <c- n>d_first</c-><c- p>)</c-></code>,
in the <code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code> header.</p>
    <li data-md>
     <p>Additional type traits, <code class="highlight"><c- n>is_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> and <code class="highlight"><c- n>is_nothrow_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>,
in the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header.</p>
    <li data-md>
     <p>New type traits, including <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>, in the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header. This is the <em>detection</em> mechanism.</p>
    <li data-md>
     <p>A new core-language rule by which a class type’s "trivial relocatability"
is inherited according to the Rule of Zero.</p>
    <li data-md>
     <p>A new attribute, <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>, in the core language.
This is the <em>opt-in</em> mechanism for program-defined types.</p>
   </ul>
   <p>These five bullet points are severable to some degree. For example, if the <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute (point 5) is adopted, library vendors will certainly use it in their implementations;
but if the attribute is rejected, library vendors could still indicate the trivial relocatability
of certain standard library types by providing library specializations of <code class="highlight"><c- n>is_trivially_relocatable</c-></code> (point 3).</p>
   <p>Points 1 and 2 are completely severable from points 3, 4, and 5;
but we believe these algorithms should be provided for symmetry with the
other uninitialized-memory algorithms in the <code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code> header
(e.g. <code class="highlight"><c- n>uninitialized_move</c-></code>)
and the other trios of type-traits in the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header
(e.g. <code class="highlight"><c- n>is_destructible</c-></code>, <code class="highlight"><c- n>is_nothrow_destructible</c-></code>, <code class="highlight"><c- n>is_trivially_destructible</c-></code>). I do not expect these templates to be frequently useful,
but I believe they should be provided, so as not to surprise the programmer
by their absence.</p>
   <p>Points 3 and 4 together motivate point 5. In order to achieve the goal of <a href="#use2">§ 3.2 Program-defined types that follow the Rule of Zero</a>,
we <em>must</em> define a core-language mechanism by which we can "inherit" trivial relocatability.
This is especially important for the template case.</p>
<pre class="language-c++ highlight">    <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
    <c- k>struct</c-> <c- n>D</c-> <c- p>{</c->
        <c- n>T</c-> <c- n>t</c-><c- p>;</c->
    <c- p>};</c->

    <c- c1>// class C comes in from outside, already marked, via whatever mechanism</c->
    <c- n>constexpr</c-> <c- b>bool</c-> <c- n>c</c-> <c- o>=</c-> <c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>C</c-> <c- o>>::</c-><c- n>value</c-><c- p>;</c->
    <c- n>constexpr</c-> <c- b>bool</c-> <c- n>dc</c-> <c- o>=</c-> <c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>D</c-><c- o>&lt;</c-><c- n>C</c-><c- o>></c-> <c- o>>::</c-><c- n>value</c-><c- p>;</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>dc</c-> <c- o>==</c-> <c- n>c</c-><c- p>);</c->
</pre>
   We strongly believe that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> should be just a plain old
class template, exactly like <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_destructible</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> and so on.
The core language <em><a data-link-type="biblio" href="#biblio-contra">should not know or care</a></em> that the class template <code class="highlight"><c- n>is_trivially_relocatable</c-></code> exists, any more than it knows that the class template <code class="highlight"><c- n>is_trivially_destructible</c-></code> exists. 
   <p>We expect that the library vendor will implement <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable</c-></code>,
just like <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_trivially_destructible</c-></code>, in terms of a non-standard compiler
builtin whose natural spelling is <code class="highlight"><c- n>__is_trivially_relocatable</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-></code>.
This builtin has been implemented in my fork of Clang; see <a data-link-type="biblio" href="#biblio-d50119">[D50119]</a>.
The compiler computes the value of <code class="highlight"><c- n>__is_trivially_relocatable</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-></code> by inspecting the
definition of <code class="highlight"><c- n>T</c-></code> (and the definitions of its base classes and members, recursively).
This recursive process "bottoms out" at primitive types, or at any type with a user-provided
move or destroy operation. For safety, classes with user-provided move or destroy operations
(e.g. <a href="#non-trivial-samples">Appendix C: Examples of non-trivially relocatable class types</a>) must be assumed <em>not</em> to be trivially relocatable. To achieve the goal
of <a href="#use3">§ 3.3 Program-defined types with non-defaulted special members</a>, we must provide a way that such a class can "opt in" and warrant to the
implementation that it is in fact trivially relocatable (despite being non-trivially
move-constructible and/or non-trivially destructible).</p>
   <p>In point 5 we propose that the opt-in mechanism should be an attribute. The programmer
of a trivially relocatable but non-trivially destructible class <code class="highlight"><c- n>C</c-></code> will mark it for
the compiler using the attribute:</p>
<pre class="language-c++ highlight">    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-> <c- n>C</c-> <c- p>{</c->
        <c- n>C</c-><c- p>(</c-><c- n>C</c-><c- o>&amp;&amp;</c-><c- p>);</c->  <c- c1>// defined elsewhere</c->
        <c- o>~</c-><c- n>C</c-><c- p>();</c-> <c- c1>// defined elsewhere</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-> <c- n>C</c-> <c- o>>::</c-><c- n>value</c-><c- p>);</c->
</pre>
   The attribute overrides the compiler’s usual computation. 
   <p>An example of a "conditionally" trivially relocatable class is shown in <a href="#sample-conditional">Conditionally trivial relocation</a>.</p>
   <p>The attribute is severable; WG21 could adopt all the rest of this proposal and
leave vendors to implement <code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>, <code class="highlight"><c- p>[[</c-><c- n>gnu</c-><c- o>::</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>, etc.,
as non-standard extension mechanisms.
In that case, we would strike <a href="#wording-attribute">§5.6</a> and one bullet point from <a href="#wording-inheritance">§5.5</a>;
the rest of this proposal would remain exactly the same.</p>
   <h2 class="heading settled" data-level="5" id="wording"><span class="secno">5. </span><span class="content">Proposed wording for C++2b</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-n4800">WG21 draft N4800</a>.</p>
   <h3 class="heading settled" data-level="5.1" id="wording-operation"><span class="secno">5.1. </span><span class="content">Relocation operation</span><a class="self-link" href="#wording-operation"></a></h3>
   <p>Add a new section in <a href="http://eel.is/c++draft/definitions">[definitions]</a>:</p>
   <p class="issue" id="issue-75ffe201"><a class="self-link" href="#issue-75ffe201"></a> [definitions] is probably the wrong place for the core-language definition of "relocation operation"</p>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <dl><dt data-md><dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export id="abstract-opdef-relocation-operation">relocation operation</dfn></dt><dd data-md><p>the homogeneous binary operation performed by <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>relocate_at</c-></code>, consisting of a move-construction immediately followed by a destruction of the source object</p> </dd></dl> </small>
   </blockquote>
   <p class="issue" id="issue-7c86f5f7"><a class="self-link" href="#issue-7c86f5f7"></a> this definition of "relocation operation" is not good</p>
   <h3 class="heading settled" data-level="5.2" id="wording-relocate-at"><span class="secno">5.2. </span><span class="content">Algorithm <code class="highlight"><c- n>relocate_at</c-></code></span><a class="self-link" href="#wording-relocate-at"></a></h3>
   <p>Add a new section after <a href="http://eel.is/c++draft/uninitialized.move">[uninitialized.move]</a>:</p>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
<c- n>T</c-> <c- o>*</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-> <c- n>source</c-><c- p>,</c-> <c- n>T</c-><c- o>*</c-> <c- n>dest</c-><c- p>);</c->

<c- k>namespace</c-> <c- n>ranges</c-> <c- p>{</c->
  <c- k>template</c-><c- o>&lt;</c-><c- n>relocatable</c-> <c- n>T</c-><c- o>></c->
  <c- n>T</c-> <c- o>*</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-> <c- n>source</c-><c- p>,</c-> <c- n>T</c-><c- o>*</c-> <c- n>dest</c-><c- p>);</c->
<c- p>}</c->
</pre> <p><em>Mandates:</em> <code class="highlight"><c- n>T</c-></code> shall be a complete non-array object type.</p> <p><em>Effects:</em> Equivalent to:</p> <pre class="highlight"><c- n>uninitialized_move</c-><c- p>(</c-><c- n>dest</c-><c- p>,</c-> <c- n>dest</c-> <c- o>+</c-> <c- mi>1</c-><c- p>,</c-> <c- n>source</c-><c- p>);</c->
<c- n>destroy_at</c-><c- p>(</c-><c- n>source</c-><c- p>);</c->
<c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>launder</c-><c- p>(</c-><c- n>dest</c-><c- p>);</c->
</pre><p>except that if <code class="highlight"><c- n>T</c-></code> is trivially relocatable <i>[basic.types]</i>, side effects
associated with the relocation of the object’s value might not happen.</p> </small>
   </blockquote>
   <p class="note" role="note"><span>Note:</span> The "as-if-by-memcpy" codepath hidden inside <code class="highlight"><c- n>relocate_at</c-></code> cannot be implemented by
literally <code class="highlight"><c- n>memcpy</c-></code> (at least not without undefined behavior).
At Kona, EWG discussion of Richard Smith’s <a data-link-type="biblio" href="#biblio-p0593r3">[P0593R3]</a> suggests to me, and Richard
confirmed, that a typical library vendor <em>could</em> implement this codepath
by a call to a hypothetical <code class="highlight"><c- n>out_of_line_memcpy</c-></code> function whose
implementation is invisible to the compiler’s optimizer.
See <a href="https://www.youtube.com/watch?v=SGdfPextuAU&amp;t=45m23s">@45:23–48:39</a> in my C++Now 2019 talk.</p>
   <h3 class="heading settled" data-level="5.3" id="wording-uninit-relocate"><span class="secno">5.3. </span><span class="content">Algorithm <code class="highlight"><c- n>uninitialized_relocate</c-></code></span><a class="self-link" href="#wording-uninit-relocate"></a></h3>
   <p>Add a new section after <a href="http://eel.is/c++draft/uninitialized.move">[uninitialized.move]</a>:</p>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>ForwardIterator1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>ForwardIterator2</c-><c- o>></c->
<c- n>ForwardIterator2</c-> <c- n>uninitialized_relocate</c-><c- p>(</c-><c- n>ForwardIterator1</c-> <c- n>first</c-><c- p>,</c-> <c- n>ForwardIterator1</c-> <c- n>last</c-><c- p>,</c->
                                        <c- n>ForwardIterator2</c-> <c- n>result</c-><c- p>);</c->
</pre> <p><em>Effects:</em> Equivalent to:</p> <pre class="highlight"><c- n>result</c-> <c- o>=</c-> <c- n>uninitialized_move</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>,</c-> <c- n>result</c-><c- p>);</c->
<c- n>destroy</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>);</c->
<c- k>return</c-> <c- n>result</c-><c- p>;</c->
</pre><p>except that if the iterators' common value type is trivially relocatable, side effects
associated with the relocation of the object’s value might not happen.</p> <p><em>Remarks:</em> If an exception is thrown, some objects in the range <code class="highlight"><c- p>[</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>)</c-></code> are left in a valid but unspecified state.</p> </small>
   </blockquote>
   <p class="note" role="note"><span>Note:</span> The "Remark" implies that <code class="highlight"><c- n>uninitialized_relocate</c-></code> has a <code class="highlight"><c- k>catch</c-></code>-and-cleanup clause
similar to <code class="highlight"><c- n>uninitialized_move</c-></code>: if an exception is thrown, the whole destination range
is destroyed before the exception is propagated. If <code class="highlight"><c- n>T</c-></code> is non-trivially relocatable and <code class="highlight"><c- n>T</c-></code>'s move-constructor might throw, then the implementation must be "move-in-a-loop
followed by destroy-in-a-loop." See the implementation in <a href="#samples">Appendix B: Sample code</a>.</p>
   <p class="note" role="note"><span>Note:</span> We are guided by <a data-link-type="biblio" href="#biblio-p0884r0">[P0884R0]</a> to make <code class="highlight"><c- n>uninitialized_relocate</c-></code> unconditionally <code class="highlight"><c- k>noexcept</c-><c- p>(</c->false<c- p>)</c-></code>.
This is consistent with <code class="highlight"><c- n>uninitialized_move</c-></code> and <code class="highlight"><c- n>destroy_at</c-></code>, both of which are unconditionally <code class="highlight"><c- k>noexcept</c-><c- p>(</c->false<c- p>)</c-></code>.</p>
   <h3 class="heading settled" data-level="5.4" id="wording-uninit-relocate-n"><span class="secno">5.4. </span><span class="content">Algorithm <code class="highlight"><c- n>uninitialized_relocate_n</c-></code></span><a class="self-link" href="#wording-uninit-relocate-n"></a></h3>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>ForwardIterator1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Size</c-><c- p>,</c-> <c- k>class</c-> <c- nc>ForwardIterator2</c-><c- o>></c->
  <c- n>pair</c-><c- o>&lt;</c-><c- n>ForwardIterator1</c-><c- p>,</c-> <c- n>ForwardIterator2</c-><c- o>></c->
    <c- n>uninitialized_relocate_n</c-><c- p>(</c-><c- n>ForwardIterator1</c-> <c- n>first</c-><c- p>,</c-> <c- n>Size</c-> <c- n>n</c-><c- p>,</c-> <c- n>ForwardIterator2</c-> <c- n>result</c-><c- p>);</c->
</pre> <p><em>Effects:</em> Equivalent to:</p> <pre class="highlight"><c- k>auto</c-> <c- n>pair</c-> <c- o>=</c-> <c- n>uninitialized_move_n</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>n</c-><c- p>,</c-> <c- n>result</c-><c- p>);</c->
<c- n>destroy_n</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>n</c-><c- p>);</c->
<c- k>return</c-> <c- n>pair</c-><c- p>;</c->
</pre><p>except that if the iterators' common value type is trivially relocatable, side effects
associated with the relocation of the object’s value might not happen.</p> <p><em>Remarks:</em> If an exception is thrown, some objects in the range <code class="highlight"><c- p>[</c-><c- n>first</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>next</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-><c- n>n</c-><c- p>))</c-></code> are left in a valid but unspecified state.</p> </small>
   </blockquote>
   <h3 class="heading settled" data-level="5.5" id="wording-inheritance"><span class="secno">5.5. </span><span class="content">Trivially relocatable type</span><a class="self-link" href="#wording-inheritance"></a></h3>
   <p>Add a new section in <a href="http://eel.is/c++draft/basic.types">[basic.types]</a>:</p>
   <p><small></small></p>
   <blockquote><small> A move-constructible, destructible object type <code class="highlight"><c- n>T</c-></code> is a <dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export id="abstract-opdef-trivially-relocatable">trivially relocatable</dfn> type if it is:<p></p> <ul><li data-md><p>a trivially copyable type, or</p> </li><li data-md><p>an array of trivially relocatable type, or</p> </li><li data-md><p>a (possibly cv-qualified) class type declared with a <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute
with value <code class="highlight">true</code>, or</p> </li><li data-md><p>a (possibly cv-qualified) class type which:</p> <ul><li data-md><p>has no user-provided move constructors or move assignment operators,</p> </li><li data-md><p>has no user-provided copy constructors or copy assignment operators,</p> </li><li data-md><p>has no user-provided destructors,</p> </li><li data-md><p>has no virtual member functions,</p> </li><li data-md><p>has no virtual base classes,</p> </li><li data-md><p>all of whose members are either of reference type or of trivially relocatable type, and</p> </li><li data-md><p>all of whose base classes are trivially relocatable.</p> </li></ul></li></ul> <p>[<em>Note:</em> For a trivially relocatable type, the <a data-link-type="abstract-op" href="#abstract-opdef-relocation-operation" id="ref-for-abstract-opdef-relocation-operation">relocation operation</a> (such as the relocation operations
performed by the library functions <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>swap</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>::</c-><c- n>resize</c-></code>) is tantamount
to a simple copy of the underlying bytes. <em>—end note</em>]</p> <p>[<em>Note:</em> It is intended that most standard library types be trivially relocatable types. <em>—end note</em>]</p> </small></blockquote>
   <p class="note" role="note"><span>Note:</span> As of P1144R5, polymorphic types are not "naturally" trivially relocatable. See <a href="#non-trivial-sample-polymorphic">Appendix C, example 5</a>.</p>
   <p class="note" role="note"><span>Note:</span> A class type declared <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c->false<c- p>)]]</c-></code> may still be trivially relocatable,
if it satisfies the criteria above. For example, it is impossible to create a trivially copyable type
which is not also trivially relocatable.</p>
   <p class="note" role="note"><span>Note:</span> There is no special treatment for volatile subobjects (see <a data-link-type="biblio" href="#biblio-subobjects">[Subobjects]</a>)
nor for possibly overlapping subobjects (see <a data-link-type="biblio" href="#biblio-subobjects">[Subobjects]</a>).</p>
   <p class="issue" id="issue-3121e1d2"><a class="self-link" href="#issue-3121e1d2"></a> The relevant move constructor, copy constructor, and/or destructor must be public and unambiguous.
We imply this via the words "A move-constructible, destructible object type". However, "move-constructible"
and "destructible" are library concepts, not core language concepts, so it is inappropriate
to use them here.</p>
   <div class="issue" id="issue-7b712591">
    <a class="self-link" href="#issue-7b712591"></a> Consider the following test cases—<wbr><small> <pre class="language-c++ highlight">    <c- k>struct</c-> <c- n>A</c-> <c- p>{</c->
        <c- k>struct</c-> <c- n>MA</c-> <c- p>{</c->
            <c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;</c-><c- p>);</c->
            <c- n>MA</c-><c- p>(</c-><c- k>const</c-> <c- n>MA</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
            <c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
        <c- p>};</c->
        <c- n>mutable</c-> <c- n>MA</c-> <c- n>ma</c-><c- p>;</c->
        <c- n>A</c-><c- p>(</c-><c- k>const</c-> <c- n>A</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>A</c-><c- o>></c-><c- p>);</c->

    <c- k>struct</c-> <c- n>B</c-> <c- p>{</c->
        <c- k>struct</c-> <c- n>MB</c-> <c- p>{</c->
            <c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- k>volatile</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>);</c->
            <c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
            <c- n>MB</c-><c- p>(</c-><c- n>MB</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
        <c- p>};</c->
        <c- k>volatile</c-> <c- n>MB</c-> <c- n>mb</c-><c- p>;</c->
        <c- n>B</c-><c- p>(</c-><c- k>const</c-> <c- n>B</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>B</c-><c- o>></c-><c- p>);</c->

    <c- k>struct</c-> <c- n>H</c-> <c- p>{</c->
        <c- n>H</c-><c- p>(</c-><c- n>H</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-> <c- n>I</c-> <c- p>{</c->
        <c- n>I</c-><c- p>(</c-><c- n>I</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- n>template</c-><c- o>&lt;</c-><c- b>bool</c-> <c- n>Cond</c-><c- o>></c->
    <c- k>struct</c-> <c- nl>J</c-> <c- p>:</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>Cond</c-><c- p>,</c-> <c- n>H</c-><c- p>,</c-> <c- n>I</c-><c- o>></c-> <c- p>{</c->
        <c- n>J</c-><c- p>(</c-><c- k>const</c-> <c- n>J</c-><c- o>&amp;</c-><c- p>);</c->
        <c- n>J</c-><c- p>(</c-><c- n>J</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->false<c- o>>></c-><c- p>);</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->true<c- o>>></c-><c- p>);</c->
</pre></small> We <em>must</em> find a rule that makes neither <code class="highlight"><c- n>A</c-></code> nor <code class="highlight"><c- n>B</c-></code> trivially relocatable,
because the move-construction <code class="highlight"><c- n>A</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>a</c-><c- p>))</c-></code> invokes user-provided copy constructor <code class="highlight"><c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;</c-><c- p>)</c-></code> and the move-construction <code class="highlight"><c- n>B</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>b</c-><c- p>))</c-></code> invokes user-provided copy constructor <code class="highlight"><c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- k>volatile</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>)</c-></code>.
Prior to P1144R3, the rule was that <code class="highlight"><c- k>mutable</c-></code> and <code class="highlight"><c- k>volatile</c-></code> data members
inhibited "natural" trivial relocatability. As of P1144R3, the rule is that
any user-provided copy constructor inhibits trivial relocatability (even in the
presence of a defaulted move constructor). 
    <p>In P1144R2, I tried to find a rule that makes <code class="highlight"><c- n>J</c-></code> trivially relocatable,
because the <code class="highlight"><c- nl>J</c-> <c- p>:</c-> <c- n>I</c-></code> pattern was used to implement "conditionally trivial relocatability"
for all allocator-aware containers in my libc++ reference implementation.
However, this paper adopts the <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code> syntax, which
means that we don’t need to care about <code class="highlight"><c- nl>J</c-> <c- p>:</c-> <c- n>I</c-></code> anymore. The new way to write <code class="highlight"><c- n>J</c-></code> is simply <small></small></p>
    <small> <pre class="highlight">    <c- k>template</c-><c- o>&lt;</c-><c- b>bool</c-> <c- n>Cond</c-><c- o>></c->
    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- o>!</c-><c- n>Cond</c-><c- p>)]]</c-> <c- n>J</c-> <c- p>{</c->
        <c- n>J</c-><c- p>(</c-><c- n>J</c-><c- o>&amp;&amp;</c-><c- p>);</c->
        <c- n>J</c-><c- p>(</c-><c- k>const</c-> <c- n>J</c-><c- o>&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->false<c- o>>></c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->true<c- o>>></c-><c- p>);</c->
</pre></small> 
   </div>
   <h3 class="heading settled" data-level="5.6" id="wording-attribute"><span class="secno">5.6. </span><span class="content"><code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute</span><a class="self-link" href="#wording-attribute"></a></h3>
   <p>Add a new section after <a href="http://eel.is/c++draft/dcl.attr.nouniqueaddr">[dcl.attr.nouniqueattr]</a>:</p>
   <p><small></small></p>
   <blockquote><small> The <em>attribute-token</em> <code class="highlight"><c- n>trivially_relocatable</c-></code> specifies that a class type’s relocation operation has no
visible side-effects other than a copy of the underlying bytes, as if by the library function <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>memcpy</c-></code>.
It may be applied to the definition of a class. It shall appear at most once in each <em>attribute-list</em>.
An <em>attribute-argument-clause</em> may be present and, if present, shall have the form<p></p> <pre class="highlight">    <c- p>(</c-> <c- n>constant</c-><c- o>-</c-><c- n>expression</c-> <c- p>)</c->
</pre>The <em>constant-expression</em> shall be an integral constant expression of type <code class="highlight"><c- b>bool</c-></code>.
If no <em>attribute-argument-clause</em> is present, it has the same effect as an <em>attribute-argument-clause</em> of <code class="highlight"><c- p>(</c->true<c- p>)</c-></code>. <p>If any definition of a class type has a <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute with value <em>V</em>, then each
definition of the same class type shall have a <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute with value <em>V</em>.
No diagnostic is required if definitions in different translation units have
mismatched <code class="highlight"><c- n>trivially_relocatable</c-></code> attributes.</p> <p>If a type <code class="highlight"><c- n>T</c-></code> is declared with the <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute, and <code class="highlight"><c- n>T</c-></code> is either not move-constructible
or not destructible, the program is ill-formed.</p> <p>If a class type is declared with the <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute, and the program relies on
observable side-effects of relocation other than a copy of the underlying bytes, the behavior is undefined.</p> </small></blockquote>
   <p class="issue" id="issue-20b76dab"><a class="self-link" href="#issue-20b76dab"></a> "If a type <code class="highlight"><c- n>T</c-></code> is declared with the <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute, and <code class="highlight"><c- n>T</c-></code> is either not move-constructible
or not destructible, the program is ill-formed." We might want to replace this wording with
a mere "Note" <em>encouraging</em> implementations to diagnose.
See <a href="https://p1144.godbolt.org/z/ociAVX">this example</a> where a diagnostic might be unwanted.</p>
   <h3 class="heading settled" data-level="5.7" id="wording-traits"><span class="secno">5.7. </span><span class="content">Type traits <code class="highlight"><c- n>is_relocatable</c-></code> etc.</span><a class="self-link" href="#wording-traits"></a></h3>
   <p>Add new entries to Table 47 in <a href="http://eel.is/c++draft/meta.unary.prop">[meta.unary.prop]</a>:</p>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <table> <tbody><tr><th>Template</th><th>Condition</th><th>Preconditions</th></tr> <tr> <td><code class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- n>is_relocatable</c-><c- p>;</c-></code></td> <td><code class="highlight"><c- n>is_move_constructible_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is <code class="highlight">true</code> and <code class="highlight"><c- n>is_destructible_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is <code class="highlight">true</code></td> <td>T shall be a complete type, <i>cv</i> <code class="highlight"><c- b>void</c-></code>, or an array of unknown bound.</td> </tr> <tr> <td><code class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- n>is_nothrow_relocatable</c-><c- p>;</c-></code></td> <td><code class="highlight"><c- n>is_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is <code class="highlight">true</code> and both the indicated move-constructor and the destructor are known not to throw any exceptions.</td> <td>T shall be a complete type, <i>cv</i> <code class="highlight"><c- b>void</c-></code>, or an array of unknown bound.</td> </tr> <tr> <td><code class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- n>is_trivially_relocatable</c-><c- p>;</c-></code></td> <td><code class="highlight"><c- n>T</c-></code> is a <a data-link-type="abstract-op" href="#abstract-opdef-trivially-relocatable" id="ref-for-abstract-opdef-trivially-relocatable①">trivially relocatable</a> type.</td> <td>T shall be a complete type, <i>cv</i> <code class="highlight"><c- b>void</c-></code>, or an array of unknown bound.</td> </tr> </tbody></table> </small>
   </blockquote>
   <h3 class="heading settled" data-level="5.8" id="wording-concept"><span class="secno">5.8. </span><span class="content"><code class="highlight"><c- n>Relocatable</c-></code> concept</span><a class="self-link" href="#wording-concept"></a></h3>
   <p>Add a new section after <a href="http://eel.is/c++draft/concept.moveconstructible">[concept.moveconstructible]</a>:</p>
   <p><small></small></p>
   <blockquote>
    <p></p>
    <small> <pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- n>concept</c-> <c- n>relocatable</c-> <c- o>=</c-> <c- n>move_constructible</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
</pre> <p>If <code class="highlight"><c- n>T</c-></code> is an object type, then let <code class="highlight"><c- n>rv</c-></code> be an rvalue of type <code class="highlight"><c- n>T</c-></code>, <code class="highlight"><c- n>lv</c-></code> an lvalue of type <code class="highlight"><c- n>T</c-></code> equal to <code class="highlight"><c- n>rv</c-></code>,
and <code class="highlight"><c- n>u2</c-></code> a distinct object of type <code class="highlight"><c- n>T</c-></code> equal to <code class="highlight"><c- n>rv</c-></code>. <code class="highlight"><c- n>T</c-></code> models <code class="highlight"><c- n>relocatable</c-></code> only if</p> <ul><li data-md><p>After the definition <code class="highlight"><c- n>T</c-> <c- n>u</c-> <c- o>=</c-> <c- n>rv</c-><c- p>;</c-></code>, <code class="highlight"><c- n>u</c-></code> is equal to <code class="highlight"><c- n>u2</c-></code>.</p> </li><li data-md><p><code class="highlight"><c- n>T</c-><c- p>(</c-><c- n>rv</c-><c- p>)</c-></code> is equal to <code class="highlight"><c- n>u2</c-></code>.</p> </li><li data-md><p>If the expression <code class="highlight"><c- n>u2</c-> <c- o>=</c-> <c- n>rv</c-></code> is well-formed, then the expression has the same semantics as <code class="highlight"><c- n>u2</c-><c- p>.</c-><c- o>~</c-><c- n>T</c-><c- p>();</c-> <c- o>::</c-><c- k>new</c-> <c- p>((</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-><c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- n>u2</c-><c- p>))</c-> <c- n>T</c-><c- p>(</c-><c- n>rv</c-><c- p>);</c-></code></p> </li><li data-md><p>If the definition <code class="highlight"><c- n>T</c-> <c- n>u</c-> <c- o>=</c-> <c- n>lv</c-><c- p>;</c-></code> is well-formed, then after the definition <code class="highlight"><c- n>u</c-></code> is equal to <code class="highlight"><c- n>u2</c-></code>.</p> </li><li data-md><p>If the expression <code class="highlight"><c- n>T</c-><c- p>(</c-><c- n>lv</c-><c- p>)</c-></code> is well-formed, then the expression’s result is equal to <code class="highlight"><c- n>u2</c-></code>.</p> </li><li data-md><p>If the expression <code class="highlight"><c- n>u2</c-> <c- o>=</c-> <c- n>lv</c-></code> is well-formed, then the expression has the same semantics as <code class="highlight"><c- n>u2</c-><c- p>.</c-><c- o>~</c-><c- n>T</c-><c- p>();</c-> <c- o>::</c-><c- k>new</c-> <c- p>((</c-><c- b>void</c-><c- o>*</c-><c- p>)</c-><c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- n>u2</c-><c- p>))</c-> <c- n>T</c-><c- p>(</c-><c- n>lv</c-><c- p>);</c-></code></p> </li></ul> </small>
   </blockquote>
   <p class="issue" id="issue-2fea1ba9"><a class="self-link" href="#issue-2fea1ba9"></a> The semantic requirements of this concept are poorly worded. We intend that a type may be relocatable
regardless of whether it is copy-constructible; but, if it is copy-constructible then copy-and-destroy
must have the same semantics as move-and-destroy. We intend that a type may be relocatable regardless of
whether it is assignable; but, if it is assignable then assignment must have the same semantics as
destroy-and-copy or destroy-and-move.</p>
   <p class="note" role="note"><span>Note:</span> The semantic requirements on assignment help us optimize <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code> and <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>erase</c-></code>.
The type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>forward_list</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> satisfies <code class="highlight"><c- n>relocatable</c-></code>, but it models <code class="highlight"><c- n>relocatable</c-></code> only if all relevant objects have equal allocators.</p>
   <p class="note" role="note"><span>Note:</span> I do not propose to add a concept named <code class="highlight"><c- n>trivially_relocatable</c-></code>.
There is currently no concept named <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>trivially_copy_constructible</c-></code> nor <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>trivial</c-></code>.</p>
   <h2 class="heading settled" data-level="6" id="alternatives"><span class="secno">6. </span><span class="content">Rationale and alternatives</span><a class="self-link" href="#alternatives"></a></h2>
   <h3 class="heading settled" data-level="6.1" id="destructive-move"><span class="secno">6.1. </span><span class="content">Why not destructive move?</span><a class="self-link" href="#destructive-move"></a></h3>
   <p><a href="http://wiki.edg.com/bin/view/Wg21sandiego2018/P1144R0">As discussed in EWGI at San Diego</a>,
this proposal does <em>not</em> give us a general user-provided "destructive move" facility.</p>
   <ul>
    <li data-md>
     <p>Denis Bider’s <a data-link-type="biblio" href="#biblio-p0023r0">[P0023R0]</a> and Pablo Halpern’s <a data-link-type="biblio" href="#biblio-n4158">[N4158]</a> went in that direction and did not succeed.
People have been chasing "destructive move" for decades; maybe it’s time to try something different.</p>
    <li data-md>
     <p>We get the performance benefit only when the library (e.g. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>::</c-><c- n>resize</c-></code>) can detect that
"relocate/destructive move" is tantamount to memcpy. If we permit a user-provided "destructive move"
operation, we must also design a way for the user to warrant that their "destructive move"
is tantamount to memcpy. No previous proposal has shown how to do this.</p>
    <li data-md>
     <p>P1144’s approach is explicitly based on existing industry practice: <a data-link-type="biblio" href="#biblio-folly">[Folly]</a>, <a data-link-type="biblio" href="#biblio-eastl">[EASTL]</a>,
and <a data-link-type="biblio" href="#biblio-bsl">[BSL]</a> all use this exact idea in practice and it seems to work for them.
Marc Glisse has been integrating the same idea into GNU libstdc++; see <a data-link-type="biblio" href="#biblio-deque">[Deque]</a>.
The term "relocation" is due to <a data-link-type="biblio" href="#biblio-eastl">[EASTL]</a> (<code class="highlight"><c- n>has_trivial_relocate</c-></code>) and <a data-link-type="biblio" href="#biblio-folly">[Folly]</a> (<code class="highlight"><c- n>IsRelocatable</c-></code>).
The same concept appears in pre-C++11 libraries under the name "movable":
Qt (<code class="highlight"><c- n>Q_MOVABLE_TYPE</c-></code>) and <a data-link-type="biblio" href="#biblio-bsl">[BSL]</a> (<code class="highlight"><c- n>IsBitwiseMoveable</c-></code>). P1144’s sole innovation is to
give a consistent set of core-language rules by which the compiler can deduce the
trivial relocatability of some class types which follow the Rule of Zero.</p>
   </ul>
   <h3 class="heading settled" data-level="6.2" id="bool-parameter"><span class="secno">6.2. </span><span class="content">Why <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code>?</span><a class="self-link" href="#bool-parameter"></a></h3>
   <p>It was suggested by numerous reviewers that <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> should
take an optional boolean parameter, as in <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c->true<c- p>)]]</c-></code>.
This allows us to write complicated conditions directly inline, instead of using
metaprogramming to inherit the right behavior from a conditional base class.</p>
   <p>See <a href="#sample-conditional">Conditionally trivial relocation</a> for an example of how this can be used.</p>
   <p>There is no technical obstacle to adding an arbitrary C++ expression as the parameter to
an attribute. The grammar for balancing <code class="highlight"><c- p>[]</c-></code> and <code class="highlight"><c- p>()</c-></code> in attribute parameters has been
there since C++11. There is already prior art for arbitrary expressions in attributes;
see <a href="https://clang.llvm.org/docs/AttributeReference.html#diagnose-if">Clang’s <code class="highlight"><c- p>[[</c-><c- n>diagnose_if</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code> attribute</a>. EWG has also previously considered an attribute <code class="highlight"><c- p>[[</c-><c- n>assume_aligned</c-><c- p>(</c-><c- n>expr</c-><c- p>)]]</c-></code>; it was rejected in favor of <a data-link-type="biblio" href="#biblio-p1007r3">[P1007R3]</a>'s non-attribute
approach, but not because of the <code class="highlight"><c- p>(</c-><c- n>expr</c-><c- p>)</c-></code> part specifically.</p>
   <p>The major downside I see to <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- n>expr</c-><c- p>)]]</c-></code> is that it could lead to
an arbitrarily complicated C++ expression appearing in an awkward position. But this
is better than having to do the metaprogramming tricks shown in <a href="#sample-conditional">Conditionally trivial relocation</a>.</p>
   <h3 class="heading settled" data-level="6.3" id="maybe-trivially-relocatable"><span class="secno">6.3. </span><span class="content">Attribute <code class="highlight"><c- p>[[</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code></span><a class="self-link" href="#maybe-trivially-relocatable"></a></h3>
   <p>The Clang patch currently available on Godbolt Compiler Explorer supports both <code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> and another attribute called <code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code>,
which John McCall requested that I explore.</p>
   <p>See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1144r4.html#maybe-trivially-relocatable">P1144R4 section 6.2</a> for discussion of the <code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code> attribute, including the reasons
I do not propose it for standardization.</p>
   <h3 class="heading settled" data-level="6.4" id="relocatable-list"><span class="secno">6.4. </span><span class="content">Should <code class="highlight"><c- n>relocate_at</c-></code> be a customization point?</span><a class="self-link" href="#relocatable-list"></a></h3>
   <p><b>No.</b> See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1144r2.html#relocatable-list">P1144R2 section 5.4</a> for discussion of this approach, which was taken by Pablo Halpern’s <a data-link-type="biblio" href="#biblio-n4158">[N4158]</a>.
See also
"<a href="https://quuxplusone.github.io/blog/2018/09/28/trivially-relocatable-vs-destructive-movable/">Trivially Relocatable versus Destructive Movable</a>" (2018-09-28).</p>
   <p>N4158’s customization-point approach has a very high cost-to-benefit ratio.
I am satisfied with P1144’s avoiding that approach.</p>
   <h3 class="heading settled" data-level="6.5" id="nothrow-relocatable"><span class="secno">6.5. </span><span class="content">Unintuitive <code class="highlight"><c- n>is_nothrow_relocatable</c-></code></span><a class="self-link" href="#nothrow-relocatable"></a></h3>
   <p>Consider a type such as</p>
<pre class="language-c++ highlight">    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-> <c- n>Widget</c-> <c- p>{</c->
        <c- b>int</c-> <c- n>i</c-><c- p>;</c->
        <c- n>Widget</c-><c- p>(</c-><c- n>Widget</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>:</c-> <c- n>i</c-><c- p>(</c-><c- n>rhs</c-><c- p>.</c-><c- n>i</c-><c- p>)</c-> <c- p>{}</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_nothrow_move_constructible_v</c-><c- o>&lt;</c-><c- n>Widget</c-><c- o>></c-><c- p>);</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_nothrow_relocatable_v</c-><c- o>&lt;</c-><c- n>Widget</c-><c- o>></c-><c- p>);</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>Widget</c-><c- o>></c-><c- p>);</c->
</pre>
   <p>Since <code class="highlight"><c- n>Widget</c-></code> is non-nothrow move-constructible, P1144 calls it non-nothrow relocatable.
So, looking at how <code class="highlight"><c- n>Widget</c-></code> interacts with the type-traits, we are in the awkward position
that <code class="highlight"><c- n>Widget</c-></code> simultaneously claims "My relocation operation might throw" and "My relocation
operation is trivial." These claims seem inconsistent.</p>
   <p>This is a real-world concern because GNU libstdc++'s <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>deque</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code> works like <code class="highlight"><c- n>Widget</c-></code>: its move-constructor is <code class="highlight"><c- k>noexcept</c-><c- p>(</c->false<c- p>)</c-></code> (it must allocate)
but it is trivially relocatable. As of 2019-01-18, libstdc++ marks its <code class="highlight"><c- n>deque</c-></code> as
trivially relocatable (see <a data-link-type="biblio" href="#biblio-deque">[Deque]</a>).</p>
   <p>However, I believe that it would be incorrect and unsafe for the library to claim that <code class="highlight"><c- n>Widget</c-></code> was "nothrow relocatable." "Nothrow relocatable" should imply that
a generic algorithm could relocate it (as if by <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>uninitialized_relocate</c-></code>)
without worrying about catching exceptions. "<code class="highlight"><c- n>T</c-></code> is trivially relocatable" means that <code class="highlight"><c- n>T</c-></code> is relocat<i>able as if</i> by <code class="highlight"><c- n>memcpy</c-></code>; it does not mean that every relocation of <code class="highlight"><c- n>T</c-></code> <i>must</i> be performed <i>literally</i> by <code class="highlight"><c- n>memcpy</c-></code>.</p>
   <p>I believe P1144’s proposed behavior is the best behavior. However, another plausible option
would be simply to eliminate the <code class="highlight"><c- n>is_nothrow_relocatable</c-></code> type-trait from the standard library.
If we don’t provide <code class="highlight"><c- n>is_nothrow_relocatable</c-></code>, then we don’t have to defend its
mildly unintuitive behavior.</p>
   <h3 class="heading settled" data-level="6.6" id="relocate-function"><span class="secno">6.6. </span><span class="content">Provide <code class="highlight"><c- n>T</c-> <c- n>relocate</c-><c- p>(</c-><c- n>T</c-><c- o>*</c-><c- p>)</c-></code>?</span><a class="self-link" href="#relocate-function"></a></h3>
   <p class="note" role="note"><span>Note:</span> This section is new in P1144R5.</p>
   <p>The current proposal provides <code class="highlight"><c- n>T</c-> <c- o>*</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>,</c-> <c- n>T</c-> <c- o>*</c-><c- n>dest</c-><c- p>)</c-></code>, which ends the lifetime of <code class="highlight"><c- n>source</c-></code> and starts the lifetime of <code class="highlight"><c- n>dest</c-></code>. Anton Zhilin suggested that a more general primitive
would actually be <code class="highlight"><c- n>T</c-> <c- n>relocate</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>)</c-></code>, which ends the lifetime of <code class="highlight"><c- n>source</c-></code> and starts the
lifetime of a prvalue <code class="highlight"><c- n>T</c-></code> wherever the caller wants.</p>
<pre class="language-c++ highlight">    <c- c1>// Before P1144:</c->
    <c- o>::</c-><c- n>new</c-> <c- p>(</c-><c- n>dst_ptr</c-><c- p>)</c-> <c- n>C</c-><c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- n>C</c-><c- o>*></c-><c- p>(</c-><c- n>src_ptr</c-><c- p>))</c-> <c- p>};</c->
    <c- n>static_cast</c-><c- o>&lt;</c-><c- n>C</c-><c- o>*></c-><c- p>(</c-><c- n>src_ptr</c-><c- p>)</c-><c- o>->~</c-><c- n>C</c-><c- p>();</c->

    <c- c1>// After P1144R5:</c->
    <c- n>std</c-><c- o>::</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- n>C</c-><c- o>*></c-><c- p>(</c-><c- n>src_ptr</c-><c- p>),</c-> <c- n>static_cast</c-><c- o>&lt;</c-><c- n>C</c-><c- o>*></c-><c- p>(</c-><c- n>dst_ptr</c-><c- p>));</c->

    <c- c1>// After Anton Zhilin’s suggestion:</c->
    <c- o>::</c-><c- n>new</c-> <c- p>(</c-><c- n>dst_ptr</c-><c- p>)</c-> <c- n>C</c-><c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>relocate</c-><c- p>(</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- n>C</c-><c- o>*></c-><c- p>(</c-><c- n>src_ptr</c-><c- p>))</c-> <c- p>};</c->
</pre>
   <p>With the <code class="highlight"><c- n>relocate</c-></code> primitive, we could implement operations such as <code class="highlight"><c- n>pilfer_back</c-></code>:</p>
<pre class="language-c++ highlight">    <c- c1>// Before Anton Zhilin’s suggestion:</c->
    <c- n>T</c-> <c- nf>pilfer_back</c-><c- p>()</c-> <c- p>{</c->
        <c- n>T</c-> <c- n>result</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>data_</c-><c- p>[</c-><c- n>size_</c-><c- o>-</c-><c- mi>1</c-><c- p>]);</c->
        <c- n>data_</c-><c- p>[</c-><c- o>--</c-><c- n>size_</c-><c- p>].</c-><c- o>~</c-><c- n>T</c-><c- p>();</c->
        <c- k>return</c-> <c- n>result</c-><c- p>;</c->
    <c- p>}</c->

    <c- c1>// After Anton Zhilin’s suggestion:</c->
    <c- n>T</c-> <c- nf>pilfer_back</c-><c- p>()</c-> <c- p>{</c->
        <c- n>T</c-> <c- n>result</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>relocate</c-><c- p>(</c-><c- n>data_</c-><c- p>[</c-><c- n>size_</c-><c- p>]);</c->
        <c- o>--</c-><c- n>size_</c-><c- p>;</c->
        <c- k>return</c-> <c- n>result</c-><c- p>;</c->
    <c- p>}</c->
</pre>
   <p><code class="highlight"><c- n>relocate_at</c-></code> can be implemented with today’s core language. Anton’s <code class="highlight"><c- n>relocate</c-></code> cannot. There is
no way to "memcpy into the return slot" of a function, because the return slot is unnamed —<wbr>unless you create a local variable to name it, by which point it is too late, because you cannot
create a local variable without constructing it. The library implementation of <code class="highlight"><c- n>relocate</c-></code> would
have to use additional implementation magic; for example, an attribute <code class="highlight"><c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>unconstructed</c-><c- p>]]</c-></code>.
That attribute (or whatever) would not need to be standardized nor exposed to users.</p>
   <p>This also assumes a compiler with Clang-level smarts about when to do NRVO. <a data-link-type="biblio" href="#biblio-p2025r0">[P2025R0]</a>,
currently in EWG, proposes that all compilers be required to have such smarts.</p>
<pre class="language-c++ highlight">    <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
    <c- n>T</c-> <c- n>relocate</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>)</c-> <c- p>{</c->
        <c- k>if</c-> <c- n>constexpr</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
            <c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>unconstructed</c-><c- p>]]</c-> <c- n>T</c-> <c- n>dest</c-><c- p>;</c->   <c- c1>// do not run dest’s constructor</c->
            <c- n>memcpy</c-><c- p>(</c-><c- o>&amp;</c-><c- n>dest</c-><c- p>,</c-> <c- n>source</c-><c- p>,</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>T</c-><c- p>));</c->  <c- c1>// do not run source’s destructor</c->
            <c- k>return</c-> <c- n>dest</c-><c- p>;</c->                       <c- c1>// copy-elision</c->
        <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
            <c- n>T</c-> <c- n>dest</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>source</c-><c- p>));</c->  <c- c1>// run dest’s constructor</c->
            <c- n>source</c-><c- o>->~</c-><c- n>T</c-><c- p>();</c->                <c- c1>// run source’s destructor</c->
            <c- k>return</c-> <c- n>dest</c-><c- p>;</c->                 <c- c1>// copy-elision</c->
        <c- p>}</c->
    <c- p>}</c->

    <c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
    <c- n>T</c-> <c- o>*</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>,</c-> <c- n>T</c-> <c- o>*</c-><c- n>dest</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- o>::</c-><c- n>new</c-> <c- p>(</c-><c- n>dest</c-><c- p>)</c-> <c- n>T</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>relocate</c-><c- p>(</c-><c- n>source</c-><c- p>));</c->
    <c- p>}</c->
</pre>
   <p>P1144R5 does not propose <code class="highlight"><c- n>T</c-> <c- n>relocate</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>)</c-></code> for inclusion in the standard library, because
it requires this additional compiler support, which has not yet been implemented anywhere.</p>
   <h3 class="heading settled" data-level="6.7" id="pmr-concerns"><span class="secno">6.7. </span><span class="content">Confusing interactions with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-></code> and <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>insert</c-></code></span><a class="self-link" href="#pmr-concerns"></a></h3>
   <p class="note" role="note"><span>Note:</span> This section is new in P1144R5.</p>
   <p>The main thing P1144 does for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code> is efficient reallocation of the whole buffer.
However, a secondary goal is to permit efficient insertion and erasure. <a href="https://godbolt.org/z/YOrD1F">Example:</a></p>
<pre class="language-c++ highlight">    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-> <c- n>vs</c-><c- p>(</c-><c- mi>1000</c-><c- p>);</c->
    <c- n>vs</c-><c- p>.</c-><c- n>erase</c-><c- p>(</c-><c- n>vs</c-><c- p>.</c-><c- n>begin</c-><c- p>()</c-><c- o>+</c-><c- mi>500</c-><c- p>);</c->
</pre>
   <p>This <code class="highlight"><c- n>erase</c-></code> requires us to shift down 500 <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>string</c-></code> objects, which can be done either
by 500 calls to <code class="highlight"><c- n>string</c-><c- o>::</c-><c- k>operator</c-><c- o>=</c-></code> followed by one call to <code class="highlight"><c- o>~</c-><c- n>string</c-></code>, or by
one call to <code class="highlight"><c- o>~</c-><c- n>string</c-></code> followed by a <code class="highlight"><c- n>memcpy</c-></code>. We want to permit the latter. That’s why
as of P1144R3, the definition of "trivially relocatable" in <a href="#wording-inheritance">§ 5.5 Trivially relocatable type</a> places requirements on <code class="highlight"><c- n>T</c-></code>'s assignment operators as well as on <code class="highlight"><c- n>T</c-></code>'s constructors and destructors.</p>
   <p>However, consider <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code>. Its move-constructor and destructor follow the
rules for trivial relocatability, but its assignment operator does not.</p>
<pre class="language-c++ highlight">    <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>>></c-> <c- n>vv</c-><c- p>;</c->
    <c- n>vv</c-><c- p>.</c-><c- n>emplace_back</c-><c- p>(</c-><c- mi>1</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>mr1</c-><c- p>);</c->
    <c- n>vv</c-><c- p>.</c-><c- n>emplace_back</c-><c- p>(</c-><c- mi>2</c-><c- p>,</c-> <c- mi>2</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>mr2</c-><c- p>);</c->
    <c- n>vv</c-><c- p>.</c-><c- n>emplace_back</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>mr3</c-><c- p>);</c->
    <c- n>vv</c-><c- p>.</c-><c- n>reserve</c-><c- p>(</c-><c- mi>1000</c-><c- p>);</c->  <c- c1>// A</c->
    <c- n>vv</c-><c- p>.</c-><c- n>erase</c-><c- p>(</c-><c- n>vv</c-><c- p>.</c-><c- n>begin</c-><c- p>());</c->  <c- c1>// B</c->
</pre>
   <p>On line "A", we would like the implementation to use trivial relocation (<code class="highlight"><c- n>memcpy</c-></code>) because it
is fast and correct. But on line "B", if the implementation today uses <code class="highlight"><c- k>operator</c-><c- o>=</c-></code> and tomorrow
uses <code class="highlight"><c- n>memcpy</c-></code>, the user will be able to detect the change by inspecting <code class="highlight"><c- n>vv</c-><c- p>[</c-><c- mi>0</c-><c- p>].</c-><c- n>get_allocator</c-><c- p>()</c-></code>.</p>
   <p>See this example completely worked out <a href="https://www.youtube.com/watch?v=SGdfPextuAU&amp;t=76m17s">@76:17–84:20</a> in my C++Now 2019 talk.</p>
   <p>For now, P1144R5 implies that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> shall not be trivially relocatable,
which means that line "A" will not get the <code class="highlight"><c- n>memcpy</c-></code> speedup unless the vendor special-cases
a whitelist of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-></code> containers. However, I think this area deserves more discussion.</p>
   <p class="note" role="note"><span>Note:</span> Regardless, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>polymorphic_allocator</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> is a trivially relocatable type.
The problem above arises from <code class="highlight"><c- n>propagate_on_move_assignment</c-></code> etc., which affect the behavior of <code class="highlight"><c- k>operator</c-><c- o>=</c-></code> only for <em>containers</em> such as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pmr</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code>. The author of the container makes
the choice whether to respect POCMA/POCCA/POCS, and the author of the container also makes the choice
when to warrant trivial relocatability. These choices are correlated, and so it is natural that
they should be made by the same person, at the same place in the source code.</p>
   <h2 class="heading settled" data-level="7" id="acknowledgements"><span class="secno">7. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Thanks to Elias Kosunen, Niall Douglas, and John Bandela for their feedback on early drafts of this paper.</p>
   <p>Many thanks to Matt Godbolt for allowing me to install the prototype Clang implementation on Compiler Explorer
(<a href="https://p1144.godbolt.org/z/oWEd_X">godbolt.org</a>). See also <a data-link-type="biblio" href="#biblio-announcing">[Announcing]</a>.</p>
   <p>Thanks to Nicolas Lesser for his relentless feedback on drafts of P1144R0, and for his helpful
review comments on the Clang implementation <a data-link-type="biblio" href="#biblio-d50119">[D50119]</a>.</p>
   <p>Thanks to Howard Hinnant for appearing with me on <a data-link-type="biblio" href="#biblio-cppchat">[CppChat]</a>, and to Jon Kalb and Phil Nash for hosting us.</p>
   <p>Thanks to Pablo Halpern for <a data-link-type="biblio" href="#biblio-n4158">[N4158]</a>, to which this paper bears a striking and coincidental resemblance —<wbr>including the meaning assigned to the word "trivial," and the library-algorithm approach to avoiding the
problems with "lame duck objects" discussed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternative%20move%20designs">the final section</a> of <a data-link-type="biblio" href="#biblio-n1377">[N1377]</a>. See <a href="http://wiki.edg.com/bin/view/Wg21rapperswil2014/N4034">discussion of N4034 at Rapperswil</a> (June 2014)
and <a href="http://wiki.edg.com/bin/view/Wg21urbana-champaign/EvolutionWorkingGroup#N4158_Destructive_Move_Rev_1">discussion
of N4158 at Urbana</a> (November 2014).</p>
   <p>Significantly different approaches to this problem have previously appeared in Rodrigo Castro Campos’s <a data-link-type="biblio" href="#biblio-n2754">[N2754]</a>, Denis Bider’s <a data-link-type="biblio" href="#biblio-p0023r0">[P0023R0]</a> (introducing a core-language "relocation" operator), and
Niall Douglas’s <a data-link-type="biblio" href="#biblio-p1029r3">[P1029R3]</a> (treating trivial relocatability as an aspect of move-construction in isolation,
rather than an aspect of the class type as a whole).</p>
   <p>Thanks to John McCall for his thought-provoking review comments on the Clang implementation <a data-link-type="biblio" href="#biblio-d50119">[D50119]</a>.</p>
   <p>Thanks to Marc Glisse for his work integrating a "trivially relocatable" trait into GNU libstdc++
and for answering my questions on <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87106">GCC bug 87106</a>.</p>
   <p>Thanks to Jens Maurer for his feedback on this paper at Kona 2019, and to Corentin Jabot for championing
P1144R4 at Prague 2020.</p>
   <h2 class="heading settled" id="polls"><span class="content">Appendix A: Straw polls</span><a class="self-link" href="#polls"></a></h2>
   <p class="issue" id="issue-8c46923c"><a class="self-link" href="#issue-8c46923c"></a> The next time this paper is seen, Anton Zhilin would like us to take a straw poll
on whether it should be possible to create a type which is "trivially relocatable, but not move-constructible."
Currently P1144 does not permit such a thing; relocatability here is defined as a superset of move-constructibility.</p>
   <h3 class="heading settled" id="taken-polls-2020-02-13"><span class="content">Polls taken at EWGI at Prague on 2020-02-13</span><a class="self-link" href="#taken-polls-2020-02-13"></a></h3>
   <p>Corentin Jabot championed P1144R4. EWGI discussed P1144R4 and Niall Douglas’s <a data-link-type="biblio" href="#biblio-p1029r3">[P1029R3]</a> consecutively,
then took the following straw polls.
The final poll was interpreted by EWGI assistant chair Erich Keane as "weak consensus" to forward P1144 to EWG.</p>
   <table class="def">
    <tbody>
     <tr>
      <th style="width: 70%;">
      <th><strong>SF</strong>
      <th><strong>F</strong>
      <th><strong>N</strong>
      <th><strong>A</strong>
      <th><strong>SA</strong>
     <tr>
      <th><small>We believe that P1029 and P1144 are sufficiently different that they should be advanced separately.</small>
      <th> 7 
      <th> 3 
      <th> 2 
      <th> 0 
      <th> 0 
     <tr>
      <th><small>EWGI is ok to have the spelling as an attribute with an expression argument.</small>
      <th> 3 
      <th> 5 
      <th> 1 
      <th> 1 
      <th> 0 
     <tr>
      <th><small>EWGI would prefer a contextual keyword.</small>
      <th> 0 
      <th> 0 
      <th> 6 
      <th> 3 
      <th> 0 
     <tr>
      <th><small>EWGI thinks the author should explore P1144 as a customizable type trait.</small>
      <th> 0 
      <th> 0 
      <th> 0 
      <th> 9 
      <th> 2 
     <tr>
      <th><small>Forward P1144 to EWG.</small>
      <th> 1 
      <th> 3 
      <th> 4 
      <th> 1 
      <th> 0 
   </table>
   <h3 class="heading settled" id="taken-polls-2018-11-12"><span class="content">Polls taken of the Internet between 2018-11-12 and 2018-11-21</span><a class="self-link" href="#taken-polls-2018-11-12"></a></h3>
   <table class="def">
    <tbody>
     <tr>
      <th style="width: 70%;">
      <th><strong>SF</strong>
      <th><strong>F</strong>
      <th><strong>N</strong>
      <th><strong>A</strong>
      <th><strong>SA</strong>
     <tr>
      <th><small>We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.</small>
      <th>6
      <th>1
      <th>0
      <th>0
      <th>1
     <tr>
      <th><small>We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members.</small>
      <th>7
      <th>1
      <th>0
      <th>0
      <th>0
     <tr>
      <th><small>Nobody should be able to warrant the trivial relocatability of <code class="highlight"><c- k>class</c-> <c- nc>C</c-></code> except for <code class="highlight"><c- k>class</c-> <c- nc>C</c-></code> itself (i.e., we do not want to see a customization point analogous to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>hash</c-></code>).</small>
      <th>4
      <th>2
      <th>2
      <th>0
      <th>0
     <tr>
      <th><small>A class should be able to warrant its own trivial relocatability via the attribute <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>, as proposed in this paper (P1144R0).</small>
      <th>3
      <th>0
      <th>3
      <th>1
      <th>0
     <tr>
      <th><small>A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name.</small>
      <th>2
      <th>0
      <th>4
      <th>1
      <th>0
     <tr>
      <th><small>A class should be able to warrant its own trivial relocatability as proposed in this paper (P1144R0), but via a contextual keyword rather than an attribute.</small>
      <th>0
      <th>2
      <th>3
      <th>3
      <th>0
     <tr>
      <th><small>If a trait with the semantics of <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is added to the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>hash</c-></code>).</small>
      <th>0
      <th>1
      <th>0
      <th>1
      <th>5
     <tr>
      <th><small>Trivial relocatability should be assumed by default. Classes such as those in <a href="#non-trivial-samples">Appendix C</a> should indicate their non-trivial relocatability via an opt-in mechanism.</small>
      <th>0
      <th>0
      <th>0
      <th>3
      <th>5
     <tr>
      <th><small>To simplify <a href="#sample-conditional">Conditionally trivial relocation</a>, if an attribute with the semantics of <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> is added, it should take a boolean argument.</small>
      <th>1
      <th>1
      <th>3
      <th>2
      <th>0
     <tr>
      <th><small>The algorithm <code class="highlight"><c- n>uninitialized_relocate</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>,</c-> <c- n>d_first</c-><c- p>)</c-></code> should be added to the <code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code> header,
as proposed in this paper (P1144R0).</small>
      <th>0
      <th>4
      <th>1
      <th>1
      <th>0
     <tr>
      <th><small>The type trait <code class="highlight"><c- n>is_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (and its <code class="highlight"><c- n>_v</c-></code> version) should be added to the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header, as proposed in this paper (P1144R0).</small>
      <th>0
      <th>2
      <th>3
      <th>0
      <th>1
     <tr>
      <th><small>If <code class="highlight"><c- n>is_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> <em>is</em> added, then we should also add <code class="highlight"><c- n>is_nothrow_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (and its <code class="highlight"><c- n>_v</c-></code> version), as proposed in this paper (P1144R0).</small>
      <th>1
      <th>4
      <th>2
      <th>0
      <th>0
     <tr>
      <th><small>The type trait <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (and its <code class="highlight"><c- n>_v</c-></code> version) should be added to the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header, under that exact name, as proposed in this paper (P1144R0).</small>
      <th>3
      <th>3
      <th>1
      <th>0
      <th>0
     <tr>
      <th><small>We approve of a trait with the semantics of <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>, but not necessarily under that exact name. (For example, <code class="highlight"><c- n>is_bitwise_relocatable</c-></code>.)</small>
      <th>3
      <th>3
      <th>0
      <th>1
      <th>0
     <tr>
      <th><small>If <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> <em>is</em> added, under that exact name, then the type trait <code class="highlight"><c- n>is_trivially_swappable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (and its <code class="highlight"><c- n>_v</c-></code> version) should also be added to the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header.</small>
      <th>0
      <th>3
      <th>3
      <th>0
      <th>0
   </table>
   <p>The "Strongly Against" vote on poll 1 was due to concerns that P1144 permits a class to warrant its
own trivial relocatability, overruling the compiler’s assumptions, not only when the compiler’s assumptions
are based on the presence of special members, but also when the compiler’s
assumptions are based partly or wholly on the non-triviality of member or base subobjects.
See further discussion under <a href="#maybe-trivially-relocatable">§ 6.3 Attribute [[maybe_trivially_relocatable]]</a>.</p>
   <p>The "Against" vote on poll 10, <code class="highlight"><c- n>uninitialized_relocate</c-></code>, was due to its exception guarantee, which was
weaker in P1144R0. P1144R1 strengthened the guarantee (and tightened the constraint on the source
iterator from <code class="highlight"><c- n>InputIterator</c-></code> to <code class="highlight"><c- n>ForwardIterator</c-></code>) to better match the other <code class="highlight"><c- n>uninitialized_foo</c-></code> algorithms.</p>
   <p>The "Strongly Against" vote on poll 11, <code class="highlight"><c- n>is_relocatable</c-></code>, was from a desire to save the name <code class="highlight"><c- n>relocatable</c-></code> for something different, such as a built-in destructive-move operation.</p>
   <h3 class="heading settled" id="taken-polls-2018-11-07"><span class="content">Poll taken of EWGI at San Diego on 2018-11-07</span><a class="self-link" href="#taken-polls-2018-11-07"></a></h3>
   <table class="def">
    <tbody>
     <tr>
      <th style="width: 70%;">
      <th><strong>SF</strong>
      <th><strong>F</strong>
      <th><strong>N</strong>
      <th><strong>A</strong>
      <th><strong>SA</strong>
     <tr>
      <th><small>Should we commit additional committee time to solving the problem P1144R0 is trying to solve, knowing it will leave less time to other work?</small>
      <th> 8 
      <th> 3 
      <th> 0 
      <th> 0 
      <th> 0 
   </table>
   <h3 class="heading settled" id="taken-polls-2018-09-26"><span class="content">Polls taken of SG14 at CppCon on 2018-09-26</span><a class="self-link" href="#taken-polls-2018-09-26"></a></h3>
   <table class="def">
    <tbody>
     <tr>
      <th style="width: 70%;">
      <th><strong>SF</strong>
      <th><strong>F</strong>
      <th><strong>N</strong>
      <th><strong>A</strong>
      <th><strong>SA</strong>
     <tr>
      <th><small>The type trait <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (and its <code class="highlight"><c- n>_v</c-></code> version) should be added to the <code class="highlight"><c- o>&lt;</c-><c- n>type_traits</c-><c- o>></c-></code> header, under that exact name, as proposed in this paper.</small>
      <th> 1 
      <th> 20 
      <th> 7 
      <th> 1 
      <th> 0 
     <tr>
      <th><small>We approve of a trait with the semantics of <code class="highlight"><c- n>is_trivially_relocatable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>, but not necessarily under that exact name. (For example, <code class="highlight"><c- n>is_bitwise_relocatable</c-></code>.)</small>
      <th> 15 
      <th> 12 
      <th> 1 
      <th> 0 
      <th> 0 
     <tr>
      <th><small>We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability.</small>
      <th> 25 
      <th> 5 
      <th> 2 
      <th> 0 
      <th> 0 
   </table>
   <h2 class="heading settled" id="samples"><span class="content">Appendix B: Sample code</span><a class="self-link" href="#samples"></a></h2>
   <h3 class="heading settled" id="sample-uninit-relocate"><span class="content">Reference implementation of <code class="highlight"><c- n>relocate_at</c-></code> and <code class="highlight"><c- n>uninitialized_relocate</c-></code></span><a class="self-link" href="#sample-uninit-relocate"></a></h3>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
<c- n>T</c-> <c- o>*</c-><c- n>relocate_at</c-><c- p>(</c-><c- n>T</c-> <c- o>*</c-><c- n>source</c-><c- p>,</c-> <c- n>T</c-> <c- o>*</c-><c- n>dest</c-><c- p>)</c->
<c- p>{</c->
    <c- k>if</c-> <c- n>constexpr</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>)</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>memmove</c-><c- p>(</c-><c- n>dest</c-><c- p>,</c-> <c- n>source</c-><c- p>,</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>T</c-><c- p>));</c->
        <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>launder</c-><c- p>(</c-><c- n>dest</c-><c- p>);</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
        <c- n>T</c-> <c- o>*</c-><c- n>result</c-> <c- o>=</c-> <c- o>::</c-><c- n>new</c-> <c- p>(</c-><c- n>dest</c-><c- p>)</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>source</c-><c- p>));</c->
        <c- n>source</c-><c- o>->~</c-><c- n>T</c-><c- p>();</c->
        <c- k>return</c-> <c- n>result</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>ForwardIterator1</c-><c- p>,</c-> <c- n>class</c-> <c- n>ForwardIterator2</c-><c- o>></c->
<c- n>ForwardIterator2</c-> <c- n>uninitialized_relocate</c-><c- p>(</c-><c- n>ForwardIterator1</c-> <c- n>first</c-><c- p>,</c-> <c- n>ForwardIterator1</c-> <c- n>last</c-><c- p>,</c->
                                        <c- n>ForwardIterator2</c-> <c- n>result</c-><c- p>)</c->
<c- p>{</c->
    <c- n>using</c-> <c- n>T</c-> <c- o>=</c-> <c- kr>typename</c-> <c- n>iterator_traits</c-><c- o>&lt;</c-><c- n>ForwardIterator2</c-><c- o>>::</c-><c- n>value_type</c-><c- p>;</c->
    <c- n>using</c-> <c- n>U</c-> <c- o>=</c-> <c- n>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>first</c-><c- p>));</c->
    <c- n>constexpr</c-> <c- b>bool</c-> <c- n>memcpyable</c-> <c- o>=</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_same_v</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>remove_ref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>></c-> <c- o>&amp;&amp;</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>);</c->
    <c- n>constexpr</c-> <c- b>bool</c-> <c- n>both_contiguous</c-> <c- o>=</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_pointer_v</c-><c- o>&lt;</c-><c- n>ForwardIterator1</c-><c- o>></c-> <c- o>&amp;&amp;</c-> <c- n>std</c-><c- o>::</c-><c- n>is_pointer_v</c-><c- o>&lt;</c-><c- n>ForwardIterator2</c-><c- o>></c-><c- p>);</c->
    <c- n>constexpr</c-> <c- b>bool</c-> <c- n>nothrow_relocatable</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>is_nothrow_constructible_v</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>U</c-><c- o>></c-><c- p>;</c->

    <c- k>if</c-> <c- nf>constexpr</c-> <c- p>(</c-><c- n>memcpyable</c-> <c- o>&amp;&amp;</c-> <c- n>both_contiguous</c-><c- p>)</c-> <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>nbytes</c-> <c- o>=</c-> <c- p>(</c-><c- b>char</c-> <c- o>*</c-><c- p>)</c-><c- n>last</c-> <c- o>-</c-> <c- p>(</c-><c- b>char</c-> <c- o>*</c-><c- p>)</c-><c- n>first</c-><c- p>;</c->
        <c- k>if</c-> <c- p>(</c-><c- n>nbytes</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
            <c- n>std</c-><c- o>::</c-><c- n>memmove</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- o>*</c-><c- n>result</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- o>*</c-><c- n>first</c-><c- p>),</c-> <c- n>nbytes</c-><c- p>);</c->
            <c- n>result</c-> <c- o>+=</c-> <c- p>(</c-><c- n>last</c-> <c- o>-</c-> <c- n>first</c-><c- p>);</c->
        <c- p>}</c->
    <c- p>}</c-> <c- k>else</c-> <c- k>if</c-> <c- nf>constexpr</c-> <c- p>(</c-><c- n>nothrow_relocatable</c-><c- p>)</c-> <c- p>{</c->
        <c- k>for</c-> <c- p>(;</c-> <c- n>first</c-> <c- o>!=</c-> <c- n>last</c-><c- p>;</c-> <c- p>(</c-><c- b>void</c-><c- p>)</c-><c- o>++</c-><c- n>result</c-><c- p>,</c-> <c- o>++</c-><c- n>first</c-><c- p>)</c-> <c- p>{</c->
            <c- o>::</c-><c- n>new</c-> <c- p>(</c-><c- n>static_cast</c-><c- o>&lt;</c-><c- b>void</c-><c- o>*></c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- o>*</c-><c- n>result</c-><c- p>)))</c-> <c- n>T</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- n>first</c-><c- p>));</c->
            <c- n>std</c-><c- o>::</c-><c- n>destroy_at</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>addressof</c-><c- p>(</c-><c- o>*</c-><c- n>first</c-><c- p>));</c->
        <c- p>}</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
        <c- n>result</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>uninitialized_move</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>,</c-> <c- n>result</c-><c- p>);</c->
        <c- n>std</c-><c- o>::</c-><c- n>destroy</c-><c- p>(</c-><c- n>first</c-><c- p>,</c-> <c- n>last</c-><c- p>);</c->
    <c- p>}</c->
    <c- k>return</c-> <c- n>result</c-><c- p>;</c->
<c- p>}</c->
</pre></small> 
   <h3 class="heading settled" id="sample-conditional"><span class="content">Conditionally trivial relocation</span><a class="self-link" href="#sample-conditional"></a></h3>
   <p>We expect, but do not require, that <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> should be trivially relocatable
if and only if <code class="highlight"><c- n>T</c-></code> itself is trivially relocatable.</p>
   <p>The following abbreviated implementation shows how to achieve an <code class="highlight"><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> which
has the same trivial-move-constructibility as <code class="highlight"><c- n>T</c-></code>, the same trivial-destructibility
as <code class="highlight"><c- n>T</c-></code>, and the same trivial-relocatability as <code class="highlight"><c- n>T</c-></code>.</p>
   <p>The primitives of move-construction and destruction are provided by four specializations
of <code class="highlight"><c- n>optional_a</c-></code>; then the public <code class="highlight"><c- n>optional</c-></code> extends the appropriate specialization of <code class="highlight"><c- n>optional_a</c-></code> and applies a conditional <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute.</p>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- o>></c->
<c- n>class</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>)]]</c-> <c- nl>optional</c-> <c- p>:</c-> <c- n>optional_base</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c->
<c- p>{</c->
    <c- n>using</c-> <c- n>optional_base</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>::</c-><c- n>optional_base</c-><c- p>;</c->
<c- p>};</c->

<c- n>template</c-><c- o>&lt;</c-><c- n>class</c-> <c- n>T</c-><c- p>,</c-> <c- b>bool</c-> <c- n>D</c-> <c- o>=</c-> <c- n>is_trivially_destructible_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- b>bool</c-> <c- n>M</c-> <c- o>=</c-> <c- n>is_trivially_move_constructible_v</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- n>class</c-> <c- n>optional_base</c-> <c- p>{</c->
    <c- c1>// NOT SHOWN</c->
<c- p>};</c->
</pre></small> 
   <p>I have implemented the entire Standard Library using the proposed <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code> attribute; you can find the source code <a href="https://github.com/Quuxplusone/libcxx/tree/trivially-relocatable">on my GitHub</a> and explore the resulting codegen <a href="https://p1144.godbolt.org/z/t28saC">on Godbolt Compiler Explorer</a>.</p>
   <p>I have also implemented case studies for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>deque</c-></code>, in each of the
alternative styles:</p>
   <table class="def">
    <tbody>
     <tr>
      <th>Style
      <th>Size of <code class="highlight"><c- n>optional</c-></code> diff (lines)
      <th>Size of <code class="highlight"><c- n>deque</c-></code> diff (lines)
     <tr>
      <td><code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-optional-tr">-2, +14</a>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-deque-tr">-18, +52</a>
     <tr>
      <td><code class="highlight"><c- p>[[</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-optional-mtr">problematic</a>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-deque-mtr">-5, +5</a>
     <tr>
      <td><code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-optional-trbool">-1, +1</a>
      <td><a href="https://github.com/Quuxplusone/libcxx/commit/example-deque-trbool">-1, +17</a>
   </table>
   <p>For why one entry in this table is "problematic," see <a href="#maybe-trivially-relocatable">§ 6.3 Attribute [[maybe_trivially_relocatable]]</a>.</p>
   <h2 class="heading settled" id="non-trivial-samples"><span class="content">Appendix C: Examples of non-trivially relocatable class types</span><a class="self-link" href="#non-trivial-samples"></a></h2>
   <h3 class="heading settled" id="non-trivial-sample-string"><span class="content">Class contains pointer to self</span><a class="self-link" href="#non-trivial-sample-string"></a></h3>
   <p>This fictional <code class="highlight"><c- n>short_string</c-></code> illustrates a mechanism that can apply
to any small-buffer-optimized class. <a data-link-type="biblio" href="#biblio-libcxxfunction">libc++'s std::function</a> uses this mechanism (on a 24-byte buffer) and is thus not trivially relocatable.</p>
   <p>However, different mechanisms for small-buffer optimization exist. <a data-link-type="biblio" href="#biblio-libcxxany">libc++'s std::any</a> also achieves small-buffer optimization
on a 24-byte buffer, without (necessarily) sacrificing trivial relocatability.</p>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- k>struct</c-> <c- n>short_string</c-> <c- p>{</c->
    <c- b>char</c-> <c- o>*</c-><c- n>data_</c-> <c- o>=</c-> <c- n>buffer_</c-><c- p>;</c->
    <c- b>size_t</c-> <c- n>size_</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
    <c- b>char</c-> <c- n>buffer_</c-><c- p>[</c-><c- mi>8</c-><c- p>]</c-> <c- o>=</c-> <c- p>{};</c->

    <c- k>const</c-> <c- b>char</c-> <c- o>*</c-><c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- p>{</c-> <c- k>return</c-> <c- n>data_</c-><c- p>;</c-> <c- p>}</c->

    <c- n>short_string</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>short_string</c-><c- p>(</c-><c- k>const</c-> <c- b>char</c-> <c- o>*</c-><c- n>s</c-><c- p>)</c-> <c- o>:</c-> <c- n>size_</c-><c- p>(</c-><c- n>strlen</c-><c- p>(</c-><c- n>s</c-><c- p>))</c-> <c- p>{</c->
        <c- k>if</c-> <c- p>(</c-><c- n>size_</c-> <c- o>&lt;</c-> <c- k>sizeof</c-> <c- n>buffer_</c-><c- p>)</c->
            <c- n>strcpy</c-><c- p>(</c-><c- n>buffer_</c-><c- p>,</c-> <c- n>s</c-><c- p>);</c->
        <c- k>else</c->
            <c- n>data_</c-> <c- o>=</c-> <c- n>strdup</c-><c- p>(</c-><c- n>s</c-><c- p>);</c->
    <c- p>}</c->
    <c- n>short_string</c-><c- p>(</c-><c- n>short_string</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c->
        <c- n>memcpy</c-><c- p>(</c-><c- n>this</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>s</c-><c- p>,</c-> <c- k>sizeof</c-><c- p>(</c-><c- o>*</c-><c- n>this</c-><c- p>));</c->
        <c- k>if</c-> <c- p>(</c-><c- n>s</c-><c- p>.</c-><c- n>data_</c-> <c- o>==</c-> <c- n>s</c-><c- p>.</c-><c- n>buffer_</c-><c- p>)</c->
            <c- n>data_</c-> <c- o>=</c-> <c- n>buffer_</c-><c- p>;</c->
        <c- k>else</c->
            <c- n>s</c-><c- p>.</c-><c- n>data_</c-> <c- o>=</c-> <c- n>nullptr</c-><c- p>;</c->
    <c- p>}</c->
    <c- o>~</c-><c- n>short_string</c-><c- p>()</c-> <c- p>{</c->
        <c- k>if</c-> <c- p>(</c-><c- n>data_</c-> <c- o>!=</c-> <c- n>buffer_</c-><c- p>)</c->
            <c- n>free</c-><c- p>(</c-><c- n>data_</c-><c- p>);</c->
    <c- p>}</c->
<c- p>};</c->
</pre></small> 
   <h3 class="heading settled" id="non-trivial-sample-list"><span class="content">Allocated memory contains pointer to self</span><a class="self-link" href="#non-trivial-sample-list"></a></h3>
   <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>list</c-></code> needs somewhere to store its "past-the-end" node, commonly referred to
as the "sentinel node," whose <code class="highlight"><c- n>prev</c-></code> pointer points to the list’s last node.
If the sentinel node is allocated on the heap, then <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>list</c-></code> can be trivially
relocatable; but if the sentinel node is placed within the <code class="highlight"><c- n>list</c-></code> object itself
(as happens on libc++ and libstdc++), then relocating the <code class="highlight"><c- n>list</c-></code> object requires
fixing up the list’s last node’s <code class="highlight"><c- n>next</c-></code> pointer so that it points to the
new sentinel node inside the destination <code class="highlight"><c- n>list</c-></code> object. This fixup of an arbitrary
heap object cannot be simulated by <code class="highlight"><c- n>memcpy</c-></code>.</p>
   <p>Traditional implementations of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>set</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>map</c-></code> also store a "past-the-end"
node inside themselves and thus also fall into this category.</p>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- k>struct</c-> <c- n>node</c-> <c- p>{</c->
    <c- n>node</c-> <c- o>*</c-><c- n>prev_</c-> <c- o>=</c-> <c- n>nullptr</c-><c- p>;</c->
    <c- n>node</c-> <c- o>*</c-><c- n>next_</c-> <c- o>=</c-> <c- n>nullptr</c-><c- p>;</c->
<c- p>};</c->
<c- k>struct</c-> <c- n>list</c-> <c- p>{</c->
    <c- n>node</c-> <c- n>n_</c-><c- p>;</c->
    <c- n>iterator</c-> <c- nf>begin</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>iterator</c-><c- p>(</c-><c- n>n_</c-><c- p>.</c-><c- n>next_</c-><c- p>);</c-> <c- p>}</c->
    <c- n>iterator</c-> <c- nf>end</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>iterator</c-><c- p>(</c-><c- o>&amp;</c-><c- n>n_</c-><c- p>);</c-> <c- p>}</c->
    <c- n>list</c-><c- p>(</c-><c- n>list</c-><c- o>&amp;&amp;</c-> <c- n>l</c-><c- p>)</c-> <c- p>{</c->
        <c- k>if</c-> <c- p>(</c-><c- n>l</c-><c- p>.</c-><c- n>n_</c-><c- p>.</c-><c- n>next_</c-><c- p>)</c-> <c- n>l</c-><c- p>.</c-><c- n>n_</c-><c- p>.</c-><c- n>next_</c-><c- o>-></c-><c- n>prev_</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>n_</c-><c- p>;</c->  <c- c1>// fixup</c->
        <c- k>if</c-> <c- p>(</c-><c- n>l</c-><c- p>.</c-><c- n>n_</c-><c- p>.</c-><c- n>prev_</c-><c- p>)</c-> <c- n>l</c-><c- p>.</c-><c- n>n_</c-><c- p>.</c-><c- n>prev_</c-><c- o>-></c-><c- n>next_</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>n_</c-><c- p>;</c->  <c- c1>// fixup</c->
        <c- n>n_</c-> <c- o>=</c-> <c- n>l</c-><c- p>.</c-><c- n>n_</c-><c- p>;</c->
        <c- n>l</c-><c- p>.</c-><c- n>n_</c-> <c- o>=</c-> <c- n>node</c-><c- p>{};</c->
    <c- p>}</c->
    <c- c1>// ...</c->
<c- p>};</c->
</pre></small> 
   <h3 class="heading settled" id="non-trivial-sample-offset-ptr"><span class="content">Class invariant depends on <code class="highlight"><c- k>this</c-></code></span><a class="self-link" href="#non-trivial-sample-offset-ptr"></a></h3>
   <p>The <code class="highlight"><c- n>offset_ptr</c-></code> provided by <a data-link-type="biblio" href="#biblio-boostinterprocess">[Boost.Interprocess]</a> is an example of this category.</p>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- k>struct</c-> <c- n>offset_ptr</c-> <c- p>{</c->
    <c- b>uintptr_t</c-> <c- n>value_</c-><c- p>;</c->

    <c- b>uintptr_t</c-> <c- nf>here</c-><c- p>()</c-> <c- k>const</c-> <c- p>{</c-> <c- k>return</c-> <c- b>uintptr_t</c-><c- p>(</c-><c- n>this</c-><c- p>);</c-> <c- p>}</c->
    <c- b>uintptr_t</c-> <c- nf>distance_to</c-><c- p>(</c-><c- b>void</c-> <c- o>*</c-><c- n>p</c-><c- p>)</c-> <c- k>const</c-> <c- p>{</c-> <c- k>return</c-> <c- b>uintptr_t</c-><c- p>(</c-><c- n>p</c-><c- p>)</c-> <c- o>-</c-> <c- n>here</c-><c- p>();</c-> <c- p>}</c->
    <c- b>void</c-> <c- o>*</c-><c- nf>get</c-><c- p>()</c-> <c- k>const</c-> <c- p>{</c-> <c- k>return</c-> <c- p>(</c-><c- b>void</c-><c- o>*</c-><c- p>)(</c-><c- n>here</c-><c- p>()</c-> <c- o>+</c-> <c- n>value_</c-><c- p>);</c-> <c- p>}</c->

    <c- n>offset_ptr</c-><c- p>()</c-> <c- o>:</c-> <c- n>value_</c-><c- p>(</c-><c- n>distance_to</c-><c- p>(</c-><c- n>nullptr</c-><c- p>))</c-> <c- p>{}</c->
    <c- n>offset_ptr</c-><c- p>(</c-><c- b>void</c-> <c- o>*</c-><c- n>p</c-><c- p>)</c-> <c- o>:</c-> <c- n>value_</c-><c- p>(</c-><c- n>distance_to</c-><c- p>(</c-><c- n>p</c-><c- p>))</c-> <c- p>{}</c->
    <c- n>offset_ptr</c-><c- p>(</c-><c- k>const</c-> <c- n>offset_ptr</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- o>:</c-> <c- n>value_</c-><c- p>(</c-><c- n>distance_to</c-><c- p>(</c-><c- n>rhs</c-><c- p>.</c-><c- n>get</c-><c- p>()))</c-> <c- p>{}</c->
    <c- n>offset_ptr</c-><c- o>&amp;</c-> <c- n>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>offset_ptr</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>)</c-> <c- p>{</c->
        <c- n>value_</c-> <c- o>=</c-> <c- n>distance_to</c-><c- p>(</c-><c- n>rhs</c-><c- p>.</c-><c- n>get</c-><c- p>());</c->
        <c- k>return</c-> <c- o>*</c-><c- n>this</c-><c- p>;</c->
    <c- p>}</c->
    <c- o>~</c-><c- n>offset_ptr</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
<c- p>};</c->
</pre></small> 
   <h3 class="heading settled" id="non-trivial-sample-registry"><span class="content">Program invariant depends on <code class="highlight"><c- k>this</c-></code></span><a class="self-link" href="#non-trivial-sample-registry"></a></h3>
   <p>In the following snippet, <code class="highlight"><c- k>struct</c-> <c- n>Widget</c-></code> is relocatable, but not
trivially relocatable, because the relocation operation of destroying a <code class="highlight"><c- n>Widget</c-></code> at point A
and constructing a new <code class="highlight"><c- n>Widget</c-></code> at point B has behavior that is observably different
from a simple <code class="highlight"><c- n>memcpy</c-></code>.</p>
   <p><small></small></p>
   <small> <pre class="language-c++ highlight"><c- n>std</c-><c- o>::</c-><c- n>set</c-><c- o>&lt;</c-><c- b>void</c-> <c- o>*></c-> <c- n>registry</c-><c- p>;</c->

<c- k>struct</c-> <c- n>registered_object</c-> <c- p>{</c->
    <c- n>registered_object</c-><c- p>()</c-> <c- p>{</c-> <c- n>registry</c-><c- p>.</c-><c- n>insert</c-><c- p>(</c-><c- n>this</c-><c- p>);</c-> <c- p>}</c->
    <c- n>registered_object</c-><c- p>(</c-><c- n>registered_object</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>registered_object</c-><c- p>(</c-><c- k>const</c-> <c- n>registered_object</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>registered_object</c-><c- o>&amp;</c-> <c- n>operator</c-><c- o>=</c-><c- p>(</c-><c- n>registered_object</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>registered_object</c-><c- o>&amp;</c-> <c- n>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>registered_object</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- o>~</c-><c- n>registered_object</c-><c- p>()</c-> <c- p>{</c-> <c- n>registry</c-><c- p>.</c-><c- n>erase</c-><c- p>(</c-><c- n>this</c-><c- p>);</c-> <c- p>}</c->
<c- p>};</c->

<c- k>struct</c-> <c- nl>Widget</c-> <c- p>:</c-> <c- n>registered_object</c-> <c- p>{};</c->
</pre></small> 
   <h3 class="heading settled" id="non-trivial-sample-polymorphic"><span class="content">Polymorphic downcast effectively relies on offset-into-self</span><a class="self-link" href="#non-trivial-sample-polymorphic"></a></h3>
   <p class="note" role="note"><span>Note:</span> This section is new in P1144R5.</p>
   <p>Thanks to David Stone for this example.
In the following snippet, <code class="highlight"><c- k>struct</c-> <c- n>Base</c-></code> is relocatable, but not trivially relocatable,
because its copy constructor and assignment operator do not copy the entire state of the
right-hand object. (Notice that <code class="highlight"><c- n>pf</c-></code> is initialized with <code class="highlight"><c- n>f</c-></code>, not with a copy of <code class="highlight"><c- n>o</c-><c- p>.</c-><c- n>pf</c-></code>.)</p>
<pre class="highlight"><c- k>struct</c-> <c- n>Base</c-> <c- p>{</c->
    <c- k>static</c-> <c- b>int</c-> <c- n>f</c-><c- p>(</c-><c- n>Base</c-><c- o>*</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- mi>21</c-><c- p>;</c-> <c- p>}</c->
    <c- b>int</c-> <c- p>(</c-><c- o>*</c-><c- n>pf</c-><c- p>)(</c-><c- n>Base</c-><c- o>*</c-><c- p>);</c->
    <c- n>Base</c-><c- p>(</c-><c- b>int</c-> <c- p>(</c-><c- o>*</c-><c- n>pf</c-><c- p>)(</c-><c- n>Base</c-><c- o>*</c-><c- p>)</c-> <c- o>=</c-> <c- n>f</c-><c- p>)</c-> <c- o>:</c-> <c- n>pf</c-><c- p>(</c-><c- n>pf</c-><c- p>)</c-> <c- p>{}</c->
    <c- n>Base</c-><c- p>(</c-><c- k>const</c-> <c- n>Base</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- o>:</c-> <c- n>pf</c-><c- p>(</c-><c- n>f</c-><c- p>)</c-> <c- p>{}</c->
    <c- n>Base</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>Base</c-><c- o>&amp;</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- o>*</c-><c- k>this</c-><c- p>;</c-> <c- p>}</c->
<c- p>};</c->
<c- k>struct</c-> <c- nl>Derived</c-> <c- p>:</c-> <c- n>Base</c-> <c- p>{</c->
    <c- k>static</c-> <c- b>int</c-> <c- n>f</c-><c- p>(</c-><c- n>Base</c-> <c- o>*</c-><c- n>self</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- p>((</c-><c- n>Derived</c-><c- o>*</c-><c- p>)</c-><c- n>self</c-><c- p>)</c-><c- o>-></c-><c- n>x</c-><c- p>;</c-> <c- p>}</c->
    <c- n>Derived</c-><c- p>()</c-> <c- o>:</c-> <c- n>Base</c-><c- p>(</c-><c- n>f</c-><c- p>)</c-> <c- p>{}</c->
    <c- n>Derived</c-><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>Derived</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>Derived</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- p>{</c-> <c- n>x</c-> <c- o>=</c-> <c- n>o</c-><c- p>.</c-><c- n>x</c-><c- p>;</c-> <c- k>return</c-> <c- o>*</c-><c- k>this</c-><c- p>;</c-> <c- p>}</c->
    <c- b>int</c-> <c- n>x</c-> <c- o>=</c-> <c- mi>42</c-><c- p>;</c->
<c- p>};</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
    <c- n>Base</c-><c- o>&amp;&amp;</c-> <c- n>d</c-> <c- o>=</c-> <c- n>Derived</c-><c- p>();</c->
    <c- n>Base</c-><c- o>&amp;&amp;</c-> <c- n>b</c-> <c- o>=</c-> <c- n>Base</c-><c- p>();</c->
    <c- n>std</c-><c- o>::</c-><c- n>swap</c-><c- p>(</c-><c- n>b</c-><c- p>,</c-> <c- n>d</c-><c- p>);</c->
    <c- n>printf</c-><c- p>(</c-><c- s>"%d</c-><c- se>\n</c-><c- s>"</c-><c- p>,</c-> <c- n>b</c-><c- p>.</c-><c- n>pf</c-><c- p>(</c-><c- o>&amp;</c-><c- n>b</c-><c- p>));</c->
<c- p>}</c->
</pre>
   <p>The above snippet is isomorphic to a classically polymorphic hierarchy
with virtual methods. Here is the same snippet using <code class="highlight"><c- k>virtual</c-></code>:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>Base</c-> <c- p>{</c->
    <c- k>virtual</c-> <c- b>int</c-> <c- n>f</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- mi>21</c-><c- p>;</c-> <c- p>}</c->
<c- p>};</c->
<c- k>struct</c-> <c- nl>Derived</c-> <c- p>:</c-> <c- n>Base</c-> <c- p>{</c->
    <c- b>int</c-> <c- n>f</c-><c- p>()</c-> <c- k>override</c-> <c- p>{</c-> <c- k>return</c-> <c- n>x</c-><c- p>;</c-> <c- p>}</c->
    <c- b>int</c-> <c- n>x</c-> <c- o>=</c-> <c- mi>42</c-><c- p>;</c->
<c- p>};</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
    <c- n>Base</c-><c- o>&amp;&amp;</c-> <c- n>b</c-> <c- o>=</c-> <c- n>Base</c-><c- p>();</c->
    <c- n>Base</c-><c- o>&amp;&amp;</c-> <c- n>d</c-> <c- o>=</c-> <c- n>Derived</c-><c- p>();</c->
    <c- n>std</c-><c- o>::</c-><c- n>swap</c-><c- p>(</c-><c- n>b</c-><c- p>,</c-> <c- n>d</c-><c- p>);</c->
    <c- n>printf</c-><c- p>(</c-><c- s>"%d</c-><c- se>\n</c-><c- s>"</c-><c- p>,</c-> <c- n>b</c-><c- p>.</c-><c- n>f</c-><c- p>());</c->
<c- p>}</c->
</pre>
   <p>This is why (as of P1144R5) the compiler will not consider types with
virtual methods to be "naturally" trivially relocatable.</p>
   <h2 class="heading settled" id="implementation"><span class="content">Appendix D: Implementation experience</span><a class="self-link" href="#implementation"></a></h2>
   <p>A prototype Clang/libc++ implementation is at</p>
   <ul>
    <li data-md>
     <p><a href="https://github.com/Quuxplusone/llvm-project/tree/trivially-relocatable">github.com/Quuxplusone/llvm-project/tree/trivially-relocatable</a></p>
    <li data-md>
     <p><a href="https://p1144.godbolt.org/z/oWEd_X">godbolt.org</a>, under the name "x86-64 clang (experimental P1144)"</p>
    <li data-md>
     <p><a href="https://reviews.llvm.org/D50119">reviews.llvm.org/D50119</a></p>
   </ul>
   <p>Side-by-side case studies of <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-></code>, <code class="highlight"><c- p>[[</c-><c- n>maybe_trivially_relocatable</c-><c- p>]]</c-></code>,
and <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code> are given in <a href="#sample-conditional">Conditionally trivial relocation</a>.</p>
   <p>As of November 2018, libstdc++ performs the <code class="highlight"><c- n>vector</c-><c- o>::</c-><c- n>resize</c-></code> optimization
for any type which has manually specialized <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>__is_bitwise_relocatable</c-></code>.
(See it on godbolt.org <a href="https://godbolt.org/z/hvx5bg">here</a>.)
Manual specialization is also the approach used by <a data-link-type="biblio" href="#biblio-eastl">[EASTL]</a>, <a data-link-type="biblio" href="#biblio-folly">[Folly]</a>, and <a data-link-type="biblio" href="#biblio-bsl">[BSL]</a>.
As of 2020-03-01, the only libstdc++ library type for which <code class="highlight"><c- n>__is_bitwise_relocatable</c-></code> has
been specialized is <code class="highlight"><c- n>deque</c-></code>; see <a data-link-type="biblio" href="#biblio-deque">[Deque]</a> and <a href="#nothrow-relocatable">§ 6.5 Unintuitive is_nothrow_relocatable</a>.</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="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="#abstract-opdef-relocation-operation">relocation operation</a><span>, in §5.1</span>
   <li><a href="#abstract-opdef-trivially-relocatable">trivially relocatable</a><span>, in §5.5</span>
  </ul>
  <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-n4800">[N4800]
   <dd>Richard Smith. <a href="https://wg21.link/n4800">Working Draft, Standard for Programming Language C++</a>. 21 January 2019. URL: <a href="https://wg21.link/n4800">https://wg21.link/n4800</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-announcing">[Announcing]
   <dd>Arthur O'Dwyer. <a href="https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/">Announcing "trivially relocatable"</a>. July 2018. URL: <a href="https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/">https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/</a>
   <dt id="biblio-bench">[Bench]
   <dd>Arthur O'Dwyer. <a href="https://github.com/Quuxplusone/from-scratch/blob/095b246d/cppnow2018/benchmark-relocatable.cc">Benchmark code from "The Best Type Traits C++ Doesn't Have"</a>. April 2018. URL: <a href="https://github.com/Quuxplusone/from-scratch/blob/095b246d/cppnow2018/benchmark-relocatable.cc">https://github.com/Quuxplusone/from-scratch/blob/095b246d/cppnow2018/benchmark-relocatable.cc</a>
   <dt id="biblio-boostinterprocess">[Boost.Interprocess]
   <dd>Ion Gaztañaga. <a href="https://www.boost.org/doc/libs/1_67_0/doc/html/interprocess/offset_ptr.html">Mapping Address Independent Pointer: offset_ptr</a>. 2005. URL: <a href="https://www.boost.org/doc/libs/1_67_0/doc/html/interprocess/offset_ptr.html">https://www.boost.org/doc/libs/1_67_0/doc/html/interprocess/offset_ptr.html</a>
   <dt id="biblio-bsl">[BSL]
   <dd>Bloomberg. <a href="https://github.com/bloomberg/bde/blob/master/groups/bsl/bslmf/bslmf_isbitwisemoveable.h#L17">bslmf::IsBitwiseMoveable: bitwise moveable trait metafunction</a>. 2013–2017. URL: <a href="https://github.com/bloomberg/bde/blob/master/groups/bsl/bslmf/bslmf_isbitwisemoveable.h#L17">https://github.com/bloomberg/bde/blob/master/groups/bsl/bslmf/bslmf_isbitwisemoveable.h#L17</a>
   <dt id="biblio-contra">[Contra]
   <dd>Arthur O'Dwyer. <a href="https://quuxplusone.github.io/blog/2018/04/15/built-in-library-types/">Contra built-in library types</a>. April 2018. URL: <a href="https://quuxplusone.github.io/blog/2018/04/15/built-in-library-types/">https://quuxplusone.github.io/blog/2018/04/15/built-in-library-types/</a>
   <dt id="biblio-cppchat">[CppChat]
   <dd>Howard Hinnant; Arthur O'Dwyer. <a href="https://www.youtube.com/watch?v=8u5Qi4FgTP8">cpp.chat episode 40: It works but it's undefined behavior</a>. August 2018. URL: <a href="https://www.youtube.com/watch?v=8u5Qi4FgTP8">https://www.youtube.com/watch?v=8u5Qi4FgTP8</a>
   <dt id="biblio-d50119">[D50119]
   <dd>Arthur O'Dwyer; Nicolas Lesser; John McCall. <a href="https://reviews.llvm.org/D50119">Compiler support for P1144R0 __is_trivially_relocatable(T)</a>. July 2018. URL: <a href="https://reviews.llvm.org/D50119">https://reviews.llvm.org/D50119</a>
   <dt id="biblio-deque">[Deque]
   <dd>Marc Glisse. <a href="https://github.com/gcc-mirror/gcc/commit/a9b9381580de611126c9888c1a6c12a77d9b682e">Improve relocation ... (__is_trivially_relocatable): Specialize for deque</a>. November 2018. URL: <a href="https://github.com/gcc-mirror/gcc/commit/a9b9381580de611126c9888c1a6c12a77d9b682e">https://github.com/gcc-mirror/gcc/commit/a9b9381580de611126c9888c1a6c12a77d9b682e</a>
   <dt id="biblio-eastl">[EASTL]
   <dd>Paul Pedriana. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#type_traits_extensions">N2271: EASTL — Electronic Arts Standard Template Library</a>. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#type_traits_extensions">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#type_traits_extensions</a>
   <dt id="biblio-fixedcapacityvector">[FixedCapacityVector]
   <dd>Arthur O'Dwyer. <a href="https://quuxplusone.github.io/blog/2019/02/22/p1144-fixed-capacity-vector/">P1144 case study: Moving a `fixed_capacity_vector`</a>. URL: <a href="https://quuxplusone.github.io/blog/2019/02/22/p1144-fixed-capacity-vector/">https://quuxplusone.github.io/blog/2019/02/22/p1144-fixed-capacity-vector/</a>
   <dt id="biblio-folly">[Folly]
   <dd>Facebook. <a href="https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation">Folly documentation on "Object Relocation"</a>. URL: <a href="https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation">https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation</a>
   <dt id="biblio-follyissue889">[FollyIssue889]
   <dd>Arthur O'Dwyer. <a href="https://github.com/facebook/folly/issues/889">Traits.h marks std::list as trivially relocatable, but in fact it is not</a>. URL: <a href="https://github.com/facebook/folly/issues/889">https://github.com/facebook/folly/issues/889</a>
   <dt id="biblio-libcxxany">[LibcxxAny]
   <dd>Eric Fiselier. <a href="https://github.com/llvm-mirror/libcxx/blob/8fdc4918/include/any#L389-L394">libc++ implementation of std::any (trivially relocatable)</a>. July 2016. URL: <a href="https://github.com/llvm-mirror/libcxx/blob/8fdc4918/include/any#L389-L394">https://github.com/llvm-mirror/libcxx/blob/8fdc4918/include/any#L389-L394</a>
   <dt id="biblio-libcxxfunction">[LibcxxFunction]
   <dd>Howard Hinnant et al. <a href="https://github.com/llvm-mirror/libcxx/blob/4e7ffcaa/include/functional#L1719-L1734">libc++ implementation of std::function (non-trivially relocatable)</a>. URL: <a href="https://github.com/llvm-mirror/libcxx/blob/4e7ffcaa/include/functional#L1719-L1734">https://github.com/llvm-mirror/libcxx/blob/4e7ffcaa/include/functional#L1719-L1734</a>
   <dt id="biblio-libstdcxxfunction">[LibstdcxxFunction]
   <dd>Doug Gregor et al. <a href="https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_function.h">libstdc++ implementation of std::function (trivially relocatable)</a>. URL: <a href="https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_function.h">https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/std_function.h</a>
   <dt id="biblio-n1377">[N1377]
   <dd>Howard Hinnant; Peter Dimov; Dave Abrahams. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">N1377: A Proposal to Add Move Semantics Support to the C++ Language</a>. September 2002. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm</a>
   <dt id="biblio-n2754">[N2754]
   <dd>Rodrigo Castro Campos. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2754.html">N2754: TriviallyDestructibleAfterMove and TriviallyReallocatable (rev 3)</a>. September 2008. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2754.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2754.html</a>
   <dt id="biblio-n4158">[N4158]
   <dd>Pablo Halpern. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf">N4158: Destructive Move (rev 1)</a>. October 2014. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf</a>
   <dt id="biblio-p0023r0">[P0023R0]
   <dd>Denis Bider. <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0023r0.pdf">P0023R0: Relocator: Efficiently Moving Objects</a>. April 2016. URL: <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0023r0.pdf">http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0023r0.pdf</a>
   <dt id="biblio-p0593r3">[P0593R3]
   <dd>Richard Smith. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0593r3.html">P0593R3: Implicit creation of objects for low-level object manipulation</a>. January 2019. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0593r3.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0593r3.html</a>
   <dt id="biblio-p0884r0">[P0884R0]
   <dd>Nicolai Josuttis. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0884r0.pdf">P0884R0: Extending the noexcept Policy, Rev. 0</a>. February 2018. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0884r0.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0884r0.pdf</a>
   <dt id="biblio-p1007r3">[P1007R3]
   <dd>Timur Doumler; Chandler Carruth. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf">P1007R3: std::assume_aligned</a>. November 2018. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf</a>
   <dt id="biblio-p1029r3">[P1029R3]
   <dd>Niall Douglas. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1029r3.pdf">P1029R3: move = bitcopies</a>. January 2020. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1029r3.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1029r3.pdf</a>
   <dt id="biblio-p2025r0">[P2025R0]
   <dd>Anton Zhilin. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2025r0.html">Guaranteed copy elision for named return objects</a>. January 2020. URL: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2025r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2025r0.html</a>
   <dt id="biblio-subobjects">[Subobjects]
   <dd>Arthur O'Dwyer. <a href="https://quuxplusone.github.io/blog/2018/07/13/trivially-copyable-corner-cases/">When is a trivially copyable object not trivially copyable?</a>. July 2018. URL: <a href="https://quuxplusone.github.io/blog/2018/07/13/trivially-copyable-corner-cases/">https://quuxplusone.github.io/blog/2018/07/13/trivially-copyable-corner-cases/</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"> [definitions] is probably the wrong place for the core-language definition of "relocation operation"<a href="#issue-75ffe201"> ↵ </a></div>
   <div class="issue"> this definition of "relocation operation" is not good<a href="#issue-7c86f5f7"> ↵ </a></div>
   <div class="issue"> The relevant move constructor, copy constructor, and/or destructor must be public and unambiguous.
We imply this via the words "A move-constructible, destructible object type". However, "move-constructible"
and "destructible" are library concepts, not core language concepts, so it is inappropriate
to use them here.<a href="#issue-3121e1d2"> ↵ </a></div>
   <div class="issue">
     Consider the following test cases—<wbr><small> <pre class="language-c++ highlight">    <c- k>struct</c-> <c- n>A</c-> <c- p>{</c->
        <c- k>struct</c-> <c- n>MA</c-> <c- p>{</c->
            <c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;</c-><c- p>);</c->
            <c- n>MA</c-><c- p>(</c-><c- k>const</c-> <c- n>MA</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
            <c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
        <c- p>};</c->
        <c- n>mutable</c-> <c- n>MA</c-> <c- n>ma</c-><c- p>;</c->
        <c- n>A</c-><c- p>(</c-><c- k>const</c-> <c- n>A</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>A</c-><c- o>></c-><c- p>);</c->

    <c- k>struct</c-> <c- n>B</c-> <c- p>{</c->
        <c- k>struct</c-> <c- n>MB</c-> <c- p>{</c->
            <c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- k>volatile</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>);</c->
            <c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
            <c- n>MB</c-><c- p>(</c-><c- n>MB</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
        <c- p>};</c->
        <c- k>volatile</c-> <c- n>MB</c-> <c- n>mb</c-><c- p>;</c->
        <c- n>B</c-><c- p>(</c-><c- k>const</c-> <c- n>B</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>B</c-><c- o>></c-><c- p>);</c->

    <c- k>struct</c-> <c- n>H</c-> <c- p>{</c->
        <c- n>H</c-><c- p>(</c-><c- n>H</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>]]</c-> <c- n>I</c-> <c- p>{</c->
        <c- n>I</c-><c- p>(</c-><c- n>I</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- n>template</c-><c- o>&lt;</c-><c- b>bool</c-> <c- n>Cond</c-><c- o>></c->
    <c- k>struct</c-> <c- nl>J</c-> <c- p>:</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>Cond</c-><c- p>,</c-> <c- n>H</c-><c- p>,</c-> <c- n>I</c-><c- o>></c-> <c- p>{</c->
        <c- n>J</c-><c- p>(</c-><c- k>const</c-> <c- n>J</c-><c- o>&amp;</c-><c- p>);</c->
        <c- n>J</c-><c- p>(</c-><c- n>J</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- p>};</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->false<c- o>>></c-><c- p>);</c->
    <c- n>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->true<c- o>>></c-><c- p>);</c->
</pre></small> We <em>must</em> find a rule that makes neither <code class="highlight"><c- n>A</c-></code> nor <code class="highlight"><c- n>B</c-></code> trivially relocatable,
because the move-construction <code class="highlight"><c- n>A</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>a</c-><c- p>))</c-></code> invokes user-provided copy constructor <code class="highlight"><c- n>MA</c-><c- p>(</c-><c- n>MA</c-><c- o>&amp;</c-><c- p>)</c-></code> and the move-construction <code class="highlight"><c- n>B</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>b</c-><c- p>))</c-></code> invokes user-provided copy constructor <code class="highlight"><c- n>MB</c-><c- p>(</c-><c- k>const</c-> <c- k>volatile</c-> <c- n>MB</c-><c- o>&amp;</c-><c- p>)</c-></code>.
Prior to P1144R3, the rule was that <code class="highlight"><c- k>mutable</c-></code> and <code class="highlight"><c- k>volatile</c-></code> data members
inhibited "natural" trivial relocatability. As of P1144R3, the rule is that
any user-provided copy constructor inhibits trivial relocatability (even in the
presence of a defaulted move constructor). 
    <p>In P1144R2, I tried to find a rule that makes <code class="highlight"><c- n>J</c-></code> trivially relocatable,
because the <code class="highlight"><c- nl>J</c-> <c- p>:</c-> <c- n>I</c-></code> pattern was used to implement "conditionally trivial relocatability"
for all allocator-aware containers in my libc++ reference implementation.
However, this paper adopts the <code class="highlight"><c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- b>bool</c-><c- p>)]]</c-></code> syntax, which
means that we don’t need to care about <code class="highlight"><c- nl>J</c-> <c- p>:</c-> <c- n>I</c-></code> anymore. The new way to write <code class="highlight"><c- n>J</c-></code> is simply <small></small></p>
    <small> <pre class="highlight">    <c- k>template</c-><c- o>&lt;</c-><c- b>bool</c-> <c- n>Cond</c-><c- o>></c->
    <c- k>struct</c-> <c- p>[[</c-><c- n>trivially_relocatable</c-><c- p>(</c-><c- o>!</c-><c- n>Cond</c-><c- p>)]]</c-> <c- n>J</c-> <c- p>{</c->
        <c- n>J</c-><c- p>(</c-><c- n>J</c-><c- o>&amp;&amp;</c-><c- p>);</c->
        <c- n>J</c-><c- p>(</c-><c- k>const</c-> <c- n>J</c-><c- o>&amp;</c-><c- p>);</c->
    <c- p>};</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->false<c- o>>></c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>not</c-> <c- n>std</c-><c- o>::</c-><c- n>is_trivially_relocatable_v</c-><c- o>&lt;</c-><c- n>J</c-><c- o>&lt;</c->true<c- o>>></c-><c- p>);</c->
</pre></small> <a href="#issue-7b712591"> ↵ </a>
   </div>
   <div class="issue"> "If a type <code class="highlight"><c- n>T</c-></code> is declared with the <code class="highlight"><c- n>trivially_relocatable</c-></code> attribute, and <code class="highlight"><c- n>T</c-></code> is either not move-constructible
or not destructible, the program is ill-formed." We might want to replace this wording with
a mere "Note" <em>encouraging</em> implementations to diagnose.
See <a href="https://p1144.godbolt.org/z/ociAVX">this example</a> where a diagnostic might be unwanted.<a href="#issue-20b76dab"> ↵ </a></div>
   <div class="issue"> The semantic requirements of this concept are poorly worded. We intend that a type may be relocatable
regardless of whether it is copy-constructible; but, if it is copy-constructible then copy-and-destroy
must have the same semantics as move-and-destroy. We intend that a type may be relocatable regardless of
whether it is assignable; but, if it is assignable then assignment must have the same semantics as
destroy-and-copy or destroy-and-move.<a href="#issue-2fea1ba9"> ↵ </a></div>
   <div class="issue"> The next time this paper is seen, Anton Zhilin would like us to take a straw poll
on whether it should be possible to create a type which is "trivially relocatable, but not move-constructible."
Currently P1144 does not permit such a thing; relocatability here is defined as a superset of move-constructibility.<a href="#issue-8c46923c"> ↵ </a></div>
  </div>
  <aside class="dfn-panel" data-for="abstract-opdef-relocation-operation">
   <b><a href="#abstract-opdef-relocation-operation">#abstract-opdef-relocation-operation</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-relocation-operation">5.5. Trivially relocatable type</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="abstract-opdef-trivially-relocatable">
   <b><a href="#abstract-opdef-trivially-relocatable">#abstract-opdef-trivially-relocatable</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-trivially-relocatable">2. Introduction and motivation</a>
    <li><a href="#ref-for-abstract-opdef-trivially-relocatable①">5.7. Type traits is_relocatable etc.</a>
   </ul>
  </aside>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script>