<!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>P2025R1: Guaranteed copy elision for return variables</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 40de15f9, updated Thu Jun 11 17:47:04 2020 -0700" name="generator">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
<style>
ins {
  background-color: #CCFFCC;
  text-decoration: none;
}
del {
  background-color: #FFCACA;
  text-decoration: none;
}
.warning-note {
  background-color: #FCFAEE;
  border-color: #E0CB52;
  overflow-x: auto;
  overflow-y: auto;
  clear: both;
}
</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-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-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-line-numbers */

.line-numbered {
    display: grid !important;
    grid-template-columns: min-content 1fr;
    grid-auto-flow: row;
}
.line-numbered > *,
.line-numbered::before,
.line-numbered::after {
    grid-column: 1/-1;
}
.line-no {
    grid-column: 1;
    color: gray;
}
.line {
    grid-column: 2;
}
.line:hover {
    background: rgba(0,0,0,.05);
}
.line-no[data-line]::before {
    padding: 0 .5em 0 .1em;
    content: attr(data-line);
}
.line-no[data-line-end]::after {
    padding: 0 .5em 0 .1em;
    content: attr(data-line-end);
}
</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-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">P2025R1<br>Guaranteed copy elision for return variables</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Draft Proposal, <time class="dt-updated" datetime="2020-06-15">2020-06-15</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:antonyzhilin@gmail.com">Anton Zhilin</a>
     <dt>Audience:
     <dd>EWG, CWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Current Source:
     <dd><a href="https://github.com/Anton3/cpp-proposals/blob/master/published/p2025r1.bs">https://github.com/Anton3/cpp-proposals/blob/master/published/p2025r1.bs</a>
     <dt>Current:
     <dd><a href="https://github.com/Anton3/cpp-proposals/blob/master/published/p2025r1.html">https://github.com/Anton3/cpp-proposals/blob/master/published/p2025r1.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>This proposal aims to provide guaranteed copy elision for common cases of local variables being returned from a function, a.k.a. "guaranteed NRVO".</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="#revision"><span class="secno">1</span> <span class="content">Revision history</span></a>
    <li><a href="#introduction"><span class="secno">2</span> <span class="content">Introduction</span></a>
    <li>
     <a href="#motivation"><span class="secno">3</span> <span class="content">Motivation</span></a>
     <ol class="toc">
      <li><a href="#construct-cook-return"><span class="secno">3.1</span> <span class="content">Construct-cook-return</span></a>
      <li><a href="#construct-cleanup-return"><span class="secno">3.2</span> <span class="content">Construct-cleanup-return</span></a>
      <li><a href="#operator-rewrites"><span class="secno">3.3</span> <span class="content">Operator rewrites</span></a>
     </ol>
    <li>
     <a href="#proposal"><span class="secno">4</span> <span class="content">Proposed solution</span></a>
     <ol class="toc">
      <li>
       <a href="#examples"><span class="secno">4.1</span> <span class="content">Examples</span></a>
       <ol class="toc">
        <li><a href="#ex-1"><span class="secno">4.1.1</span> <span class="content">Example 1</span></a>
        <li><a href="#ex-2"><span class="secno">4.1.2</span> <span class="content">Example 2</span></a>
        <li><a href="#ex-3"><span class="secno">4.1.3</span> <span class="content">Example 3</span></a>
        <li><a href="#ex-4"><span class="secno">4.1.4</span> <span class="content">Example 4</span></a>
        <li><a href="#ex-5"><span class="secno">4.1.5</span> <span class="content">Example 5</span></a>
        <li><a href="#ex-6"><span class="secno">4.1.6</span> <span class="content">Example 6</span></a>
        <li><a href="#ex-7"><span class="secno">4.1.7</span> <span class="content">Example 7</span></a>
        <li><a href="#ex-8"><span class="secno">4.1.8</span> <span class="content">Example 8</span></a>
        <li><a href="#ex-9"><span class="secno">4.1.9</span> <span class="content">Example 9</span></a>
        <li><a href="#ex-10"><span class="secno">4.1.10</span> <span class="content">Example 10</span></a>
        <li><a href="#ex-11"><span class="secno">4.1.11</span> <span class="content">Example 11</span></a>
        <li><a href="#ex-12"><span class="secno">4.1.12</span> <span class="content">Example 12</span></a>
        <li><a href="#ex-13"><span class="secno">4.1.13</span> <span class="content">Example 13</span></a>
        <li><a href="#ex-14"><span class="secno">4.1.14</span> <span class="content">Example 14</span></a>
        <li><a href="#ex-15"><span class="secno">4.1.15</span> <span class="content">Example 15</span></a>
        <li><a href="#ex-16"><span class="secno">4.1.16</span> <span class="content">Example 16</span></a>
        <li><a href="#ex-17"><span class="secno">4.1.17</span> <span class="content">Example 17</span></a>
        <li><a href="#ex-18"><span class="secno">4.1.18</span> <span class="content">Example 18</span></a>
        <li><a href="#ex-19"><span class="secno">4.1.19</span> <span class="content">Example 19</span></a>
        <li><a href="#ex-20"><span class="secno">4.1.20</span> <span class="content">Example 20</span></a>
       </ol>
     </ol>
    <li>
     <a href="#wording"><span class="secno">5</span> <span class="content">Proposed wording</span></a>
     <ol class="toc">
      <li><a href="#wording-definitions"><span class="secno">5.1</span> <span class="content">Definitions</span></a>
      <li><a href="#wording-behavior"><span class="secno">5.2</span> <span class="content">The behavior of return variables</span></a>
      <li><a href="#wording-refs"><span class="secno">5.3</span> <span class="content">Cross-references</span></a>
      <li><a href="#wording-non-class"><span class="secno">5.4</span> <span class="content">Returning non-class types</span></a>
     </ol>
    <li>
     <a href="#faq"><span class="secno">6</span> <span class="content">Discussion</span></a>
     <ol class="toc">
      <li><a href="#term"><span class="secno">6.1</span> <span class="content">Is "return variable" a good term choice?</span></a>
      <li>
       <a href="#req-change"><span class="secno">6.2</span> <span class="content">Have requirements for copy elision changed?</span></a>
       <ol class="toc">
        <li><a href="#req-parentheses"><span class="secno">6.2.1</span> <span class="content">Parentheses are now allowed around the variable name</span></a>
        <li><a href="#req-lambda"><span class="secno">6.2.2</span> <span class="content">Copy elision is no longer allowed for lambda captures</span></a>
        <li><a href="#req-value-exeptions"><span class="secno">6.2.3</span> <span class="content">Exception-declarations can introduce return variables</span></a>
       </ol>
      <li><a href="#trivial-temporaries"><span class="secno">6.3</span> <span class="content">What about trivially copyable temporaries?</span></a>
      <li><a href="#non-class"><span class="secno">6.4</span> <span class="content">What about copy elision for non-class types?</span></a>
      <li>
       <a href="#invalidation"><span class="secno">6.5</span> <span class="content">What about the invalidation of optimizations?</span></a>
       <ol class="toc">
        <li><a href="#escape-analysis"><span class="secno">6.5.1</span> <span class="content">Complication of escape analysis</span></a>
       </ol>
      <li><a href="#abi"><span class="secno">6.6</span> <span class="content">Are the proposed changes source or ABI breaking?</span></a>
      <li><a href="#costs"><span class="secno">6.7</span> <span class="content">What are the costs associated with the proposed changes?</span></a>
     </ol>
    <li>
     <a href="#implementation"><span class="secno">7</span> <span class="content">Implementation experience</span></a>
     <ol class="toc">
      <li><a href="#implementation-exceptions"><span class="secno">7.1</span> <span class="content">How to deal with exceptions?</span></a>
      <li><a href="#implementation-strategy"><span class="secno">7.2</span> <span class="content">An exception-safe implementation strategy</span></a>
      <li><a href="#potential-elision"><span class="secno">7.3</span> <span class="content">When is copy elision for potential return variables feasible?</span></a>
      <li><a href="#implementation-circle"><span class="secno">7.4</span> <span class="content">A proof of concept implementation in Circle</span></a>
     </ol>
    <li>
     <a href="#alternatives"><span class="secno">8</span> <span class="content">Alternative solutions</span></a>
     <ol class="toc">
      <li><a href="#existing-features"><span class="secno">8.1</span> <span class="content">Implement similar functionality using existing features</span></a>
      <li><a href="#more-nrvo"><span class="secno">8.2</span> <span class="content">"Guarantee NRVO" in more cases</span></a>
      <li><a href="#explicit-mark"><span class="secno">8.3</span> <span class="content">Require an explicit mark for return variables</span></a>
      <li><a href="#alias-expressions"><span class="secno">8.4</span> <span class="content">Alias expressions</span></a>
     </ol>
    <li>
     <a href="#future-work"><span class="secno">9</span> <span class="content">Future work</span></a>
     <ol class="toc">
      <li><a href="#more-elision"><span class="secno">9.1</span> <span class="content">Guarantee some other types of copy elision</span></a>
      <li><a href="#disallowed-elision"><span class="secno">9.2</span> <span class="content">Guarantee currently disallowed types of copy elision</span></a>
      <li><a href="#other-moves"><span class="secno">9.3</span> <span class="content">Reduce the number of moves performed in other cases</span></a>
      <li><a href="#more-temporaries"><span class="secno">9.4</span> <span class="content">Allow temporaries to be created for types other than trivially-copyables</span></a>
      <li><a href="#pin"><span class="secno">9.5</span> <span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pin</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> class</span></a>
      <li><a href="#optional-mark"><span class="secno">9.6</span> <span class="content">Add an optional mark <code class="highlight"><c- p>[[</c-><c- n>nrvo_verify</c-><c- p>]]</c-></code></span></a>
      <li><a href="#complex-expressions"><span class="secno">9.7</span> <span class="content">Allow copy elision for complex expressions</span></a>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">10</span> <span class="content">Acknowledgements</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="revision"><span class="secno">1. </span><span class="content">Revision history</span><a class="self-link" href="#revision"></a></h2>
   <p>R1 (post-Prague):</p>
   <ul>
    <li data-md>
     <p>The proposal has been rewritten from scratch</p>
    <li data-md>
     <p>Renamed "named return object" to "return variable"</p>
    <li data-md>
     <p>Rewrote <a href="#wording">§ 5 Proposed wording</a> completely</p>
    <li data-md>
     <p>Fixed an issue where <code class="highlight"><c- k>return</c-></code> statements in nested lambdas affected copy elision</p>
    <li data-md>
     <p>Fixed an issue where the function return object was seemingly constructed and destroyed multiple times</p>
    <li data-md>
     <p>Fixed the invalidation of optimizations: <a href="#invalidation">§ 6.5 What about the invalidation of optimizations?</a></p>
    <li data-md>
     <p>Applied several fixes to copy elision requirements: <a href="#req-change">§ 6.2 Have requirements for copy elision changed?</a></p>
    <li data-md>
     <p>Moved the wording for guaranteed copy elision to <a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a></p>
    <li data-md>
     <p>Used the same terms for copy elision and guaranteed copy elision</p>
    <li data-md>
     <p>Allowed copy elision for non-class types: <a href="#non-class">§ 6.4 What about copy elision for non-class types?</a></p>
    <li data-md>
     <p>Added some wording for trivially copyable types and expanded <a href="#trivial-temporaries">§ 6.3 What about trivially copyable temporaries?</a> section</p>
    <li data-md>
     <p>Clarified the intent of allowing non-copyable, non-movable types: <a href="#proposal">§ 4 Proposed solution</a></p>
    <li data-md>
     <p>Added the <a href="#introduction">§ 2 Introduction</a> section</p>
    <li data-md>
     <p>Expanded the <a href="#motivation">§ 3 Motivation</a> section</p>
    <li data-md>
     <p>Added more <a href="#examples">§ 4.1 Examples</a></p>
    <li data-md>
     <p>Added the <a href="#escape-analysis">§ 6.5.1 Complication of escape analysis</a> subsection</p>
    <li data-md>
     <p>Added the <a href="#pin">§ 9.5 std::pin&lt;T> class</a> subsection</p>
    <li data-md>
     <p>Added the <a href="#more-temporaries">§ 9.4 Allow temporaries to be created for types other than trivially-copyables</a> subsection</p>
    <li data-md>
     <p>Expanded the <a href="#explicit-mark">§ 8.3 Require an explicit mark for return variables</a> subsection</p>
    <li data-md>
     <p>Added the <a href="#optional-mark">§ 9.6 Add an optional mark [[nrvo_verify]]</a> subsection</p>
    <li data-md>
     <p>Added the <a href="#complex-expressions">§ 9.7 Allow copy elision for complex expressions</a> subsection</p>
    <li data-md>
     <p>Added the <a href="#implementation">§ 7 Implementation experience</a> section</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="introduction"><span class="secno">2. </span><span class="content">Introduction</span><a class="self-link" href="#introduction"></a></h2>
   <p>When a function cannot carry its result in registers, implementations add a hidden parameter containing the address of the caller-owned <em>return slot</em> (which is usually an object in the C++ sense). When the function decides to return, the result of the function is stored there. For example, in C++14, 2 copies could be performed for both <code class="highlight"><c- n>foo</c-></code> and <code class="highlight"><c- n>bar</c-></code> (assuming <code class="highlight"><c- n>widget</c-></code> is not trivially copyable):</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->      <c- c1>// hidden parameter: widget* r</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>return</c-> <c- n>x</c-><c- p>;</c->         <c- c1>// copy</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- n>widget</c-> <c- nf>bar</c-><c- p>()</c-> <c- p>{</c->      <c- c1>// hidden parameter: widget* r</c-></span><span class="line-no" data-line="6"></span><span class="line">  <c- k>return</c-> <c- n>widget</c-><c- p>();</c->  <c- c1>// copy</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="8"></span><span class="line"></span><span class="line-no" data-line="9"></span><span class="line"><c- b>void</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="10"></span><span class="line">  <c- k>auto</c-> <c- n>y</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c->   <c- c1>// copy</c-></span><span class="line-no" data-line="11"></span><span class="line">  <c- k>auto</c-> <c- n>z</c-> <c- o>=</c-> <c- n>bar</c-><c- p>();</c->   <c- c1>// copy</c-></span><span class="line-no" data-line="12"></span><span class="line"><c- p>}</c-></span></pre>
   <p><code class="highlight"><c- n>x</c-></code> or <code class="highlight"><c- n>widget</c-><c- p>()</c-></code> was constructed, then copied into the return slot (<code class="highlight"><c- o>*</c-><c- n>r</c-></code>), then the return slot was copied into <code class="highlight"><c- n>y</c-></code> or <code class="highlight"><c- n>z</c-></code>. The last copy followed from the imperfect pre-C++17 value category design and is irrelevant to our purposes.</p>
   <p>The implementation could eliminate some copies under the as-if rule or as allowed by <a href="http://eel.is/c++draft/class.copy.elision#1">copy elision</a>. The copy in <code class="highlight"><c- n>bar</c-></code> could be eliminated by Unnamed Return Value Optimization (URVO) and the copy in <code class="highlight"><c- n>foo</c-></code> — by Named Return Value Optimization (NRVO): <code class="highlight"><c- n>widget</c-><c- p>()</c-></code> and <code class="highlight"><c- n>w</c-></code> would be constructed directly into the return slot. Collectively, both optimizations are sometimes known as RVO; confusingly, URVO is sometimes also called RVO. Note that all of these terms are applied to the implementation and to the physical machine, and are not defined in the Standard.</p>
   <p>The updated value category and temporary materialization rules brought by C++17 (informally known as <strong>guaranteed copy elision</strong>) mandated, among everything, that no copies or moves can be made for a returned prvalue expression (except for <a href="http://eel.is/c++draft/class.temporary">trivially copyable</a> class types). This made URVO mandatory in most cases.</p>
   <p>In C++20, the only copy allowed in the example is the one at line 3 (actually, <code class="highlight"><c- n>x</c-></code> is implicitly moved from). Copy elision (NRVO) is allowed there and is routinely performed by most compilers, but is still non-guaranteed, and the <code class="highlight"><c- n>widget</c-></code> class cannot be non-copyable non-movable. With the proposed wording, <code class="highlight"><c- n>x</c-></code> is called a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable">return variable</a>, and no copy or move is performed at line 3 — this copy evasion will also informally be called <strong>guaranteed copy elision</strong>.</p>
   <p>To differentiate between the two kinds of guaranteed copy elision, it is sometimes useful to use informal terms "guaranteed URVO" and "guaranteed NRVO", meaning the respective language features. Unless otherwise specified, "copy elision" refers to the implementation-defined copy elision provided by <a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]</a>.</p>
   <h2 class="heading settled" data-level="3" id="motivation"><span class="secno">3. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p>What follows are the examples where the absence of guaranteed copy elision for <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable">returned</a> variables enforces rewriting the code in a way that is less readable or efficient.</p>
   <h3 class="heading settled" data-level="3.1" id="construct-cook-return"><span class="secno">3.1. </span><span class="content">Construct-cook-return</span><a class="self-link" href="#construct-cook-return"></a></h3>
   <p>Sometimes we want to create an object, set it up and return it.</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>w</c-><c- p>;</c->
  <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
  <c- k>return</c-> <c- n>w</c-><c- p>;</c->  <c- c1>// move or copy elision</c->
<c- p>}</c->
</pre>
   <p>Implementations usually do perform copy elision in such simple cases, but <code class="highlight"><c- n>widget</c-></code> must be at least movable. This situation is unacceptable in these cases, among others:</p>
   <ul>
    <li data-md>
     <p>If the setup process includes taking a pointer to <code class="highlight"><c- n>w</c-></code> and storing it elsewhere</p>
    <li data-md>
     <p>If <code class="highlight"><c- n>widget</c-></code> is non-copyable non-movable, because its memory location is critically important to its functionality, e.g. <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>mutex</c-></code></p>
    <li data-md>
     <p>If <code class="highlight"><c- n>widget</c-></code> is non-copyable, because it manages resources that are not easy to copy, and non-movable, because it does not have an empty state, e.g. <code class="highlight"><c- n>open_file</c-></code> and <code class="highlight"><c- n>not_null_ptr</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code></p>
   </ul>
   <p>On practice, the workaround can be either:</p>
   <ul>
    <li data-md>
     <p>Two-stage initialization, where a local variable is constructed in its destination (e.g. using the default constructor) and is then immediately passed to function(s) by reference in order to complete the setup of the object</p>
    <li data-md>
     <p>Always storing the object on heap, e.g. by returning <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>widget</c-><c- o>></c-></code> instead of <code class="highlight"><c- n>widget</c-></code> from factory functions</p>
   </ul>
   <p>Both "solutions" are often viewed as anti-patterns. A proper solution should allow for the construct-cook-return pattern, even if a copy or move is not affordable.</p>
   <h3 class="heading settled" data-level="3.2" id="construct-cleanup-return"><span class="secno">3.2. </span><span class="content">Construct-cleanup-return</span><a class="self-link" href="#construct-cleanup-return"></a></h3>
   <p>With <a data-link-type="biblio" href="#biblio-p1144r5">[P1144R5]</a>, we may be able to relocate elements out of containers, which should be more efficient:</p>
<pre class="highlight"><c- n>widget</c-> <c- n>widget_owner</c-><c- o>::</c-><c- n>pilfer</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>w</c-> <c- o>=</c-> <c- k>this</c-><c- o>-></c-><c- n>relocate_internal</c-><c- p>();</c->
  <c- k>this</c-><c- o>-></c-><c- n>cleanup_storage</c-><c- p>();</c->
  <c- k>return</c-> <c- n>w</c-><c- p>;</c->  <c- c1>// move or copy elision</c->
<c- p>}</c->
</pre>
   <p>Unfortunately, such a clean-up work inhibits guaranteed copy elision. This can, however, be worked around using a facility like <code class="highlight"><c- n>scope_success</c-></code> from <a data-link-type="biblio" href="#biblio-p0052r9">[P0052R9]</a>:</p>
<pre class="highlight"><c- n>widget</c-> <c- n>widget_owner</c-><c- o>::</c-><c- n>pilfer</c-><c- p>()</c-> <c- p>{</c->
  <c- k>auto</c-> <c- n>s</c-> <c- o>=</c-> <c- n>scope_success</c-><c- p>([</c-><c- o>&amp;</c-><c- p>]{</c-> <c- k>this</c-><c- o>-></c-><c- n>cleanup_storage</c-><c- p>();</c-> <c- p>});</c->
  <c- k>return</c-> <c- k>this</c-><c- o>-></c-><c- n>relocate_internal</c-><c- p>();</c->  <c- c1>// guaranteed copy elision</c->
<c- p>}</c->
</pre>
   <p>The code rewritten in such a way is less straightforward and contains the potential overhead of <code class="highlight"><c- n>scope_success</c-></code>.</p>
   <h3 class="heading settled" data-level="3.3" id="operator-rewrites"><span class="secno">3.3. </span><span class="content">Operator rewrites</span><a class="self-link" href="#operator-rewrites"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p1046r2">[P1046R2]</a> proposes automatically generating <code class="highlight"><c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-></code> for a type that implements <code class="highlight"><c- k>operator</c-><c- o>+=</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-></code>. Its definition would look approximately as follows:</p>
<pre class="highlight"><c- n>T</c-> <c- n>T</c-><c- o>::</c-><c- k>operator</c-><c- o>++</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-> <c- p>{</c->
  <c- n>T</c-> <c- n>result</c-> <c- o>=</c-> <c- o>*</c-><c- k>this</c-><c- p>;</c->  <c- c1>// intended copy</c->
  <c- o>*</c-><c- k>this</c-> <c- o>+=</c-> <c- mi>1</c-><c- p>;</c->
  <c- k>return</c-> <c- n>result</c-><c- p>;</c->  <c- c1>// guaranteed copy elision wanted</c->
<c- p>}</c->
</pre>
   <p>In order to deliver on the promise of guaranteed copy elision there, we would have to use the <code class="highlight"><c- n>scope_success</c-></code> trick described above.</p>
   <h2 class="heading settled" data-level="4" id="proposal"><span class="secno">4. </span><span class="content">Proposed solution</span><a class="self-link" href="#proposal"></a></h2>
   <p>If a returned variable is of the same non-trivially-copyable class type as the return type of the function (ignoring cv-qualification), and all <a href="http://eel.is/c++draft/stmt.if#def:discarded_statement">non-discarded</a> <code class="highlight"><c- k>return</c-></code> statements in its <a href="http://eel.is/c++draft/basic.scope#def:potential_scope">potential scope</a> <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable①">return</a> the variable, guaranteed copy elision is performed. The type of the variable is allowed to be non-copyable, non-movable.</p>
   <p>(For the purposes of brevity, the explanation above is not rigorous; see <a href="#wording">§ 5 Proposed wording</a> for a rigorous explanation.)</p>
   <p>To state the gist of the main requirement even easier (and even less rigorous):</p>
   <blockquote>
    <p>Copy elision is guaranteed for <code class="highlight"><c- k>return</c-> <c- n>x</c-><c- p>;</c-></code> if every <code class="highlight"><c- k>return</c-></code> "seen" by <code class="highlight"><c- n>x</c-></code> is <code class="highlight"><c- k>return</c-> <c- n>x</c-><c- p>;</c-></code></p>
   </blockquote>
   <h3 class="heading settled" data-level="4.1" id="examples"><span class="secno">4.1. </span><span class="content">Examples</span><a class="self-link" href="#examples"></a></h3>
   <p>Suppose that <code class="highlight"><c- n>widget</c-></code> is a class type, is copy-constructible and move-constructible. Unless stated otherwise, references to copy elision utilize <a href="http://eel.is/c++draft/class.copy.elision#1.1">[class.copy.elision]/(1.1)</a>.</p>
   <p>Legend:</p>
   <ul>
    <li data-md>
     <p>✗ Old</p>
    <li data-md>
     <p>✓ Proposed</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.1" id="ex-1"><span class="secno">4.1.1. </span><span class="content">Example 1</span><a class="self-link" href="#ex-1"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>return</c-> <c- n>widget</c-><c- p>(</c-><c- n>x</c-><c- p>);</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗✓ No copies or moves needed at line 2 ("guaranteed URVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.2" id="ex-2"><span class="secno">4.1.2. </span><span class="content">Example 2</span><a class="self-link" href="#ex-2"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>auto</c-> <c- n>w</c-> <c- o>=</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 4</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 4 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.3" id="ex-3"><span class="secno">4.1.3. </span><span class="content">Example 3</span><a class="self-link" href="#ex-3"></a></h4>
   <p>Guaranteed copy elision cannot be performed at line 4, because the <code class="highlight"><c- k>return</c-></code> statement on line 6, which belongs to the potential scope of <code class="highlight"><c- n>w</c-></code>, returns non-<code class="highlight"><c- n>w</c-></code>.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c->  <c- c1>//!</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- p>}</c-> <c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="6"></span><span class="line">    <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="7"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗✓ Move (possibly elided) at line 4</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.4" id="ex-4"><span class="secno">4.1.4. </span><span class="content">Example 4</span><a class="self-link" href="#ex-4"></a></h4>
   <p>The example above can be "fixed" so that guaranteed copy elision is performed. Now all the <code class="highlight"><c- k>return</c-></code> statements within the potential scope of <code class="highlight"><c- n>w</c-></code> (the one on line 4) return <code class="highlight"><c- n>w</c-></code>.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- p>}</c-> <c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="6"></span><span class="line">    <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="7"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 4</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 4 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.5" id="ex-5"><span class="secno">4.1.5. </span><span class="content">Example 5</span><a class="self-link" href="#ex-5"></a></h4>
   <p>Guaranteed copy elision cannot be performed at line 6, because the <code class="highlight"><c- k>return</c-></code> statement on line 4, which belongs to the potential scope of <code class="highlight"><c- n>w</c-></code>, returns non-<code class="highlight"><c- n>w</c-></code>.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  …</span><span class="line-no" data-line="4"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- p>{};</c-></span><span class="line-no" data-line="5"></span><span class="line">  …</span><span class="line-no" data-line="6"></span><span class="line">  <c- k>return</c-> <c- n>w</c-><c- p>;</c->  <c- c1>//!</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗✓ Move (possibly elided) at line 6</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.6" id="ex-6"><span class="secno">4.1.6. </span><span class="content">Example 6</span><a class="self-link" href="#ex-6"></a></h4>
   <p>The example above can be "fixed" so that guaranteed copy elision is performed. Now all the <code class="highlight"><c- k>return</c-></code> statements within the potential scope of <code class="highlight"><c- n>w</c-></code> (the one on line 7) return <code class="highlight"><c- n>w</c-></code>.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>do</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line">    …</span><span class="line-no" data-line="5"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>break</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line">    …</span><span class="line-no" data-line="7"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="8"></span><span class="line">  <c- p>}</c-> <c- k>while</c-> <c- p>(</c->false<c- p>);</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- k>return</c-> <c- p>{};</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 7</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 7 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.7" id="ex-7"><span class="secno">4.1.7. </span><span class="content">Example 7</span><a class="self-link" href="#ex-7"></a></h4>
   <p>Here, the <code class="highlight"><c- k>return</c-></code> statement at line 2 does not belong to the potential scope of <code class="highlight"><c- n>b</c-></code> (which starts at line 3), therefore not inhibiting guaranteed copy elision at line 5.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- p>{};</c->  <c- c1>//!</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>widget</c-> <c- n>b</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line">  …</span><span class="line-no" data-line="5"></span><span class="line">  <c- k>return</c-> <c- n>b</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 5</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 5 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.8" id="ex-8"><span class="secno">4.1.8. </span><span class="content">Example 8</span><a class="self-link" href="#ex-8"></a></h4>
   <p>Here, the <code class="highlight"><c- k>return</c-></code> statement at line 5 belongs to the potential scope of <code class="highlight"><c- n>one</c-></code> and thus inhibits guaranteed copy elision for <code class="highlight"><c- n>one</c-></code>.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>one</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>if</c-> <c- p>(</c-><c- n>toss_a_coin</c-><c- p>())</c-> <c- k>return</c-> <c- n>one</c-><c- p>;</c->  <c- c1>//!</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>widget</c-> <c- n>two</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>return</c-> <c- n>two</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at lines 3 and 5</p>
    <li data-md>
     <p>✓ Move (possibly elided) at line 3. No copies or moves needed at line 5 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.9" id="ex-9"><span class="secno">4.1.9. </span><span class="content">Example 9</span><a class="self-link" href="#ex-9"></a></h4>
   <p>Constructing, setting up and passing an object as a parameter by value using an immediately invoked lambda expression (<code class="highlight"><c- n>p</c-></code> is directly initialized under the name of <code class="highlight"><c- n>w</c-></code>).</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- b>void</c-> <c- nf>consume_widget</c-><c- p>(</c-><c- n>widget</c-> <c- n>p</c-><c- p>);</c-></span><span class="line-no" data-line="2"></span><span class="line"></span><span class="line-no" data-line="3"></span><span class="line"><c- b>void</c-> <c- nf>test</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- b>int</c-> <c- n>y</c-> <c- o>=</c-> <c- n>process</c-><c- p>(</c-><c- n>x</c-><c- p>);</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- n>consume_widget</c-><c- p>([</c-><c- o>&amp;</c-><c- p>]</c-> <c- p>{</c-></span><span class="line-no" data-line="6"></span><span class="line">    <c- k>auto</c-> <c- n>w</c-> <c- o>=</c-> <c- n>widget</c-><c- p>(</c-><c- n>x</c-><c- p>);</c-></span><span class="line-no" data-line="7"></span><span class="line">    <c- n>w</c-><c- p>.</c-><c- n>set_y</c-><c- p>(</c-><c- n>y</c-><c- p>);</c-></span><span class="line-no" data-line="8"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- p>}());</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 8</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 8 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.10" id="ex-10"><span class="secno">4.1.10. </span><span class="content">Example 10</span><a class="self-link" href="#ex-10"></a></h4>
   <p>If <code class="highlight"><c- n>w</c-></code> is not returned, it is destroyed, and another <code class="highlight"><c- n>widget</c-></code> (perhaps, another object named <code class="highlight"><c- n>w</c-></code>) can take its place.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- k>if</c-> <c- p>(</c->false<c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- nl>impossible</c-><c- p>:</c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="6"></span><span class="line"></span><span class="line-no" data-line="7"></span><span class="line">  <c- k>while</c-> <c- p>(</c->…<c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="8"></span><span class="line">    <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="10"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>break</c-><c- p>;</c-></span><span class="line-no" data-line="11"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>continue</c-><c- p>;</c-></span><span class="line-no" data-line="12"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>goto</c-> <c- n>impossible</c-><c- p>;</c-></span><span class="line-no" data-line="13"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>throw</c-> …<c- p>;</c-></span><span class="line-no" data-line="14"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="15"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="16"></span><span class="line">  <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="17"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at lines 9 and 14</p>
    <li data-md>
     <p>✓ No copies or moves needed at lines 9 and 14 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.11" id="ex-11"><span class="secno">4.1.11. </span><span class="content">Example 11</span><a class="self-link" href="#ex-11"></a></h4>
   <p>Implementation-wise, <code class="highlight"><c- n>w1</c-></code>, <code class="highlight"><c- n>w2</c-></code> and <code class="highlight"><c- n>w3</c-></code> will occupy the return slot at different times. Wording-wise, if we reach line 10, then <code class="highlight"><c- n>w1</c-></code> and <code class="highlight"><c- n>w2</c-></code> are not considered to have ever denoted the result object of the function call; they are considered normal local variables, so the result object of the function is only constructed and destroyed once.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">      <c- n>widget</c-> <c- n>w1</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">      <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>w1</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line">    <c- p>}</c-></span><span class="line-no" data-line="7"></span><span class="line">    <c- n>widget</c-> <c- n>w2</c-><c- p>;</c-></span><span class="line-no" data-line="8"></span><span class="line">    <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>w2</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="10"></span><span class="line">  <c- n>widget</c-> <c- n>w3</c-><c- p>;</c-></span><span class="line-no" data-line="11"></span><span class="line">  <c- k>return</c-> <c- n>w3</c-><c- p>;</c-></span><span class="line-no" data-line="12"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at lines 5, 8, 11</p>
    <li data-md>
     <p>✓ No copies or moves needed at lines 5, 8, 11 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.12" id="ex-12"><span class="secno">4.1.12. </span><span class="content">Example 12</span><a class="self-link" href="#ex-12"></a></h4>
   <p>Guaranteed copy elision will be unaffected by a nested class, a lambda capture and a discarded <code class="highlight"><c- k>return</c-></code> statement.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>struct</c-> <c- n>s</c-> <c- p>{</c-> <c- n>widget</c-> <c- n>f</c-><c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>widget</c-><c- p>();</c-> <c- p>}</c-> <c- p>};</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- k>auto</c-> <c- n>l</c-> <c- o>=</c-> <c- p>[</c-><c- o>&amp;</c-><c- n>w</c-><c- p>]()</c-> <c- p>{</c-> <c- k>return</c-> <c- n>widget</c-><c- p>();</c-> <c- p>}();</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c->false<c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>widget</c-><c- p>();</c-> <c- p>}</c-></span><span class="line-no" data-line="6"></span><span class="line">  <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 6</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 6 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.13" id="ex-13"><span class="secno">4.1.13. </span><span class="content">Example 13</span><a class="self-link" href="#ex-13"></a></h4>
   <p>Guaranteed copy elision will be required in constant evaluation context.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>consteval</c-> <c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>widget</c-> <c- n>y</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>return</c-> <c- n>y</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- k>constinit</c-> <c- n>widget</c-> <c- n>z</c-> <c- o>=</c-> <c- n>test</c-><c- p>();</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move at lines 3 and 5 (copy elision is not allowed)</p>
    <li data-md>
     <p>✓ Move at line 3 (copy elision is not allowed). No copies or moves needed at line 5 ("guaranteed NRVO")</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.14" id="ex-14"><span class="secno">4.1.14. </span><span class="content">Example 14</span><a class="self-link" href="#ex-14"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- b>void</c-> <c- nf>foo</c-><c- p>();</c->  <c- c1>// throws a widget</c-></span><span class="line-no" data-line="2"></span><span class="line"></span><span class="line-no" data-line="3"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- k>try</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line">    <c- n>foo</c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line">  <c- p>}</c-> <c- k>catch</c-> <c- p>(</c-><c- n>widget</c-> <c- n>w</c-><c- p>)</c-> <c- p>{</c->  <c- c1>//!</c-></span><span class="line-no" data-line="7"></span><span class="line">    <c- n>watch</c-><c- p>(</c-><c- n>w</c-><c- p>);</c-></span><span class="line-no" data-line="8"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Copy (possibly elided, <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a>) at line 6. Move (possibly elided) at line 8</p>
    <li data-md>
     <p>✓ Copy (possibly elided, <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a>) at line 6. No copies or moves needed at line 8 ("guaranteed NRVO")</p>
   </ul>
   <p>See also: <a href="#req-value-exeptions">§ 6.2.3 Exception-declarations can introduce return variables</a></p>
   <h4 class="heading settled" data-level="4.1.15" id="ex-15"><span class="secno">4.1.15. </span><span class="content">Example 15</span><a class="self-link" href="#ex-15"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>if</c-> <c- p>(</c-><c- n>toss_a_coin</c-><c- p>())</c-> <c- k>return</c-> <c- p>(</c-><c- n>x</c-><c- p>);</c->  <c- c1>//!</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>widget</c-> <c- n>y</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>return</c-> <c- p>((</c-><c- n>y</c-><c- p>));</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move at lines 3 and 5 (copy elision in not allowed, but implementations perform copy elision in this case anyway)</p>
    <li data-md>
     <p>✓ Move (possibly elided) at line 3. No copies or moves needed at line 5 ("guaranteed NRVO")</p>
   </ul>
   <p>See also: <a href="#req-parentheses">§ 6.2.1 Parentheses are now allowed around the variable name</a></p>
   <h4 class="heading settled" data-level="4.1.16" id="ex-16"><span class="secno">4.1.16. </span><span class="content">Example 16</span><a class="self-link" href="#ex-16"></a></h4>
   <p>For trivially copyable types, a copy may still be introduced.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>struct</c-> <c- n>gadget</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>gadget</c-><c- o>*</c-> <c- n>p</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>gadget</c-><c- p>()</c-> <c- o>:</c-> <c- n>p</c-><c- p>(</c-><c- k>this</c-><c- p>)</c-> <c- p>{}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- p>};</c-></span><span class="line-no" data-line="5"></span><span class="line"></span><span class="line-no" data-line="6"></span><span class="line"><c- n>gadget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="7"></span><span class="line">  <c- n>gadget</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="8"></span><span class="line">  <c- k>return</c-> <c- n>x</c-><c- p>;</c->  <c- c1>//!</c-></span><span class="line-no" data-line="9"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- n>gadget</c-> <c- n>y</c-> <c- o>=</c-> <c- n>test</c-><c- p>();</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Trivial copy (possibly elided) at line 8. An additional copy may be introduced. It is implementation-defined whether <code class="highlight"><c- n>x</c-></code> and <code class="highlight"><c- n>y</c-></code> name the same object and whether <code class="highlight"><c- n>y</c-><c- p>.</c-><c- n>p</c-></code> dangles</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 8 ("guaranteed NRVO"). An additional copy may be introduced. It is implementation-defined whether <code class="highlight"><c- n>x</c-></code> and <code class="highlight"><c- n>y</c-></code> name the same object and whether <code class="highlight"><c- n>y</c-><c- p>.</c-><c- n>p</c-></code> dangles</p>
   </ul>
   <p>See also: <a href="#trivial-temporaries">§ 6.3 What about trivially copyable temporaries?</a></p>
   <h4 class="heading settled" data-level="4.1.17" id="ex-17"><span class="secno">4.1.17. </span><span class="content">Example 17</span><a class="self-link" href="#ex-17"></a></h4>
   <p>For non-class types, a copy may still be introduced.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>using</c-> <c- n>large</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- b>intmax_t</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"></span><span class="line-no" data-line="3"></span><span class="line"><c- n>large</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>large</c-> <c- n>x</c-> <c- o>=</c-> <c- mi>42</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>return</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="7"></span><span class="line"></span><span class="line-no" data-line="8"></span><span class="line"><c- n>large</c-> <c- n>a</c-> <c- o>=</c-> <c- n>test</c-><c- p>();</c-></span><span class="line-no" data-line="9"></span><span class="line"><c- n>large</c-> <c- n>b</c-> <c- o>=</c-> <c- n>test</c-><c- p>()</c-> <c- o>+</c-> <c- n>test</c-><c- p>();</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- b>signed</c-> <c- b>char</c-> <c- n>c</c-> <c- o>=</c-> <c- n>test</c-><c- p>();</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Trivial copy at line 5 (copy elision is not allowed). An additional copy may be introduced. It is implementation-defined whether <code class="highlight"><c- n>x</c-></code> and <code class="highlight"><c- n>a</c-></code> name the same object</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 5 ("guaranteed NRVO"). An additional copy may be introduced. It is implementation-defined whether <code class="highlight"><c- n>x</c-></code> and <code class="highlight"><c- n>a</c-></code> name the same object</p>
   </ul>
   <p>See also: <a href="#non-class">§ 6.4 What about copy elision for non-class types?</a></p>
   <h4 class="heading settled" data-level="4.1.18" id="ex-18"><span class="secno">4.1.18. </span><span class="content">Example 18</span><a class="self-link" href="#ex-18"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- b>bool</c-> <c- n>B</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- n>widget</c-> <c- n>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- k>if</c-> <c- nf>constexpr</c-> <c- p>(</c-><c- n>B</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line">    <c- k>if</c-> <c- p>(</c->false<c- p>)</c-> <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="7"></span><span class="line">  <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 7</p>
    <li data-md>
     <p>✓ In the instantiation where <code class="highlight"><c- n>B</c-> <c- o>==</c-> false</code>, no copies or moves are needed at line 7 ("guaranteed NRVO"). In the instantiation where <code class="highlight"><c- n>B</c-> <c- o>==</c-> true</code>, move (possibly elided) at line 7</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.19" id="ex-19"><span class="secno">4.1.19. </span><span class="content">Example 19</span><a class="self-link" href="#ex-19"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>const</c-> <c- k>volatile</c-> <c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>a</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>a</c-><c- p>.</c-><c- n>mutate</c-><c- p>();</c->  <c- c1>// OK</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- k>return</c-> <c- n>a</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- k>auto</c-> <c- n>b</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c-></span><span class="line-no" data-line="7"></span><span class="line"></span><span class="line-no" data-line="8"></span><span class="line"><c- n>widget</c-> <c- nf>bar</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="10"></span><span class="line">    <c- k>const</c-> <c- n>widget</c-> <c- n>c</c-><c- p>;</c-></span><span class="line-no" data-line="11"></span><span class="line">    <c- c1>// c.mutate();  // ERROR</c-></span><span class="line-no" data-line="12"></span><span class="line">    <c- c1>// const_cast&lt;widget&amp;>(c).mutate();  // UB</c-></span><span class="line-no" data-line="13"></span><span class="line">    <c- k>return</c-> <c- n>c</c-><c- p>;</c-></span><span class="line-no" data-line="14"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="15"></span><span class="line">  <c- k>volatile</c-> <c- n>widget</c-> <c- n>d</c-><c- p>;</c-></span><span class="line-no" data-line="16"></span><span class="line">  <c- k>return</c-> <c- n>d</c-><c- p>;</c->  <c- c1>//!</c-></span><span class="line-no" data-line="17"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="18"></span><span class="line"><c- k>auto</c-> <c- n>e</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c-></span><span class="line-no" data-line="19"></span><span class="line"></span><span class="line-no" data-line="20"></span><span class="line"><c- b>void</c-> <c- nf>baz</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="21"></span><span class="line">  <c- c1>// b.mutate();  // ERROR</c-></span><span class="line-no" data-line="22"></span><span class="line">  <c- c1>// const_cast&lt;widget&amp;>(b).mutate();  // UB</c-></span><span class="line-no" data-line="23"></span><span class="line">  <c- n>e</c-><c- p>.</c-><c- n>mutate</c-><c- p>();</c->  <c- c1>// OK</c-></span><span class="line-no" data-line="24"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at lines 4 and 13. Copy at line 16 (copy elision and implicit move are not allowed)</p>
    <li data-md>
     <p>✓ No copies or moves needed at lines 4 and 13 ("guaranteed NRVO"). Copy at line 16 (copy elision and implicit move are not allowed)</p>
   </ul>
   <h4 class="heading settled" data-level="4.1.20" id="ex-20"><span class="secno">4.1.20. </span><span class="content">Example 20</span><a class="self-link" href="#ex-20"></a></h4>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>extern</c-> <c- n>widget</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"></span><span class="line-no" data-line="3"></span><span class="line"><c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>widget</c-> <c- n>y</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- k>if</c-> <c- p>(</c-><c- o>&amp;</c-><c- n>x</c-> <c- o>==</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>)</c-> <c- p>{</c->  <c- c1>// true</c-></span><span class="line-no" data-line="6"></span><span class="line">    <c- k>throw</c-> <c- mi>0</c-><c- p>;</c-></span><span class="line-no" data-line="7"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="8"></span><span class="line">  <c- k>return</c-> <c- n>y</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="10"></span><span class="line"></span><span class="line-no" data-line="11"></span><span class="line"><c- n>widget</c-> <c- n>x</c-> <c- o>=</c-> <c- n>test</c-><c- p>();</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move (possibly elided) at line 8</p>
    <li data-md>
     <p>✓ No copies or moves needed at line 8 ("guaranteed NRVO")</p>
   </ul>
   <h2 class="heading settled" data-level="5" id="wording"><span class="secno">5. </span><span class="content">Proposed wording</span><a class="self-link" href="#wording"></a></h2>
   <p>The wording in this section is relative to WG21 draft <a data-link-type="biblio" href="#biblio-n4861">[N4861]</a>.</p>
   <h3 class="heading settled" data-level="5.1" id="wording-definitions"><span class="secno">5.1. </span><span class="content">Definitions</span><a class="self-link" href="#wording-definitions"></a></h3>
   <p>Add new sections in <a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a>:</p>
   <blockquote> A <code class="highlight"><c- k>return</c-></code> (<a href="http://eel.is/c++draft/stmt.return">[stmt.return]</a>) or <code class="highlight"><c- k>co_return</c-></code> (<a href="http://eel.is/c++draft/stmt.return.coroutine">[stmt.return.coroutine]</a>) statement <em>R</em> <dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export data-lt="to directly observe a variable" id="abstract-opdef-to-directly-observe-a-variable">directly observes</dfn> a variable <em>V</em> if the potential scope (<a href="http://eel.is/c++draft/basic.scope">[basic.scope]</a>) of <em>V</em> includes <em>R</em> and <em>V</em> is declared in the body or <em>parameter-declaration-clause</em> of the innermost enclosing function or <em>lambda-expression</em> of <em>R</em>. If, additionally, the operand of <em>R</em> is a (possibly parenthesized) <em>id-expression</em> designating <em>V</em>, then <em>R</em> <dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export data-lt="to return a variable" id="abstract-opdef-to-return-a-variable">returns</dfn> the variable <em>V</em>. </blockquote>
   <blockquote>
     A variable with automatic storage duration is called a <dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export id="abstract-opdef-potential-return-variable">potential return variable</dfn> when all of the following conditions are satisfied: 
    <ul>
     <li data-md>
      <p>the variable is not a function parameter,</p>
     <li data-md>
      <p>the type of the variable is an object type, is not <code class="highlight"><c- k>volatile</c-></code>-qualified, and is the same (ignoring cv-qualification) as the return type of the immediately enclosing function or <em>lambda-expression</em>, and</p>
     <li data-md>
      <p>at least one non-discarded (<a href="http://eel.is/c++draft/stmt.if">[stmt.if]</a>) <code class="highlight"><c- k>return</c-></code> statement <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable②">returns</a> the variable. [ <em>Note:</em> The enclosing function cannot be a coroutine. — <em>end note</em> ]</p>
    </ul>
    <p>If additionally, all non-discarded <code class="highlight"><c- k>return</c-></code> statements, which <a data-link-type="abstract-op" href="#abstract-opdef-to-directly-observe-a-variable" id="ref-for-abstract-opdef-to-directly-observe-a-variable">directly observe</a> the variable, <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable③">return</a> it, then the variable is called a <dfn class="dfn-paneled" data-dfn-type="abstract-op" data-export id="abstract-opdef-return-variable">return variable</dfn>. [ <em>Note:</em> A potential return variable shall have an eligible copy or move constructor (<a href="http://eel.is/c++draft/class.copy.ctor">[class.copy.ctor]</a>), unless it is a return variable. — <em>end note</em> ]</p>
   </blockquote>
   <blockquote class="note warning-note"> Note:
The definition avoids mentioning the object a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①">return variable</a> names prematurely. </blockquote>
   <blockquote class="note warning-note"> Note:
See also <a href="#req-change">§ 6.2 Have requirements for copy elision changed?</a>, <a href="#non-class">§ 6.4 What about copy elision for non-class types?</a> </blockquote>
   <blockquote class="issue" id="issue-b1429285"><a class="self-link" href="#issue-b1429285"></a> Too many new terms might have been introduced: <a data-link-type="abstract-op" href="#abstract-opdef-to-directly-observe-a-variable" id="ref-for-abstract-opdef-to-directly-observe-a-variable①">to directly observe a variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable④">to return a variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-potential-return-variable" id="ref-for-abstract-opdef-potential-return-variable">potential return variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable②">return variable</a>. </blockquote>
   <blockquote class="issue" id="issue-1d52cd17"><a class="self-link" href="#issue-1d52cd17"></a> Should we say "function or <em>lambda-expression</em>", or is it enough to say "function"? </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/class.copy.elision#3">[class.copy.elision]/3</a>:</p>
   <blockquote>
     […] In the following copy-initialization contexts, a move operation might be used instead of a copy operation: 
    <ul>
     <li data-md>
      <del>If the expression in a <code class="highlight"><c- k>return</c-></code> ([stmt.return]) or <code class="highlight"><c- n>co_</c->­<c- k>return</c-></code> ([stmt.return.coroutine]) statement is a (possibly parenthesized) <em>id-expression</em> that names an implicitly movable entity declared in the body or <em>parameter-declaration-clause</em> of the innermost enclosing function or <em>lambda-expression</em></del>
      <ins>if a statement returns an implicitly movable entity</ins>
      , or 
     <li data-md>
      <p>if the operand of a <em>throw-expression</em> […]</p>
    </ul>
   </blockquote>
   <h3 class="heading settled" data-level="5.2" id="wording-behavior"><span class="secno">5.2. </span><span class="content">The behavior of return variables</span><a class="self-link" href="#wording-behavior"></a></h3>
   <p>Add new sections in <a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a>:</p>
   <blockquote> A <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable③">return variable</a> occupies the same storage as the result object of the function call expression. </blockquote>
   <blockquote>
     If the scope of a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable④">return variable</a> is exited by executing a statement that <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable⑤">returns</a> the variable (and the destruction of local variables is not terminated by an exception), then the variable denotes the result object of the function call expression. [ <em>Note:</em> If the <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable⑤">return variable</a> is of a trivially copyable type, then a temporary object can be introduced, with a subsequent copy or move (<a href="http://eel.is/c++draft/class.temporary">[class.temporary]</a>). In this case the variable shall denote the temporary. — <em>end note</em> ] The statement that returns the variable performs no copy-initialization (<a href="http://eel.is/c++draft/stmt.return">[stmt.return]</a>) and does not cause the destruction of the object (<a href="http://eel.is/c++draft/stmt.jump">[stmt.jump]</a>). Except for that, until the control is transferred out of the function, the variable shall be treated as a local variable with automatic storage duration, and <code class="highlight"><c- k>const</c-></code> and <code class="highlight"><c- k>volatile</c-></code> semantics (<a href="http://eel.is/c++draft/dcl.type.cv">[dcl.type.cv]</a>) applied to the object corresponding to the type of the return variable. [ <em>Example:</em> 
<pre class="highlight"><c- k>class</c-> <c- nc>A</c-> <c- p>{</c->
  <c- b>int</c-> <c- n>x</c-><c- p>;</c->
  <c- n>A</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- n>A</c-><c- p>(</c-><c- n>A</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
<c- p>};</c->

<c- n>A</c-> <c- nf>f</c-><c- p>()</c-> <c- p>{</c->
  <c- n>A</c-> <c- n>a</c-><c- p>;</c->       <c- c1>// "a" is a return variable</c->
  <c- n>a</c-><c- p>.</c-><c- n>x</c-> <c- o>=</c-> <c- mi>5</c-><c- p>;</c->   <c- c1>// OK, a has non-const semantics</c->
  <c- k>return</c-> <c- n>a</c-><c- p>;</c->  <c- c1>// OK, no copy-initialization</c->
<c- p>}</c->

<c- k>const</c-> <c- n>A</c-> <c- n>b</c-> <c- o>=</c-> <c- n>f</c-><c- p>();</c->  <c- c1>// "b" names the same object as "a"</c->
</pre>
    <p>— <em>end example</em> ] The destructor for the object is potentially invoked (<a href="http://eel.is/c++draft/class.dtor">[class.dtor]</a>, <a href="http://eel.is/c++draft/except.ctor">[except.ctor]</a>). [ <em>Example:</em></p>
<pre class="highlight"><c- k>class</c-> <c- nc>A</c-> <c- p>{</c->
  <c- o>~</c-><c- n>A</c-><c- p>()</c-> <c- p>{}</c->
<c- p>};</c->
<c- n>A</c-> <c- nf>f</c-><c- p>()</c-> <c- p>{</c->
  <c- n>A</c-> <c- n>a</c-><c- p>;</c->
  <c- k>return</c-> <c- n>a</c-><c- p>;</c->  <c- c1>// error: destructor of A is private (even though it is never invoked)</c->
<c- p>}</c->
</pre>
    <p>— <em>end example</em> ]</p>
   </blockquote>
   <blockquote>
     If the scope of a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable⑥">return variable</a> is exited in a way other than by executing a statement that <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable" id="ref-for-abstract-opdef-to-return-a-variable⑥">returns</a> the variable (or the destruction of a local variable is terminated by an exception), the return variable is considered a normal local variable that denotes an object of automatic storage duration. [ <em>Note:</em> In particular, on exit from the scope, the object is destroyed, among other objects of automatic storage duration, in the reverse order of construction (<a href="http://eel.is/c++draft/stmt.jump">[stmt.jump]</a>). If destruction of a local variable is terminated by an exception, the return variable can be destroyed out of normal order, as per <a href="http://eel.is/c++draft/except.ctor">[except.ctor]</a>. — <em>end note</em> ] [ <em>Example:</em> 
<pre class="highlight"><c- k>struct</c-> <c- n>A</c-> <c- p>{</c->
  <c- n>A</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- n>A</c-><c- p>(</c-><c- n>A</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- p>{</c-> <c- p>}</c->
<c- p>};</c->

<c- k>struct</c-> <c- n>X</c-> <c- p>{</c-> <c- o>~</c-><c- n>X</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>(</c->false<c- p>)</c-> <c- p>{</c-> <c- k>throw</c-> <c- mi>0</c-><c- p>;</c-> <c- p>}</c-> <c- p>};</c->

<c- n>A</c-> <c- nf>f</c-><c- p>()</c-> <c- p>{</c->
  <c- n>A</c-> <c- n>a</c-><c- p>;</c->
  <c- n>X</c-> <c- n>x</c-><c- p>;</c->
  <c- n>A</c-> <c- n>b</c-><c- p>;</c->
  <c- n>A</c-> <c- n>c</c-><c- p>;</c->  <c- c1>// #1</c->
  <c- n>A</c-> <c- n>d</c-><c- p>;</c->
  <c- k>return</c-> <c- n>c</c-><c- p>;</c->  <c- c1>// #2</c->
<c- p>}</c->
</pre>
    <p>At #1, the <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable⑦">return variable</a> <code class="highlight"><c- n>c</c-></code> is constructed in the storage for the result object of the function call expression. The local variable <code class="highlight"><c- n>c</c-></code> does not denote the result object, because the control will exit the scope of <code class="highlight"><c- n>c</c-></code> by the means of an exception. At #2, the local variable <code class="highlight"><c- n>d</c-></code> is destroyed, then the local variable <code class="highlight"><c- n>b</c-></code> is destroyed. Next, the local variable <code class="highlight"><c- n>x</c-></code> is destroyed, causing stack unwinding, resulting in the destruction of the local variable <code class="highlight"><c- n>c</c-></code>, followed by the destruction of the local variable <code class="highlight"><c- n>a</c-></code>. The function call is terminated by the exception.</p>
    <p>— <em>end example</em> ]</p>
   </blockquote>
   <blockquote> Until the control is transferred out of the function, if the value of the object of the <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable⑧">return variable</a> or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the variable, the value of the object or subobject thus obtained is unspecified. </blockquote>
   <blockquote class="note warning-note"> Note:
The object of a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable⑨">return variable</a> is analogous to an object under construction. Some wording was borrowed from <a href="http://eel.is/c++draft/class.ctor#5">[class.ctor]</a> and <a href="http://eel.is/c++draft/class.cdtor#2">[class.cdtor]/2</a>. </blockquote>
   <blockquote class="note warning-note"> Note:
See also <a href="#trivial-temporaries">§ 6.3 What about trivially copyable temporaries?</a>, <a href="#invalidation">§ 6.5 What about the invalidation of optimizations?</a> </blockquote>
   <blockquote class="issue" id="issue-2dd63f8d"><a class="self-link" href="#issue-2dd63f8d"></a> Following the proposed wording, it cannot be known at the time of initialization of the <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①⓪">return variable</a>'s object, what object it is exactly ("Schrodinger’s object"). Later on, it is retrospectively established that we either have initialized and worked with a normal local variable, or with the result object of the function call expression. </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]/1</a>:</p>
   <blockquote>
     […] This elision of copy/move operations, called <em>copy elision</em>, is permitted in the following circumstances (which may be combined to eliminate multiple copies): 
    <ul>
     <li data-md>
      <del>in a <code class="highlight"><c- k>return</c-></code> statement in a function with a class return type, when the <em>expression</em> is the name of a non-volatile object with automatic storage duration (other than a function parameter or a variable introduced by the <em>exception-declaration</em> of a <em>handler</em> (<a href="http://eel.is/c++draft/except.handle">[except.handle]</a>)) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the object directly into the function call’s return object</del>
      <ins>the implementation can treat a <a data-link-type="abstract-op" href="#abstract-opdef-potential-return-variable" id="ref-for-abstract-opdef-potential-return-variable①">potential return variable</a> as a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①①">return variable</a></ins>
     <li data-md>
      <p>in a <em>throw-expression</em> […]</p>
    </ul>
   </blockquote>
   <h3 class="heading settled" data-level="5.3" id="wording-refs"><span class="secno">5.3. </span><span class="content">Cross-references</span><a class="self-link" href="#wording-refs"></a></h3>
   <p>Modify <a href="http://eel.is/c++draft/stmt.jump#2">[stmt.jump]/2</a>:</p>
   <blockquote>
     On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction. [ <em>Note:</em> For temporaries, see <a href="http://eel.is/c++draft/class.temporary">[class.temporary]</a>. 
    <ins>For objects participating in copy elision, see <a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a>.</ins>
     — <em>end note</em> ] Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of objects with automatic storage duration that are in scope at the point transferred from but not at the point transferred to. (See <a href="http://eel.is/c++draft/stmt.dcl">[stmt.dcl]</a> for transfers into blocks). […] 
   </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/stmt.return#2">[stmt.return]/2</a>:</p>
   <blockquote>
     […] A <code class="highlight"><c- k>return</c-></code> statement with any other operand shall be used only in a function whose return type is not cv <code class="highlight"><c- b>void</c-></code>; the <code class="highlight"><c- k>return</c-></code> statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function call by copy-initialization from the operand 
    <ins>(except when copy elision applies (<a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a>))</ins>
    . […] 
   </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/stmt.dcl#2">[stmt.dcl]/2</a>:</p>
   <blockquote>
     Variables with automatic storage duration are initialized each time their <em>declaration-statement</em> is executed. 
    <ins>[ <em>Note:</em></ins>
     Variables with automatic storage duration declared in the block are destroyed on exit from the block 
    <ins>as described in</ins>
    <del>(</del>
     <a href="http://eel.is/c++draft/stmt.jump">[stmt.jump]</a> 
    <del>)</del>
    . 
    <ins>— <em>end note</em> ]</ins>
   </blockquote>
   <blockquote class="note warning-note"> Note:
The modified sentence currently duplicates the specification in <a href="http://eel.is/c++draft/stmt.jump#2">[stmt.jump]/2</a>. If the sentence is turned into a reference, it will not have to duplicate the exception for return variables. </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/class.dtor#15">[class.dtor]/15</a>:</p>
   <blockquote>
     […] A destructor is potentially invoked if it is invoked or as specified in [expr.new], [stmt.return], 
    <ins><a href="http://eel.is/c++draft/class.copy.elision">[class.copy.elision]</a>,</ins>
     [dcl.init.aggr], [class.base.init], and [except.throw]. A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation. 
   </blockquote>
   <h3 class="heading settled" data-level="5.4" id="wording-non-class"><span class="secno">5.4. </span><span class="content">Returning non-class types</span><a class="self-link" href="#wording-non-class"></a></h3>
   <p>Modify <a href="http://eel.is/c++draft/class.temporary#3">[class.temporary]/3</a>:</p>
   <blockquote>
     When an object of class type <code class="highlight"><c- n>X</c-></code> is passed to or returned from a function, if <code class="highlight"><c- n>X</c-></code> has at least one eligible copy or move constructor ([special]), each such constructor is trivial, and the destructor of <code class="highlight"><c- n>X</c-></code> is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object. The temporary object is constructed from the function argument or return value, respectively, and the function’s parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). 
    <ins>Similarly, when an object of a non-class type is passed to or returned from a function, implementations are permitted to create a temporary object.</ins>
     [ <em>Note:</em> This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. <em>— end note</em> ] 
   </blockquote>
   <blockquote class="note warning-note"> Note:
CWG2434 (<a href="https://raw.githack.com/zygoloid/wg21papers/master/to-review/cwg2434.html">alt. link</a>) proposes essentially the same change. The wording might be more precise over there. </blockquote>
   <p>Add a new section after <a href="http://eel.is/c++draft/expr.context#2">[expr.context]/2</a>:</p>
   <blockquote> When a function call prvalue expression of non-class type other than <em>cv</em> <code class="highlight"><c- b>void</c-></code> is used to compute the value of an operand of a built-in operator, the prvalue result object is a temporary object. </blockquote>
   <p>Modify <a href="http://eel.is/c++draft/basic.lval#5">[basic.lval]/5</a>:</p>
   <blockquote>
     The result object of a prvalue is the object initialized by the prvalue; 
    <del>a non-discarded prvalue that is used to compute the value of an operand of a built-in operator or</del>
     a prvalue that has type cv void has no result object. [ Note: Except when the prvalue is the operand of a decltype-specifier, a prvalue of class or array type always has a result object. For a discarded prvalue that has type other than cv void, a temporary object is materialized; see [expr.context]. — end note ] 
   </blockquote>
   <blockquote class="note warning-note"> Note:
See also <a href="#non-class">§ 6.4 What about copy elision for non-class types?</a>. </blockquote>
   <h2 class="heading settled" data-level="6" id="faq"><span class="secno">6. </span><span class="content">Discussion</span><a class="self-link" href="#faq"></a></h2>
   <h3 class="heading settled" data-level="6.1" id="term"><span class="secno">6.1. </span><span class="content">Is "return variable" a good term choice?</span><a class="self-link" href="#term"></a></h3>
   <blockquote class="issue" id="issue-9ca2bd58"><a class="self-link" href="#issue-9ca2bd58"></a> "<a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①②">Return variable</a>" might not be the best term for our purposes. </blockquote>
   <p>A previous revision of this proposal (R0) used the term "named return object". That term choice was unfortunate, because it refers to a variable, not to an object. And a variable cannot be "unnamed", so that was excessive.</p>
   <p>Some alternative choices:</p>
   <ul>
    <li data-md>
     <p>result variable</p>
    <li data-md>
     <p>return object name</p>
    <li data-md>
     <p>result object name</p>
    <li data-md>
     <p>transparently returned variable</p>
   </ul>
   <h3 class="heading settled" data-level="6.2" id="req-change"><span class="secno">6.2. </span><span class="content">Have requirements for copy elision changed?</span><a class="self-link" href="#req-change"></a></h3>
   <p>There are multiple issues with current wording for copy elision. While <a href="http://eel.is/c++draft/class.copy.elision#3">[class.copy.elision]/3</a> has recently been updated (<a data-link-type="biblio" href="#biblio-p0527r1">[P0527R1]</a>, <a data-link-type="biblio" href="#biblio-p1155r3">[P1155R3]</a>, <a data-link-type="biblio" href="#biblio-p1825r0">[P1825R0]</a>), <a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]/1</a> has not. Proposed wording cleans up those issues.</p>
   <h4 class="heading settled" data-level="6.2.1" id="req-parentheses"><span class="secno">6.2.1. </span><span class="content">Parentheses are now allowed around the variable name</span><a class="self-link" href="#req-parentheses"></a></h4>
   <p>See <a href="#ex-15">§ 4.1.15 Example 15</a>. <code class="highlight"><c- n>x</c-></code> is considered a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①③">return variable</a>, and <code class="highlight"><c- n>y</c-></code> a <a data-link-type="abstract-op" href="#abstract-opdef-potential-return-variable" id="ref-for-abstract-opdef-potential-return-variable②">potential return variable</a>.</p>
   <p>Meanwhile, at the time of writing, copy elision is not allowed for parenthesized variables.</p>
   <p>Implementation divergence has been discovered. Clang and MSVC currently does perform copy elision there, but GCC does not. Consequently, this change may be delivered in a Defect Report.</p>
   <h4 class="heading settled" data-level="6.2.2" id="req-lambda"><span class="secno">6.2.2. </span><span class="content">Copy elision is no longer allowed for lambda captures</span><a class="self-link" href="#req-lambda"></a></h4>
   <p>In the following case, name lookup for <code class="highlight"><c- n>w</c-></code> at line 4 finds exactly the outer <code class="highlight"><c- n>w</c-></code> variable. The <code class="highlight"><c- n>w</c-></code> expression does satisfy the "name of a non-volatile object with automatic storage duration" condition. Therefore, copy elision is currently allowed for the inner return statement. This seems unintentional; none of the major compilers performs copy elision in this case.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- k>return</c-> <c- p>[</c-><c- o>&amp;</c-><c- n>w</c-><c- p>]</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- k>return</c-> <c- n>w</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- p>}();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   <ul>
    <li data-md>
     <p>✗ Move or non-guaranteed copy elision (?!) at line 4. No copies or moves needed for <code class="highlight"><c- k>return</c-></code> at line 3</p>
    <li data-md>
     <p>✓ Move at line 4 (copy elision is not allowed). No copies or moves needed for <code class="highlight"><c- k>return</c-></code> at line 3</p>
   </ul>
   <p>This case will no longer be eligible for copy elision under the proposed wording. This change may be delivered in a Defect Report as well.</p>
   <h4 class="heading settled" data-level="6.2.3" id="req-value-exeptions"><span class="secno">6.2.3. </span><span class="content">Exception-declarations can introduce return variables</span><a class="self-link" href="#req-value-exeptions"></a></h4>
   <blockquote class="note warning-note"> Note:
Guaranteed copy elision will only affect exceptions caught by value ("by copy"). Exceptions caught by reference are not affected. </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>struct</c-> <c- n>widget</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>widget</c-><c- p>(</c-><c- k>const</c-> <c- n>widget</c-><c- o>&amp;</c-><c- p>);</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>widget</c-><c- p>(</c-><c- n>widget</c-><c- o>&amp;&amp;</c-><c- p>);</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>};</c-></span><span class="line-no" data-line="6"></span><span class="line"></span><span class="line-no" data-line="7"></span><span class="line"><c- b>void</c-> <c- nf>bar</c-><c- p>();</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- b>bool</c-> <c- nf>toss_a_coin</c-><c- p>();</c-></span><span class="line-no" data-line="9"></span><span class="line"></span><span class="line-no" data-line="10"></span><span class="line"><c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="11"></span><span class="line">  <c- k>try</c-> <c- p>{</c-></span><span class="line-no" data-line="12"></span><span class="line">    <c- n>bar</c-><c- p>();</c-></span><span class="line-no" data-line="13"></span><span class="line">  <c- p>}</c-> <c- k>catch</c-> <c- p>(</c-><c- n>widget</c-> <c- n>w</c-><c- p>)</c-> <c- p>{</c->            <c- c1>// (1.4)</c-></span><span class="line-no" data-line="14"></span><span class="line">    <c- n>use</c-><c- p>(</c-><c- n>w</c-><c- p>);</c-></span><span class="line-no" data-line="15"></span><span class="line">    <c- k>if</c-> <c- p>(</c-><c- n>toss_a_coin</c-><c- p>())</c-> <c- k>return</c-> <c- n>w</c-><c- p>;</c->  <c- c1>// (1.1)</c-></span><span class="line-no" data-line="16"></span><span class="line">  <c- p>}</c-></span><span class="line-no" data-line="17"></span><span class="line">  <c- k>return</c-> <c- n>widget</c-><c- p>();</c-></span><span class="line-no" data-line="18"></span><span class="line"><c- p>}</c-></span></pre>
   <p><b>Not applying <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a></b></p>
   <ul>
    <li data-md>
     <p>✗ At line 13, copy. At line 15, move or non-guaranteed copy elision</p>
    <li data-md>
     <p>✓ At line 13, copy. At line 15, guaranteed copy elision</p>
   </ul>
   <p><b>Applying <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a> (non-guaranteed)</b></p>
   <ul>
    <li data-md>
     <p>✗✓ At line 13, <code class="highlight"><c- n>w</c-></code> is an alias for the exception in flight. At line 15, copy (copyability is not required if the compiler can prove that <code class="highlight"><c- n>toss_a_coin</c-></code> never returns <code class="highlight">true</code>) or copy elision (<a href="http://eel.is/c++draft/class.copy.elision#1.1">[class.copy.elision]/(1.1)</a>, highly impractical in this case). The compiler must prove that this application of <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a> does not change the meaning of the program.</p>
   </ul>
   <p>This proposal can inhibit <a href="http://eel.is/c++draft/class.copy.elision#1.4">[class.copy.elision]/(1.4)</a> in some edge cases for a particular compiler. In return, copy elision is guaranteed consistently for the <code class="highlight"><c- k>return</c-></code> statement (<a href="http://eel.is/c++draft/class.copy.elision#1.1">[class.copy.elision]/(1.1)</a>).</p>
   <p>Overall, it seems that this is an edge case that can be removed painlessly. To guarantee the absence of copies for the exception object, one should catch the exception by reference, instead of catching by copy and complaining about the copy. On the other hand, when a copy is intended, this proposal ensures that the caught exception is treated as well as any other variable.</p>
   <blockquote class="issue" id="issue-395f911b"><a class="self-link" href="#issue-395f911b"></a> The previous restriction in this case looks like not-a-defect. Should this change belong to a separate proposal? </blockquote>
   <h3 class="heading settled" data-level="6.3" id="trivial-temporaries"><span class="secno">6.3. </span><span class="content">What about trivially copyable temporaries?</span><a class="self-link" href="#trivial-temporaries"></a></h3>
   <p>According to <a href="http://eel.is/c++draft/class.temporary">[class.temporary]</a>, the implementation is allowed to create a copy when the object of a trivially copyable type is returned. That is also the case when the copied object participates in (existing or proposed) guaranteed copy elision. If the address of such an object is saved to a pointer variable, the pointer will become dangling on return from the function:</p>
<pre class="highlight"><c- k>class</c-> <c- nc>A</c-> <c- p>{</c->
<c- k>public</c-><c- o>:</c->
  <c- n>A</c-><c- o>*</c-> <c- n>p</c-><c- p>;</c->
  <c- n>A</c-><c- p>()</c-> <c- o>:</c-> <c- n>p</c-><c- p>(</c-><c- k>this</c-><c- p>)</c-> <c- p>{}</c->
<c- p>};</c->

<c- n>A</c-> <c- nf>existing</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>A</c-><c- p>();</c->
<c- p>}</c->
<c- n>A</c-> <c- n>x</c-> <c- o>=</c-> <c- n>existing</c-><c- p>();</c->  <c- c1>// x.p may be dangling</c->

<c- n>A</c-><c- o>*</c-> <c- n>q</c-><c- p>;</c->
<c- n>A</c-> <c- nf>proposed</c-><c- p>()</c-> <c- p>{</c->
  <c- n>A</c-> <c- n>y</c-> <c- o>=</c-> <c- n>A</c-><c- p>();</c->
  <c- n>q</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>;</c->
  <c- k>return</c-> <c- n>y</c-><c- p>;</c->
<c- p>}</c->
<c- n>A</c-> <c- n>z</c-> <c- o>=</c-> <c- n>proposed</c-><c- p>();</c->  <c- c1>// z.p and q may be dangling</c->
</pre>
   <p>Changing <a href="http://eel.is/c++draft/class.temporary">[class.temporary]</a> and prohibiting such temporaries would cause ABI breakage, and is infeasible. ABI issues aside, it is not desirable to prohibit optimizations related to liberal treatment of trivially copyable types.</p>
   <p>The amount of copying will still be reduced even for those cases. Currently it is implementation-defined whether a copy is elided (<a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]/1</a>) and whether a temporary is created (<a href="http://eel.is/c++draft/class.temporary#3">[class.temporary]/3</a>). Depending on that, either 0, 1 or 2 copies may be performed (counting moves as copies). For example:</p>
<pre class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pair</c-><c- o>&lt;</c-><c- b>int</c-><c- p>,</c-> <c- b>int</c-><c- o>></c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- k>auto</c-> <c- n>a</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>pair</c-><c- p>(</c-><c- mi>1</c-><c- p>,</c-> <c- mi>2</c-><c- p>);</c->
  <c- k>return</c-> <c- n>a</c-><c- p>;</c->
<c- p>}</c->
<c- k>auto</c-> <c- n>b</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c->
</pre>
   <p>Currently, 4 scenarios are possible:</p>
   <ol>
    <li data-md>
     <p>Copy elided, no temporary. <code class="highlight"><c- n>a</c-></code> and <code class="highlight"><c- n>b</c-></code> denote the same object. 0 copies</p>
    <li data-md>
     <p>Copy elided, temporary. <code class="highlight"><c- n>a</c-></code> denotes the temporary, trivially copied into <code class="highlight"><c- n>b</c-></code>. 1 copy</p>
    <li data-md>
     <p>Copy not elided, no temporary. <code class="highlight"><c- n>a</c-></code> is a normal local variable, trivially copied into <code class="highlight"><c- n>b</c-></code>. 1 copy</p>
    <li data-md>
     <p>Copy not elided, temporary. <code class="highlight"><c- n>a</c-></code> is trivially copied into the temporary, which is then trivially copied into <code class="highlight"><c- n>b</c-></code>. 2 copies</p>
   </ol>
   <p>With this proposal accepted, only scenarios 1 and 2 are possible.</p>
   <p>See also: <a href="#ex-16">§ 4.1.16 Example 16</a></p>
   <h3 class="heading settled" data-level="6.4" id="non-class"><span class="secno">6.4. </span><span class="content">What about copy elision for non-class types?</span><a class="self-link" href="#non-class"></a></h3>
   <p>Currently, <a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]/1</a> disallows copy elision when a variable of a non-class type is returned. Moreover, it is difficult to talk about copy elision for non-class types, because a function call with result of a non-class object type might not have a result object (see <a href="http://eel.is/c++draft/expr.prop#basic.lval-5">[expr.prop]/5</a>).</p>
   <p>Meanwhile, there are definitely situations where results of non-class types are passed on stack. An implementation can perform NRVO, so the result gets written directly into the memory location specified by the caller. For example, on Clang:</p>
<pre class="highlight"><c- c1>// substitute with any non-class object type passed on stack,</c->
<c- c1>// e.g. std::int64_t on a 16-bit system.</c->
<c- k>using</c-> <c- n>big_t</c-> <c- o>=</c-> <c- n>_ExtInt</c-><c- p>(</c-><c- mi>256</c-><c- p>);</c->

<c- n>big_t</c-><c- o>*</c-> <c- n>px</c-> <c- o>=</c-> <c- k>nullptr</c-><c- p>;</c->

<c- n>big_t</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- n>big_t</c-> <c- n>x</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
  <c- n>px</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>x</c-><c- p>;</c->
  <c- k>return</c-> <c- n>x</c-><c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c->
  <c- n>big_t</c-> <c- n>y</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c->
  <c- n>printf</c-><c- p>(</c-><c- s>"%p  %p  %d</c-><c- se>\n</c-><c- s>"</c-><c- p>,</c-> <c- n>py</c-><c- p>,</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>,</c-> <c- n>py</c-> <c- o>==</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>);</c->
  <c- c1>//=>  &lt;addr.>  &lt;same addr.>  0</c->
<c- p>}</c->
</pre>
   <p>While <code class="highlight"><c- n>x</c-></code> and <code class="highlight"><c- n>y</c-></code> represent the same object "in the metal", they name different objects in the current C++ sense of "object", thus they compare unequal.</p>
   <p>The proposed wording suggests being more honest in this regard by saying that a function with object return type always has a result object, and then by allowing non-class object types to participate in copy elision on equal rights with trivially-copyable objects.</p>
   <p>See also: <a href="#ex-17">§ 4.1.17 Example 17</a></p>
   <blockquote class="issue" id="issue-6b2a45ae"><a class="self-link" href="#issue-6b2a45ae"></a> Should copy elision for non-class types belong to a separate proposal? </blockquote>
   <h3 class="heading settled" data-level="6.5" id="invalidation"><span class="secno">6.5. </span><span class="content">What about the invalidation of optimizations?</span><a class="self-link" href="#invalidation"></a></h3>
   <p>Observe an example:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>struct</c-> <c- n>A</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- b>int</c-> <c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- n>A</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- o>:</c-> <c- n>x</c-><c- p>(</c-><c- n>x</c-><c- p>)</c-> <c- p>{}</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- n>A</c-><c- p>(</c-><c- k>const</c-> <c- n>A</c-><c- o>&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- o>:</c-> <c- n>x</c-><c- p>(</c-><c- n>o</c-><c- p>.</c-><c- n>x</c-><c- p>)</c-> <c- p>{}</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>};</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- k>extern</c-> <c- n>A</c-> <c- n>global</c-><c- p>;</c-></span><span class="line-no" data-line="7"></span><span class="line"></span><span class="line-no" data-line="8"></span><span class="line"><c- n>A</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="9"></span><span class="line">  <c- n>A</c-> <c- n>local</c-><c- p>(</c-><c- mi>2</c-><c- p>);</c-></span><span class="line-no" data-line="10"></span><span class="line">  <c- n>local</c-><c- p>.</c-><c- n>x</c-> <c- o>+=</c-> <c- n>global</c-><c- p>.</c-><c- n>x</c-><c- p>;</c-></span><span class="line-no" data-line="11"></span><span class="line">  <c- k>return</c-> <c- n>local</c-><c- p>;</c-></span><span class="line-no" data-line="12"></span><span class="line"><c- p>}</c-></span></pre>
   <p>Currently, copy elision is not guaranteed here and cannot make invalid code valid. <code class="highlight"><c- n>global</c-></code> at line 10 can be assumed to have nothing common with local, e.g. <code class="highlight"><c- n>global</c-></code> cannot be defined as <code class="highlight"><c- n>A</c-> <c- n>global</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c-></code>. Compilers use this knowledge to optimize <code class="highlight"><c- n>foo</c-></code> to the equivalent of:</p>
<pre class="highlight"><c- n>A</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>A</c-><c- p>(</c-><c- mi>2</c-> <c- o>+</c-> <c- n>global</c-><c- p>.</c-><c- n>x</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>Under this proposal, <code class="highlight"><c- n>local</c-></code> and <code class="highlight"><c- n>global</c-></code> can be assumed to be distinct too, for a different reason. Inside <code class="highlight"><c- n>A</c-> <c- n>global</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c-></code>, <code class="highlight"><c- n>global</c-></code> and <code class="highlight"><c- n>local</c-></code> are guaranteed to denote the same object, because <code class="highlight"><c- n>local</c-></code> is a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①④">return variable</a>. Before <code class="highlight"><c- n>foo</c-></code> returns, the value of <code class="highlight"><c- n>local</c-><c- p>.</c-><c- n>x</c-></code> is accessed through glvalue <code class="highlight"><c- n>global</c-><c- p>.</c-><c- n>x</c-></code> that is not obtained from <code class="highlight"><c- n>local</c-></code>, thus the value of <code class="highlight"><c- n>global</c-><c- p>.</c-><c- n>x</c-></code> is unspecified.</p>
   <p>In summary, code which would require invalidation of optimizations for its correctness is kept incorrect.</p>
   <h4 class="heading settled" data-level="6.5.1" id="escape-analysis"><span class="secno">6.5.1. </span><span class="content">Complication of escape analysis</span><a class="self-link" href="#escape-analysis"></a></h4>
   <p>Previously, implementations could choose to never perform copy elision (<a href="http://eel.is/c++draft/class.copy.elision#1.1">[class.copy.elision]/(1.1)</a>) for some non-trivially-copyable class types. For these classes, the implementation could assume that the address of a local variable never escapes:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>widget</c-> <c- p>{</c->
  <c- n>widget</c-><c- p>()</c-> <c- p>{</c-> <c- p>}</c->
  <c- n>widget</c-><c- p>(</c-><c- n>widget</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- p>{</c-> <c- p>}</c->
<c- p>};</c->

<c- n>widget</c-> <c- nf>foo</c-><c- p>();</c->   <c- c1>// invisible implementation</c->
<c- n>widget</c-><c- o>*</c-> <c- nf>bar</c-><c- p>();</c->  <c- c1>// invisible implementation</c->

<c- b>void</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>x</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c->
  <c- k>if</c-> <c- p>(</c-><c- o>&amp;</c-><c- n>x</c-> <c- o>==</c-> <c- n>bar</c-><c- p>())</c-> <c- k>throw</c-> <c- s>"impossible"</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Under the proposed wording, <code class="highlight"><c- n>test</c-></code> is guaranteed to throw if we define <code class="highlight"><c- n>foo</c-></code> and <code class="highlight"><c- n>bar</c-></code> as follows:</p>
<pre class="highlight"><c- n>widget</c-><c- o>*</c-> <c- n>py</c-><c- p>;</c->

<c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>y</c-><c- p>;</c->
  <c- n>py</c-> <c- o>=</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>;</c->
  <c- k>return</c-> <c- n>y</c-><c- p>;</c->
<c- p>}</c->

<c- n>widget</c-><c- o>*</c-> <c- nf>bar</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> <c- n>py</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Accounting for such cases will lead to pessimizations for some implementations.</p>
   <h3 class="heading settled" data-level="6.6" id="abi"><span class="secno">6.6. </span><span class="content">Are the proposed changes source or ABI breaking?</span><a class="self-link" href="#abi"></a></h3>
   <p>Propored changes <em>can break</em> constant expressions that rely on effects of the copy-initialization and destruction that are proposed to be elided. The defect report <a data-link-type="biblio" href="#biblio-cwg2278">[CWG2278]</a>, requiring that copy elision is not performed in constant expressions, has been presented in March, 2018. However, relying on the effects of copy-initialization and destruction in constant expressions is considered exotic, and real-world code breakage is deemed to be minimal.</p>
   <p>The proposal prohibits some corner-case copy elision (<a href="#req-lambda">§ 6.2.2 Copy elision is no longer allowed for lambda captures</a>), which was most probably a defect. Note that previously, copy elision could not be relied upon by portable programs.</p>
   <p>The proposal allows some new cases of copy elision described in previous sub-sections. Programs that relied on copy elision not being performed there (corner-case scenarios) will no longer be valid.</p>
   <p>The proposal is <em>not</em> ABI-breaking, because, in all known implementations, whether NRVO is performed for a function does not impact its calling convention.</p>
   <h3 class="heading settled" data-level="6.7" id="costs"><span class="secno">6.7. </span><span class="content">What are the costs associated with the proposed changes?</span><a class="self-link" href="#costs"></a></h3>
   <p>There is no runtime cost associated with the proposed copy elision, because storage for the return object is allocated on stack before the function body starts executing, in all known implementations.</p>
   <p>The proposal will make declarations of local variables with automatic storage duration context-dependent: storage of a variable will depend on <code class="highlight"><c- k>return</c-></code> statements in its potential scope. However, this analysis is local and purely syntactic. The impact on compilation times is thus deemed to be minimal.</p>
   <p>Compilers that already perform NRVO will enable it (or at least the required part of it) in all compilation modes. The proposal might even have a positive impact on compilation time, because such implementations will not have to check whether copy-initialization on the return type can be performed.</p>
   <h2 class="heading settled" data-level="7" id="implementation"><span class="secno">7. </span><span class="content">Implementation experience</span><a class="self-link" href="#implementation"></a></h2>
   <h3 class="heading settled" data-level="7.1" id="implementation-exceptions"><span class="secno">7.1. </span><span class="content">How to deal with exceptions?</span><a class="self-link" href="#implementation-exceptions"></a></h3>
   <p>If the <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> statement is executed, but the destruction of a local variable throws, we may need to destroy the return variable. Some popular compilers, such as GCC and Clang, fail to call the destructor for the return variable in such cases (as of the time of writing) when they choose to perform copy elision:</p>
   <ul>
    <li data-md>
     <p><a href="https://bugs.llvm.org/show_bug.cgi?id=12286">This bug report</a> was filed against Clang in 2012 and still is open</p>
    <li data-md>
     <p><a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33799">This bug report</a> was filed against GCC in 2007 and still is open</p>
   </ul>
   <p>Here are some tests that we have to keep in mind when implementing the proposal:</p>
<pre class="highlight"><c- cp>#include</c-> &lt;cstdio>

<c- k>struct</c-> <c- n>X</c-> <c- p>{</c->
  <c- b>char</c-> <c- n>s</c-><c- p>;</c->
  <c- b>bool</c-> <c- k>throws</c-><c- p>;</c->

  <c- o>~</c-><c- n>X</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>(</c->false<c- p>)</c-> <c- p>{</c->
    <c- n>printf</c-><c- p>(</c-><c- s>"~%c</c-><c- se>\n</c-><c- s>"</c-><c- p>,</c-> <c- n>s</c-><c- p>);</c->
    <c- k>if</c-> <c- p>(</c-><c- k>throws</c-><c- p>)</c-> <c- k>throw</c-> <c- mi>0</c-><c- p>;</c->
  <c- p>}</c->

  <c- n>X</c-><c- p>(</c-><c- n>X</c-><c- o>&amp;&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->

  <c- k>explicit</c-> <c- nf>X</c-><c- p>(</c-><c- b>char</c-> <c- n>s</c-><c- p>,</c-> <c- b>bool</c-> <c- k>throws</c-> <c- o>=</c-> false<c- p>)</c-> 
    <c- o>:</c-> <c- n>s</c-><c- p>(</c-><c- n>s</c-><c- p>),</c-> <c- k>throws</c-><c- p>(</c-><c- k>throws</c-><c- p>)</c->
  <c- p>{</c->
    <c- n>printf</c-><c- p>(</c-><c- s>"%c</c-><c- se>\n</c-><c- s>"</c-><c- p>,</c-> <c- n>s</c-><c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- c1>// correct order of destruction: ma</c->
<c- n>X</c-> <c- nf>test1</c-><c- p>()</c-> <c- p>{</c->
  <c- n>X</c-> <c- n>m</c-><c- p>(</c-><c- sc>'m'</c-><c- p>,</c-> true<c- p>);</c->
  <c- k>return</c-> <c- n>X</c-><c- p>(</c-><c- sc>'a'</c-><c- p>);</c->
<c- p>}</c->

<c- c1>// correct order of destruction: dbmca</c->
<c- n>X</c-> <c- nf>test2</c-><c- p>()</c-> <c- p>{</c->
  <c- n>X</c-> <c- n>a</c-><c- p>(</c-><c- sc>'a'</c-><c- p>);</c->
  <c- n>X</c-> <c- n>m</c-><c- p>(</c-><c- sc>'m'</c-><c- p>,</c-> true<c- p>);</c->
  <c- n>X</c-> <c- n>b</c-><c- p>(</c-><c- sc>'b'</c-><c- p>);</c->
  <c- n>X</c-> <c- n>c</c-><c- p>(</c-><c- sc>'c'</c-><c- p>);</c->
  <c- n>X</c-> <c- n>d</c-><c- p>(</c-><c- sc>'d'</c-><c- p>);</c->
  <c- k>return</c-> <c- n>c</c-><c- p>;</c->
<c- p>}</c->

<c- c1>// correct order of destruction: mab</c->
<c- n>X</c-> <c- nf>test3</c-><c- p>()</c-> <c- p>{</c->
  <c- n>X</c-> <c- n>a</c-><c- p>(</c-><c- sc>'a'</c-><c- p>);</c->
  <c- n>X</c-> <c- n>b</c-><c- p>(</c-><c- sc>'b'</c-><c- p>);</c->
  <c- k>try</c-> <c- p>{</c->
    <c- n>X</c-> <c- n>m</c-><c- p>(</c-><c- sc>'m'</c-><c- p>,</c-> true<c- p>);</c->
    <c- k>return</c-> <c- n>b</c-><c- p>;</c->
  <c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>b</c-><c- p>;</c->  <c- c1>// b is returned here</c->
<c- p>}</c->

<c- c1>// correct order of destruction if cond:  mbad</c->
<c- c1>// correct order of destruction if !cond: bmcad</c->
<c- n>X</c-> <c- nf>test4</c-><c- p>(</c-><c- b>bool</c-> <c- n>cond</c-><c- p>)</c-> <c- p>{</c->
  <c- n>X</c-> <c- n>a</c-><c- p>(</c-><c- sc>'a'</c-><c- p>);</c->
  <c- k>try</c-> <c- p>{</c->
    <c- n>X</c-> <c- n>m</c-><c- p>(</c-><c- sc>'m'</c-><c- p>,</c-> true<c- p>);</c->
    <c- p>{</c->
      <c- n>X</c-> <c- n>b</c-><c- p>(</c-><c- sc>'b'</c-><c- p>);</c->
      <c- k>if</c-> <c- p>(</c-><c- n>cond</c-><c- p>)</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>b</c-><c- p>;</c->
      <c- p>}</c->
    <c- p>}</c->
    <c- p>{</c->
      <c- n>X</c-> <c- n>c</c-><c- p>(</c-><c- sc>'c'</c-><c- p>);</c->
      <c- k>return</c-> <c- n>c</c-><c- p>;</c->
    <c- p>}</c->
  <c- p>}</c-> <c- k>catch</c-> <c- p>(...)</c-> <c- p>{</c-> <c- p>}</c->
  <c- k>return</c-> <c- n>X</c-><c- p>(</c-><c- sc>'d'</c-><c- p>);</c->
<c- p>}</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
  <c- k>try</c-> <c- p>{</c-> <c- n>test1</c-><c- p>();</c-> <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{}</c-> <c- n>puts</c-><c- p>(</c-><c- s>""</c-><c- p>);</c->
  <c- k>try</c-> <c- p>{</c-> <c- n>test2</c-><c- p>();</c-> <c- p>}</c-> <c- k>catch</c-><c- p>(...)</c-> <c- p>{}</c-> <c- n>puts</c-><c- p>(</c-><c- s>""</c-><c- p>);</c->
  <c- n>test3</c-><c- p>();</c-> <c- n>puts</c-><c- p>(</c-><c- s>""</c-><c- p>);</c->
  <c- n>test4</c-><c- p>(</c->true<c- p>);</c-> <c- n>puts</c-><c- p>(</c-><c- s>""</c-><c- p>);</c->
  <c- n>test4</c-><c- p>(</c->false<c- p>);</c-> <c- n>puts</c-><c- p>(</c-><c- s>""</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="7.2" id="implementation-strategy"><span class="secno">7.2. </span><span class="content">An exception-safe implementation strategy</span><a class="self-link" href="#implementation-strategy"></a></h3>
   <p>All possible "exceptional" cases can be grouped into two categories:</p>
   <ul>
    <li data-md>
     <p>If the variable, which destruction throws, is defined <em>inside</em> the potential scope of the return variable, we need to revert the effects of the <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> statement, and not destroy the variable right away</p>
    <li data-md>
     <p>If the variable, which destruction throws, is defined <em>outside</em> the potential scope of the return variable, we need to destroy the return variable</p>
   </ul>
   <p>To deal with the various possible circumstances, the following implementation strategy is suggested:</p>
   <blockquote>
    <ul>
     <li data-md>
      <p>There are two flags per function:</p>
      <ul>
       <li data-md>
        <p>The "initialized" flag, <code class="highlight">true</code> when the object would be alive even without NRVO</p>
       <li data-md>
        <p>The "returned" flag, <code class="highlight">true</code> when we have executed <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> and no destructor has thrown yet</p>
       <li data-md>
        <p>Both initially <code class="highlight">false</code></p>
      </ul>
     <li data-md>
      <p>After the construction of a return variable:</p>
      <ul>
       <li data-md>
        <p>Set "initialized" to <code class="highlight">true</code></p>
      </ul>
     <li data-md>
      <p>At the normal destruction of a return variable:</p>
      <ul>
       <li data-md>
        <p>Set "initialized" to <code class="highlight">false</code></p>
       <li data-md>
        <p>Only destroy if "returned" is <code class="highlight">false</code></p>
      </ul>
     <li data-md>
      <p>At the <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> statement:</p>
      <ul>
       <li data-md>
        <p>Set "returned" to <code class="highlight">true</code></p>
      </ul>
     <li data-md>
      <p>If the potentially-throwing destructor of a local variable (other than a return variable), which potential scope contains a <code class="highlight"><c- k>return</c-></code> statement, throws:</p>
      <ul>
       <li data-md>
        <p>If "initialized" is <code class="highlight">false</code> and "returned" is <code class="highlight">true</code>, destroy the result slot</p>
       <li data-md>
        <p>Set "returned" to <code class="highlight">false</code></p>
      </ul>
     <li data-md>
      <p>After the execution of the operand of a <code class="highlight"><c- k>return</c-></code> statement (other than a <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> statement), but before the destruction of temporaries:</p>
      <ul>
       <li data-md>
        <p>Set "returned" to <code class="highlight">true</code></p>
      </ul>
     <li data-md>
      <p>In a <code class="highlight"><c- k>return</c-></code> statement (other than a <code class="highlight"><c- k>return</c-> <c- n>rv</c-><c- p>;</c-></code> statement), if the potentially-throwing destructor of a temporary throws:</p>
      <ul>
       <li data-md>
        <p>Destroy the return slot</p>
       <li data-md>
        <p>Set "returned" to <code class="highlight">false</code></p>
      </ul>
    </ul>
   </blockquote>
   <p>It is expected that constant propagation eliminates all branches at least for non-exceptional paths. An implementation that uses Table-Driven Exception Handling can instead fold these flags into exception-handling tables, eliminating all overhead for non-exceptional paths.</p>
   <h3 class="heading settled" data-level="7.3" id="potential-elision"><span class="secno">7.3. </span><span class="content">When is copy elision for potential return variables feasible?</span><a class="self-link" href="#potential-elision"></a></h3>
   <p>Extended copy elision (treating a potential return variable as a return variable) does not seem to be easily achievable. For example:</p>
<pre class="highlight"><c- b>bool</c-> <c- nf>toss_a_coin</c-><c- p>()</c-> <c- p>{</c->
  <c- k>return</c-> true<c- p>;</c->
<c- p>}</c->

<c- n>widget</c-> <c- nf>test</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>a</c-><c- p>;</c->
  <c- n>widget</c-> <c- n>b</c-><c- p>;</c->
  <c- n>widget</c-> <c- n>c</c-><c- p>;</c->
  <c- k>if</c-> <c- p>(</c-><c- n>toss_a_coin</c-><c- p>())</c-> <c- p>{</c->
    <c- k>return</c-> <c- n>widget</c-><c- p>();</c->  <c- c1>// d</c->
  <c- p>}</c->
  <c- k>return</c-> <c- n>b</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>If the implementation treats <code class="highlight"><c- n>b</c-></code> as a return variable, then the destruction shall occur in the order "dcba". (Because <code class="highlight"><c- n>b</c-></code> does not end up being returned, is shall be treated like a normal local variable.) But that means <code class="highlight"><c- n>b</c-></code> is destroyed after <code class="highlight"><c- n>d</c-></code> is constructed, which is not possible. To perform copy elision in this case, the implementation must prove that the destruction of <code class="highlight"><c- n>b</c-></code> can be moved right before the construction of <code class="highlight"><c- n>d</c-></code> (and before the destruction of <code class="highlight"><c- n>c</c-></code>!) under the "as-if" rule.</p>
   <p>This only seems feasible in case no non-trivially-destructible variables are declared between the potential return variable <code class="highlight"><c- n>b</c-></code> and the <code class="highlight"><c- k>return</c-></code> statement that does not return <code class="highlight"><c- n>b</c-></code>, and if the operand of the <code class="highlight"><c- k>return</c-></code> statement is "sufficiently pure". These limiting conditions are satisfied in the following common case:</p>
<pre class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>test</c-><c- p>()</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>result</c-><c- p>;</c->
  <c- n>fill_vector</c-><c- p>(</c-><c- n>result</c-><c- p>);</c->
  <c- k>if</c-> <c- p>(</c-><c- n>something_went_wrong</c-><c- p>(</c-><c- n>result</c-><c- p>))</c-> <c- k>return</c-> <c- p>{};</c->
  <c- k>return</c-> <c- n>result</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="7.4" id="implementation-circle"><span class="secno">7.4. </span><span class="content">A proof of concept implementation in Circle</span><a class="self-link" href="#implementation-circle"></a></h3>
   <p>The suggested exception-safe algorithm has been implemented by Sean Baxter in <a href="https://www.circle-lang.org/">Circle</a> compiler <a data-link-type="biblio" href="#biblio-p2062r0">[p2062r0]</a>, <a href="http://circle-lang.org/linux/build_98.tgz">build 98</a>. For the purposes of this proposal, Circle can be viewed as a Clang fork with several extensions, including, now, guaranteed copy elision for return variables.</p>
   <p>The initial testing shows that all the cases are handled correctly. Analysis of the IR and assembly at -O2 shows no sign of the flags - they are eliminated by constant propagation and incorporated into TDEH by the existing passes.</p>
   <p>The only limitation of the current implementation is that discarded branches of "if constexpr" can still prevent "guaranteed NRVO" from happening. No non-guaranteed copy elision for potential return variables is provided.</p>
   <h2 class="heading settled" data-level="8" id="alternatives"><span class="secno">8. </span><span class="content">Alternative solutions</span><a class="self-link" href="#alternatives"></a></h2>
   <h3 class="heading settled" data-level="8.1" id="existing-features"><span class="secno">8.1. </span><span class="content">Implement similar functionality using existing features</span><a class="self-link" href="#existing-features"></a></h3>
   <p>We can implement similar functionality, with cooperation from the returned object type, in some cases.</p>
   <p>Suppose the <code class="highlight"><c- n>widget</c-></code> class defines the following constructor, among others:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-><c- p>...</c-> <c- n>Args</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>invocable</c-><c- o>&lt;</c-><c- n>widget</c-><c- o>&amp;></c-> <c- n>Func</c-><c- o>></c->
<c- n>widget</c-><c- p>(</c-><c- n>Args</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>args</c-><c- p>,</c-> <c- n>Func</c-><c- o>&amp;&amp;</c-> <c- n>func</c-><c- p>)</c->
  <c- o>:</c-> <c- n>widget</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Args</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>)...)</c->
  <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Func</c-><c- o>></c-><c- p>(</c-><c- n>func</c-><c- p>)),</c-> <c- o>*</c-><c- k>this</c-><c- p>);</c-> <c- p>}</c->
</pre>
   <p>We can then use it to observe the result object of a prvalue through a reference before returning it:</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- b>int</c-> <c- n>y</c-> <c- o>=</c-> <c- n>process</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->

  <c- k>return</c-> <c- n>widget</c-><c- p>(</c-><c- n>x</c-><c- p>,</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>](</c-><c- n>widget</c-><c- o>&amp;</c-> <c- n>w</c-><c- p>)</c-> <c- p>{</c->
    <c- n>w</c-><c- p>.</c-><c- n>set_y</c-><c- p>(</c-><c- n>y</c-><c- p>);</c->
  <c- p>});</c->
<c- p>}</c->
</pre>
   <p>However, it requires cooperation from <code class="highlight"><c- n>widget</c-></code> and breaks when some of its other constructors accept an invocable parameter. We cannot implement this functionality in general.</p>
   <h3 class="heading settled" data-level="8.2" id="more-nrvo"><span class="secno">8.2. </span><span class="content">"Guarantee NRVO" in more cases</span><a class="self-link" href="#more-nrvo"></a></h3>
<pre class="highlight"><c- k>class</c-> <c- nc>builder</c-> <c- p>{</c->
<c- k>public</c-><c- o>:</c->
  <c- n>builder</c-><c- p>();</c->
  <c- n>widget</c-> <c- nf>build</c-><c- p>();</c->
  <c- n>widget</c-> <c- nf>rebuild</c-><c- p>();</c->
  …
<c- p>};</c->

<c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- n>builder</c-> <c- n>b</c-><c- p>;</c->
  <c- n>widget</c-> <c- n>w</c-> <c- o>=</c-> <c- n>b</c-><c- p>.</c-><c- n>build</c-><c- p>();</c->
  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- n>b</c-><c- p>.</c-><c- n>rebuild</c-><c- p>();</c->
  <c- k>return</c-> <c- n>w</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Copy elision will <strong>not</strong> be guaranteed for <code class="highlight"><c- n>w</c-></code>, according to this proposal. Meanwhile, one could say that it could be guaranteed: if the condition is true, then we could arrange it so that <code class="highlight"><c- n>w</c-></code> (which is stored as the return object) is destroyed before <code class="highlight"><c- n>b</c-><c- p>.</c-><c- n>rebuild</c-><c- p>()</c-></code> is called.</p>
   <p>However, what if <code class="highlight"><c- n>build</c-></code> saves a pointer to the returned object, which is then used in <code class="highlight"><c- n>rebuild</c-></code>? Then the <code class="highlight"><c- n>b</c-><c- p>.</c-><c- n>rebuild</c-><c- p>()</c-></code> call will try to reach for <code class="highlight"><c- n>w</c-></code>, which will lead to undefined behavior.</p>
   <p>While the compiler can in some cases analyze the control flow and usage patterns (usually after inlining is performed), this is impossible in general. (This is why a previous attempt at "guaranteeing NRVO" was shut down, see <a data-link-type="biblio" href="#biblio-cwg2278">[CWG2278]</a>.) The limitations of the proposed solution describe the cases where correctness can always be guaranteed without overhead and non-local reasoning.</p>
   <h3 class="heading settled" data-level="8.3" id="explicit-mark"><span class="secno">8.3. </span><span class="content">Require an explicit mark for return variables</span><a class="self-link" href="#explicit-mark"></a></h3>
   <p>As an alternative, <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①⑤">return variables</a> could require a specific attribute or a mark of some sort in order to be eligible for guaranteed copy elision:</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>w</c-> <c- p>[[</c-><c- n>nrvo</c-><c- p>]];</c->
  <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
  <c- k>return</c-> <c- n>w</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>The mark would only be applicable to non-trivially-copyable return types.</p>
   <p>The benefit of requiring a mark is that the compiler would not have to determine for each local variable whether it could be a return variable. However, the cost of the compile-time checks is deemed to be low, while there would be some language complexity cost associated with the mark.</p>
   <p>Another benefit would be that the reader of the code would be able to see at a glance that <code class="highlight"><c- n>w</c-></code> is a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①⑥">return variable</a> without reading further.</p>
   <p>The arguments against requiring an explicit mark are:</p>
   <ul>
    <li data-md>
     <p>The mark takes space and makes code less elegant</p>
    <li data-md>
     <p>In the majority of cases, control flow is not exceedingly complex</p>
    <li data-md>
     <p>If the objects of some class should not be moved, it is usually a good idea to make the class non-movable</p>
    <li data-md>
     <p><code class="highlight"><c- n>pin</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> (<a href="#pin">§ 9.5 std::pin&lt;T> class</a>) could be used to protect against copying when it is important, but the type is movable</p>
    <li data-md>
     <p>Without the mark, existing code can benefit from guaranteed copy elision</p>
   </ul>
   <h3 class="heading settled" data-level="8.4" id="alias-expressions"><span class="secno">8.4. </span><span class="content">Alias expressions</span><a class="self-link" href="#alias-expressions"></a></h3>
   <p>Alias expressions would be a new type of expression. An <dfn data-dfn-type="abstract-op" data-export id="abstract-opdef-alias-expression">alias expression<a class="self-link" href="#abstract-opdef-alias-expression"></a></dfn> would accept a prvalue, execute a block, providing that block a "magical" reference to the result object of that prvalue, and the alias expression would itself be a prvalue with the original result object:</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>setup_widget</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- k>return</c-> <c- k>using</c-> <c- p>(</c-><c- n>w</c-> <c- o>=</c-> <c- n>widget</c-><c- p>())</c-> <c- p>{</c->
    <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <p>Such a construct would require more wording and special cases on the behavior of the "magical" reference <code class="highlight"><c- n>w</c-></code> and the underlying object. It would be prohibited to <code class="highlight"><c- k>return</c-></code> from inside the block of the alias expression. More importantly, alias expressions would introduce the precedent of an expression that contains statements, which has issues with a lot of the standard. And as with <a href="#explicit-mark">explicit marks</a>, it introduces more syntax, which the proposed solution avoids.</p>
   <p>Alias expressions could also be used to get rid of copies in places other than the return expressions, e.g. when passing a function argument by value:</p>
<pre class="highlight"><c- b>void</c-> <c- nf>consume_widget</c-><c- p>(</c-><c- n>widget</c-><c- p>);</c->

<c- b>void</c-> <c- nf>test</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- n>consume_widget</c-><c- p>(</c-><c- k>using</c-> <c- p>(</c-><c- n>w</c-> <c- o>=</c-> <c- n>widget</c-><c- p>())</c-> <c- p>{</c->
    <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
  <c- p>});</c->
<c- p>}</c->
</pre>
   <p>The proposed solution can be used with an immediately invoked lambda expression to perform the same task:</p>
<pre class="highlight"><c- b>void</c-> <c- nf>consume_widget</c-><c- p>(</c-><c- n>widget</c-><c- p>);</c->

<c- b>void</c-> <c- nf>test</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- n>consume_widget</c-><c- p>([</c-><c- o>&amp;</c-><c- p>]</c-> <c- p>{</c->
    <c- n>widget</c-> <c- n>w</c-><c- p>;</c->
    <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
    <c- k>return</c-> <c- n>w</c-><c- p>;</c->
  <c- p>}());</c->
<c- p>}</c->
</pre>
   <h2 class="heading settled" data-level="9" id="future-work"><span class="secno">9. </span><span class="content">Future work</span><a class="self-link" href="#future-work"></a></h2>
   <h3 class="heading settled" data-level="9.1" id="more-elision"><span class="secno">9.1. </span><span class="content">Guarantee some other types of copy elision</span><a class="self-link" href="#more-elision"></a></h3>
   <p><a href="http://eel.is/c++draft/class.copy.elision#1">[class.copy.elision]/1</a> describes 4 cases where copy elision is allowed. Let us review whether it is feasible to guarantee copy elision in those cases:</p>
   <ul>
    <li data-md>
     <p>(1.1) is feasible to guarantee with the limitations described in this proposal, because such an "optimization" is always correct, does not introduce overhead and does not require non-local reasoning.</p>
    <li data-md>
     <p>(1.2) leads to an extra allocation in case the control flow escapes the scope before the throw-expression is executed. It would only be feasible to guarantee when the scope contains no other jump statements, and all the functions called are <code class="highlight"><c- k>noexcept</c-></code>. Those cases are deemed highly specific, but <strong>can</strong> be tackled in a separate proposal.</p>
    <li data-md>
     <p>(1.3) requires non-local reasoning and is therefore infeasible to guarantee.</p>
    <li data-md>
     <p>(1.4) requires non-local reasoning and is therefore infeasible to guarantee.</p>
   </ul>
   <h3 class="heading settled" data-level="9.2" id="disallowed-elision"><span class="secno">9.2. </span><span class="content">Guarantee currently disallowed types of copy elision</span><a class="self-link" href="#disallowed-elision"></a></h3>
   <p>Requiring copy elision in more cases than is currently allowed by the standard is a breaking change and is out of scope of this proposal. If another proposal that guarantees copy elision in more cases is accepted, those cases could also be reviewed for feasibility of guaranteed copy elision. This proposal will not be influenced by that future work.</p>
   <h3 class="heading settled" data-level="9.3" id="other-moves"><span class="secno">9.3. </span><span class="content">Reduce the number of moves performed in other cases</span><a class="self-link" href="#other-moves"></a></h3>
   <p>This proposal belongs to a group of proposals that aim to reduce the number of moves performed in C++ programs. Within that group, there are two subgroups:</p>
   <ul>
    <li data-md>
     <p>Some proposals allow to replace moves with operations that are yet cheaper than moves (known as relocation or destructive move): <a data-link-type="biblio" href="#biblio-n4158">[N4158]</a>, <a data-link-type="biblio" href="#biblio-p0023r0">[P0023R0]</a>, <a data-link-type="biblio" href="#biblio-p1144r5">[P1144R5]</a>.</p>
    <li data-md>
     <p>Other proposals aim to remove the need for moving altogether. This proposal, as well as <a data-link-type="biblio" href="#biblio-p0927r2">[P0927R2]</a>, belongs to that group.</p>
   </ul>
   <p>The problem solved by the current proposal is orthogonal to the problems dealt with by relocation proposals, as well as to the problem dealt with by P0927R2.</p>
   <p>The current proposal combines with <a data-link-type="biblio" href="#biblio-p0927r2">[P0927R2]</a> nicely. That proposal requires that the lazy parameter is only used once (and forwarded to another lazy parameter or to its final destination), while in some cases it may be desirable to acquire and use it for some time before forwarding. This proposal would allow to achieve it in a clean way, see the immediately invoked lambda expression example.</p>
   <p>The changes proposed by this proposal and <a data-link-type="biblio" href="#biblio-p0927r2">[P0927R2]</a>, combined, would allow to implement alias expressions (see the corresponding section) without any extra help from the language:</p>
<pre class="highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- p>,</c-> <c- n>invokable</c-><c- o>&lt;</c-><c- n>T</c-><c- o>&amp;></c-> <c- n>Func</c-><c- o>></c->
<c- n>T</c-> <c- n>also</c-><c- p>([]</c-> <c- o>-></c-> <c- n>T</c-> <c- n>value</c-><c- p>,</c-> <c- n>Func</c-><c- o>&amp;&amp;</c-> <c- n>func</c-><c- p>)</c-> <c- p>{</c->
  <c- n>T</c-> <c- n>computed</c-> <c- o>=</c-> <c- n>value</c-><c- p>();</c->
  <c- n>func</c-><c- p>(</c-><c- n>computed</c-><c- p>);</c->
  <c- k>return</c-> <c- n>computed</c-><c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- n>consume_widget</c-><c- p>(</c-><c- n>widget</c-><c- p>);</c->

<c- b>void</c-> <c- nf>test</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c-> <c- p>{</c->
  <c- n>consume_widget</c-><c- p>(</c-><c- n>also</c-><c- p>(</c-><c- n>widget</c-><c- p>(</c-><c- n>x</c-><c- p>),</c-> <c- p>[</c-><c- o>&amp;</c-><c- p>](</c-><c- k>auto</c-><c- o>&amp;</c-> <c- n>w</c-><c- p>)</c-> <c- p>{</c->
    <c- n>w</c-><c- p>.</c-><c- n>set_x</c-><c- p>(</c-><c- n>x</c-><c- p>);</c->
  <c- p>}));</c->
<c- p>}</c->
</pre>
   <h3 class="heading settled" data-level="9.4" id="more-temporaries"><span class="secno">9.4. </span><span class="content">Allow temporaries to be created for types other than trivially-copyables</span><a class="self-link" href="#more-temporaries"></a></h3>
   <p>Currently, extra copies of the result object are allowed for trivially copyable types, to allow passing those objects in registers, presumably when it is beneficial for performance. A relocation proposal, such as <a data-link-type="biblio" href="#biblio-p1144r5">[P1144R5]</a>, could allow trivially relocatable types to be treated the same way. If so, then those types will need to be excluded from guaranteed copy elision.</p>
   <p>This important change will be source-breaking and will lead to silent UB and bugs if the relocation proposal (with the exemption for trivially relocatable types) is accepted in a later C++ version compared to this proposal.</p>
   <h3 class="heading settled" data-level="9.5" id="pin"><span class="secno">9.5. </span><span class="content"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>pin</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> class</span><a class="self-link" href="#pin"></a></h3>
   <p>For trivially copyable types, copy elision will still be non-guaranteed: the implementation may do a trivial copy to pass the result in registers. Meanwhile, sometimes it is highly desirable to have the guarantee for the absence of copies, e.g. when a pointer to the variable is stored elsewhere. To help in this situation, we may want a non-copyable, non-movable wrapper <code class="highlight"><c- n>pin</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> which is an aggregate with a single <code class="highlight"><c- n>value</c-></code> data member. It can be used as follows:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>A</c-> <c- p>{</c->
  <c- n>A</c-><c- o>*</c-> <c- n>p</c-><c- p>;</c->
  <c- k>constexpr</c-> <c- nf>A</c-><c- p>(</c-><c- b>int</c-><c- p>)</c-> <c- o>:</c-> <c- n>p</c-><c- p>(</c-><c- k>this</c-><c- p>)</c-> <c- p>{}</c->
<c- p>};</c->

<c- k>constexpr</c-> <c- n>pin</c-><c- o>&lt;</c-><c- n>A</c-><c- o>></c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- n>pin</c-><c- o>&lt;</c-><c- n>A</c-><c- o>></c-> <c- n>x</c-><c- p>{</c-><c- mi>1</c-><c- p>};</c->
  <c- k>return</c-> <c- n>x</c-><c- p>;</c->
<c- p>}</c->

<c- b>void</c-> <c- n>test_foo</c-><c- p>()</c-> <c- p>{</c->
  <c- k>constexpr</c-> <c- k>auto</c-> <c- n>y</c-> <c- o>=</c-> <c- n>foo</c-><c- p>();</c->
  <c- k>static_assert</c-><c- p>(</c-><c- n>y</c-><c- p>.</c-><c- n>value</c-><c- p>.</c-><c- n>p</c-> <c- o>==</c-> <c- o>&amp;</c-><c- n>y</c-><c- p>.</c-><c- n>value</c-><c- p>);</c->  <c- c1>// OK</c->
<c- p>}</c->

<c- n>pin</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c->
  <c- n>pin</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-> <c- n>std</c-><c- o>::</c-><c- n>string</c-> <c- n>y</c-><c- p>;</c->
  …
  <c- k>if</c-> <c- p>(</c->…<c- p>)</c-> <c- k>return</c-> <c- p>{};</c->
  …
  <c- k>return</c-> <c- n>y</c-><c- p>;</c->  <c- c1>// ERROR: y is not a return variable</c->
<c- p>}</c->
</pre>
   <p>The <code class="highlight"><c- n>pin</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> class can be implemented as follows:</p>
<pre class="highlight"><c- k>struct</c-> <c- n>__pin_non_movable</c-> <c- p>{</c->
  <c- n>__pin_non_movable</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>__pin_non_movable</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>delete</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
<c- k>struct</c-> <c- n>__pin_holder</c-> <c- p>{</c->
  <c- n>T</c-> <c- n>value</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- n>T</c-><c- o>></c->
<c- k>struct</c-> <c- nl>pin</c-> <c- p>:</c-> <c- n>__pin_holder</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- n>__pin_non_movable</c-> <c- p>{</c-> <c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="9.6" id="optional-mark"><span class="secno">9.6. </span><span class="content">Add an optional mark <code class="highlight"><c- p>[[</c-><c- n>nrvo_verify</c-><c- p>]]</c-></code></span><a class="self-link" href="#optional-mark"></a></h3>
   <p>Sometimes it’s useful to assert that a variable is a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①⑦">return variable</a> (and of a non-trivially-copyable type, otherwise it is useless). It would allow to catch subtle bugs caused by evolution of code.</p>
   <p>Before:</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>frobnicate</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>result</c-> <c- p>[[</c-><c- n>nrvo_verify</c-><c- p>]];</c->
  <c- n>watch</c-><c- p>(</c-><c- o>&amp;</c-><c- n>result</c-><c- p>);</c->
  <c- c1>// …</c->
      <c- k>if</c-> <c- p>(</c-><c- n>good</c-><c- p>())</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>result</c-><c- p>;</c->
      <c- p>}</c->
  <c- c1>// …</c->
  <c- k>return</c-> <c- n>result</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>After:</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>frobnicate</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>result</c-> <c- p>[[</c-><c- n>nrvo_verify</c-><c- p>]];</c->  <c- c1>// ERROR, good</c->
  <c- n>watch</c-><c- p>(</c-><c- o>&amp;</c-><c- n>result</c-><c- p>);</c->
  <c- c1>// …</c->
      <c- k>if</c-> <c- p>(</c-><c- n>good</c-><c- p>())</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>result</c-><c- p>;</c->
      <c- p>}</c-> <c- k>else</c-> <c- k>if</c-> <c- p>(</c-><c- n>bad</c-><c- p>())</c-> <c- p>{</c->
        <c- k>return</c-> <c- n>widget</c-><c- p>();</c->
      <c- p>}</c->
  <c- c1>// …</c->
  <c- k>return</c-> <c- n>result</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <blockquote class="note warning-note"> Note:
This idea is different from <a href="#explicit-mark">§ 8.3 Require an explicit mark for return variables</a>. Here, the mark is optional. </blockquote>
   <blockquote class="note warning-note"> Note:
Note that the same result can be achieved using <a href="#pin">§ 9.5 std::pin&lt;T> class</a> without a specialized language feature. </blockquote>
   <h3 class="heading settled" data-level="9.7" id="complex-expressions"><span class="secno">9.7. </span><span class="content">Allow copy elision for complex expressions</span><a class="self-link" href="#complex-expressions"></a></h3>
   <p>Can copy elision be allowed in these cases?</p>
<pre class="highlight"><c- n>widget</c-> <c- nf>foo</c-><c- p>()</c-> <c- p>{</c->
  <c- n>widget</c-> <c- n>x</c-><c- p>;</c->
  <c- k>return</c-> <c- n>x</c-> <c- o>+=</c-> <c- n>bar</c-><c- p>();</c->
  <c- k>return</c-> <c- n>foo</c-><c- p>(),</c-> <c- n>bar</c-><c- p>(),</c-> <c- n>x</c-><c- p>;</c->
  <c- k>return</c-> <c- n>toss_a_coin</c-><c- p>()</c-> <c- o>?</c-> <c- n>foo</c-><c- p>()</c-> <c- o>:</c-> <c- n>x</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <ul>
    <li data-md>
     <p>For assignment operators, assuming that they return <code class="highlight"><c- o>*</c-><c- k>this</c-></code> is infeasible, as voted in Kona 2019 (<a data-link-type="biblio" href="#biblio-p1155r2">[P1155R2]</a>)</p>
    <li data-md>
     <p>For a comma operator, it can be overloaded. We could allow it in the non-overloaded case (<a data-link-type="biblio" href="#biblio-cwg2125">[CWG2125]</a>)</p>
    <li data-md>
     <p>A ternary operator could be treated as an <code class="highlight"><c- k>if</c-></code> statement, at which point <code class="highlight"><c- n>x</c-></code> cannot be a <a data-link-type="abstract-op" href="#abstract-opdef-return-variable" id="ref-for-abstract-opdef-return-variable①⑧">return variable</a> (another <code class="highlight"><c- k>return</c-></code> in scope), but we could allow it to be a <a data-link-type="abstract-op" href="#abstract-opdef-potential-return-variable" id="ref-for-abstract-opdef-potential-return-variable③">potential return variable</a>, if <code class="highlight"><c- n>x</c-></code> is not implicitly converted</p>
   </ul>
   <p>All in all, it seems that the benefits are not worth the additional complexity.</p>
   <h2 class="heading settled" data-level="10" id="acknowledgements"><span class="secno">10. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Thanks to Agustín Bergé, Arthur O’Dwyer, Krystian Stasiowski and everyone else who provided feedback on a draft of this proposal.</p>
   <p>Special thanks to Antony Polukhin for championing the proposal.</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-alias-expression">alias expression</a><span>, in §8.4</span>
   <li><a href="#abstract-opdef-potential-return-variable">potential return variable</a><span>, in §5.1</span>
   <li><a href="#abstract-opdef-return-variable">return variable</a><span>, in §5.1</span>
   <li><a href="#abstract-opdef-to-directly-observe-a-variable">to directly observe a variable</a><span>, in §5.1</span>
   <li><a href="#abstract-opdef-to-return-a-variable">to return a variable</a><span>, in §5.1</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-n4861">[N4861]
   <dd>Richard Smith, Thomas Koeppe, Jens Maurer, Dawn Perchik. <a href="https://wg21.link/n4861">Working Draft, Standard for Programming Language C++</a>. 8 April 2020. URL: <a href="https://wg21.link/n4861">https://wg21.link/n4861</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-cwg2125">[CWG2125]
   <dd>Vinny Romano. <a href="https://wg21.link/cwg2125">Copy elision and comma operator</a>. 6 May 2015. extension. URL: <a href="https://wg21.link/cwg2125">https://wg21.link/cwg2125</a>
   <dt id="biblio-cwg2278">[CWG2278]
   <dd>Richard Smith. <a href="https://wg21.link/cwg2278">Copy elision in constant expressions reconsidered</a>. 27 June 2016. drafting. URL: <a href="https://wg21.link/cwg2278">https://wg21.link/cwg2278</a>
   <dt id="biblio-n4158">[N4158]
   <dd>Pablo Halpern. <a href="https://wg21.link/n4158">Destructive Move (Rev 1)</a>. 12 October 2014. URL: <a href="https://wg21.link/n4158">https://wg21.link/n4158</a>
   <dt id="biblio-p0023r0">[P0023R0]
   <dd>Denis Bider. <a href="https://wg21.link/p0023r0">Relocator: Efficiently moving objects</a>. 8 April 2016. URL: <a href="https://wg21.link/p0023r0">https://wg21.link/p0023r0</a>
   <dt id="biblio-p0052r9">[P0052R9]
   <dd>Peter Sommerlad, Andrew L. Sandoval. <a href="https://wg21.link/p0052r9">Generic Scope Guard and RAII Wrapper for the Standard Library</a>. 3 October 2018. URL: <a href="https://wg21.link/p0052r9">https://wg21.link/p0052r9</a>
   <dt id="biblio-p0527r1">[P0527R1]
   <dd>David Stone. <a href="https://wg21.link/p0527r1">Implicitly move from rvalue references in return statements</a>. 8 November 2017. URL: <a href="https://wg21.link/p0527r1">https://wg21.link/p0527r1</a>
   <dt id="biblio-p0927r2">[P0927R2]
   <dd>James Dennett, Geoff Romer. <a href="https://wg21.link/p0927r2">Towards A (Lazy) Forwarding Mechanism for C++</a>. 5 October 2018. URL: <a href="https://wg21.link/p0927r2">https://wg21.link/p0927r2</a>
   <dt id="biblio-p1046r2">[P1046R2]
   <dd>David Stone. <a href="https://wg21.link/p1046r2">Automatically Generate More Operators</a>. 11 January 2020. URL: <a href="https://wg21.link/p1046r2">https://wg21.link/p1046r2</a>
   <dt id="biblio-p1144r5">[P1144R5]
   <dd>Arthur O'Dwyer. <a href="https://wg21.link/p1144r5">Object relocation in terms of move plus destroy</a>. 2 March 2020. URL: <a href="https://wg21.link/p1144r5">https://wg21.link/p1144r5</a>
   <dt id="biblio-p1155r2">[P1155R2]
   <dd>Arthur O'Dwyer, David Stone. <a href="https://wg21.link/p1155r2">More implicit moves</a>. 19 January 2019. URL: <a href="https://wg21.link/p1155r2">https://wg21.link/p1155r2</a>
   <dt id="biblio-p1155r3">[P1155R3]
   <dd>Arthur O'Dwyer, David Stone. <a href="https://wg21.link/p1155r3">More implicit moves</a>. 17 June 2019. URL: <a href="https://wg21.link/p1155r3">https://wg21.link/p1155r3</a>
   <dt id="biblio-p1825r0">[P1825R0]
   <dd>David Stone. <a href="https://wg21.link/p1825r0">Merged wording for P0527R1 and P1155R3</a>. 19 July 2019. URL: <a href="https://wg21.link/p1825r0">https://wg21.link/p1825r0</a>
   <dt id="biblio-p2062r0">[P2062R0]
   <dd>Daveed Vandevoorde, Wyatt Childers, Andrew Sutton, Faisal Vali. <a href="https://wg21.link/p2062r0">The Circle Meta-model</a>. 13 January 2020. URL: <a href="https://wg21.link/p2062r0">https://wg21.link/p2062r0</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"> Too many new terms might have been introduced: <a data-link-type="abstract-op" href="#abstract-opdef-to-directly-observe-a-variable">to directly observe a variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-to-return-a-variable">to return a variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-potential-return-variable">potential return variable</a>, <a data-link-type="abstract-op" href="#abstract-opdef-return-variable">return variable</a>. <a href="#issue-b1429285"> ↵ </a></div>
   <div class="issue"> Should we say "function or <em>lambda-expression</em>", or is it enough to say "function"? <a href="#issue-1d52cd17"> ↵ </a></div>
   <div class="issue"> Following the proposed wording, it cannot be known at the time of initialization of the <a data-link-type="abstract-op" href="#abstract-opdef-return-variable">return variable</a>'s object, what object it is exactly ("Schrodinger’s object"). Later on, it is retrospectively established that we either have initialized and worked with a normal local variable, or with the result object of the function call expression. <a href="#issue-2dd63f8d"> ↵ </a></div>
   <div class="issue"> "<a data-link-type="abstract-op" href="#abstract-opdef-return-variable">Return variable</a>" might not be the best term for our purposes. <a href="#issue-9ca2bd58"> ↵ </a></div>
   <div class="issue"> The previous restriction in this case looks like not-a-defect. Should this change belong to a separate proposal? <a href="#issue-395f911b"> ↵ </a></div>
   <div class="issue"> Should copy elision for non-class types belong to a separate proposal? <a href="#issue-6b2a45ae"> ↵ </a></div>
  </div>
  <aside class="dfn-panel" data-for="abstract-opdef-to-directly-observe-a-variable">
   <b><a href="#abstract-opdef-to-directly-observe-a-variable">#abstract-opdef-to-directly-observe-a-variable</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-to-directly-observe-a-variable">5.1. Definitions</a> <a href="#ref-for-abstract-opdef-to-directly-observe-a-variable①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="abstract-opdef-to-return-a-variable">
   <b><a href="#abstract-opdef-to-return-a-variable">#abstract-opdef-to-return-a-variable</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-to-return-a-variable">3. Motivation</a>
    <li><a href="#ref-for-abstract-opdef-to-return-a-variable①">4. Proposed solution</a>
    <li><a href="#ref-for-abstract-opdef-to-return-a-variable②">5.1. Definitions</a> <a href="#ref-for-abstract-opdef-to-return-a-variable③">(2)</a> <a href="#ref-for-abstract-opdef-to-return-a-variable④">(3)</a>
    <li><a href="#ref-for-abstract-opdef-to-return-a-variable⑤">5.2. The behavior of return variables</a> <a href="#ref-for-abstract-opdef-to-return-a-variable⑥">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="abstract-opdef-potential-return-variable">
   <b><a href="#abstract-opdef-potential-return-variable">#abstract-opdef-potential-return-variable</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-potential-return-variable">5.1. Definitions</a>
    <li><a href="#ref-for-abstract-opdef-potential-return-variable①">5.2. The behavior of return variables</a>
    <li><a href="#ref-for-abstract-opdef-potential-return-variable②">6.2.1. Parentheses are now allowed around the variable name</a>
    <li><a href="#ref-for-abstract-opdef-potential-return-variable③">9.7. Allow copy elision for complex expressions</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="abstract-opdef-return-variable">
   <b><a href="#abstract-opdef-return-variable">#abstract-opdef-return-variable</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-abstract-opdef-return-variable">2. Introduction</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①">5.1. Definitions</a> <a href="#ref-for-abstract-opdef-return-variable②">(2)</a>
    <li><a href="#ref-for-abstract-opdef-return-variable③">5.2. The behavior of return variables</a> <a href="#ref-for-abstract-opdef-return-variable④">(2)</a> <a href="#ref-for-abstract-opdef-return-variable⑤">(3)</a> <a href="#ref-for-abstract-opdef-return-variable⑥">(4)</a> <a href="#ref-for-abstract-opdef-return-variable⑦">(5)</a> <a href="#ref-for-abstract-opdef-return-variable⑧">(6)</a> <a href="#ref-for-abstract-opdef-return-variable⑨">(7)</a> <a href="#ref-for-abstract-opdef-return-variable①⓪">(8)</a> <a href="#ref-for-abstract-opdef-return-variable①①">(9)</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①②">6.1. Is "return variable" a good term choice?</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①③">6.2.1. Parentheses are now allowed around the variable name</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①④">6.5. What about the invalidation of optimizations?</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①⑤">8.3. Require an explicit mark for return variables</a> <a href="#ref-for-abstract-opdef-return-variable①⑥">(2)</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①⑦">9.6. Add an optional mark [[nrvo_verify]]</a>
    <li><a href="#ref-for-abstract-opdef-return-variable①⑧">9.7. Allow copy elision for complex expressions</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>