<!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>P0201R6: &lt;code>polymorphic_value&lt;/code>: A Polymorphic Value Type for C++</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
 *     -> ins/del.c### for candidate and proposed changes (amendments)
 *
 * 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)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *   - .correction for "candidate corrections"       (div, aside, details, section)
 *   - .addition   for "candidate additions"         (div, aside, details, section)
 *   - .correction.proposed for "proposed corrections" (div, aside, details, section)
 *   - .addition.proposed   for "proposed additions"   (div, aside, details, section)
 *
 * 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
 *
 * Outdated warning for old specs
 *
 * 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)
 *
 ******************************************************************************/

/* color variables included separately for reliability */

/******************************************************************************/
/*                                    Body                                    */
/******************************************************************************/

	html {
	}

	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;

		color: black;
		color: var(--text);
		background: white top left fixed no-repeat;
		background: var(--bg) 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: solid var(--logo-bg);
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		background: var(--logo-bg);
		color: white;
		color: var(--logo-text);
		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;
		background: var(--logo-active-bg);
		border-color: #c00;
		border-color: var(--logo-active-bg);
	}

	/* 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: 3;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;

			color: #707070;
			color: var(--tocnav-normal-text);
			background: white;
			background: var(--tocnav-normal-bg);
		}
		#toc-nav > a:hover,
		#toc-nav > a:focus {
			color: black;
			color: var(--tocnav-hover-text);
			background: #f8f8f8;
			background: var(--tocnav-hover-bg);
		}
		#toc-nav > a:active {
			color: #c00;
			color: var(--tocnav-active-text);
			background: white;
			background: var(--tocnav-active-bg);
		}

		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		/* 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 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);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) 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);
			color: var(--tocsidebar-heading-text);
		}
		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);
			color: black;
			color: var(--tocsidebar-text);
			background: inherit;
			background-color: #f7f8f9;
			background-color: var(--tocsidebar-bg);
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
			box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) 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);
			color: var(--tocsidebar-heading-text);
		}

		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;
		color: var(--heading-text);
	}

	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,
	#profile-and-date {
		/* #profile-and-date 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) > :not(.head) + hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		color: black;
		color: var(--hr-text);
		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;
	border-left: 0.5em solid var(--algo-border);
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	 padding: .5em;
	 border: thin solid #ddd;
	 border: thin solid var(--algo-border);
	 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: inherit;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del {
		color: #aa0000;
		color: var(--del-text);
		background: transparent;
		background: var(--del-bg);
		text-decoration: line-through;
	}
	ins {
		color: #006100;
		color: var(--ins-text);
		background: transparent;
		background: var(--ins-bg);
		text-decoration: underline;
	}

	/* for amendments (candidate/proposed changes) */

	.amendment ins, .correction ins, .addition ins,
	ins[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment del, .correction del, .addition del,
	del[class^=c] {
		text-decoration-style: dotted;
	}
	.amendment.proposed ins, .correction.proposed ins, .addition.proposed ins,
	ins[class^=c].proposed {
		text-decoration-style: double;
	}
	.amendment.proposed del, .correction.proposed del, .addition.proposed del,
	del[class^=c].proposed {
		text-decoration-style: double;
	}

/** 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;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	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;
		color: var(--a-normal-text);
		text-decoration: underline #707070;
		text-decoration: underline var(--a-normal-underline);
		text-decoration-skip-ink: none;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		text-decoration-color: #bbb;
		text-decoration-color: var(--a-visited-underline);
	}

	/* Indicate interaction with the link */
	a[href]:focus,
	a[href]:hover {
		text-decoration-thickness: 2px;
	}
	a[href]:active {
		color: #c00;
		color: var(--a-active-text);
		text-decoration-color: #c00;
		text-decoration-color: var(--a-active-underline);
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	img, svg {
		/* Intentionally not color-scheme aware. */
		background: white;
	}

	/* 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;
		height: 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,
	.amendment, .correction, .addition {
		margin: 1em auto;
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	blockquote > :first-child,
	.note  > p:first-child,
	.issue > p:first-child,
	.amendment > p:first-child,
	.correction > p:first-child,
	.addition > p:first-child {
		margin-top: 0;
	}
	blockquote > :last-child,
	.note  > p:last-child,
	.issue > p:last-child,
	.amendment > p:last-child,
	.correction > p:last-child,
	.addition > p:last-child {
		margin-bottom: 0;
	}


	.issue::before, .issue > .marker,
	.example::before, .example > .marker,
	.note::before, .note > .marker,
	details.note > summary > .marker,
	.amendment::before, .amendment > .marker,
	details.amendment > summary > .marker,
	.addition::before, .addition > .marker,
	addition.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	correction.amendment > summary > .marker
	{
		text-transform: uppercase;
		padding-right: 1em;
	}

	.example::before, .example > .marker {
		display: block;
		padding-right: 0em;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
		border-color: var(--blockquote-border);
		background: transparent;
		background: var(--blockquote-bg);
		color: currentcolor;
		color: var(--blockquote-text);
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* 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;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* 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;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary {
		color: hsl(120, 70%, 30%);
		color: var(--noteheading-text);
	}
	/* Add .note::before { content: "Note "; } for autogen label,
	  or use class="marker" to mark up the label in source. */

	details.note[open] > summary {
		border-bottom: 1px silver solid;
		border-bottom: 1px var(--notesummary-underline) solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		border-color: var(--assertion-border);
		background: #EEE;
		background: var(--assertion-bg);
		color: black;
		color: var(--assertion-text);
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-color: var(--advisement-border);
		border-style: none solid;
		background: #fec;
		background: var(--advisement-bg);
		color: black;
		color: var(--advisement-text);
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement::before, .advisement > .marker {
		color: #b35f00;
		color: var(--advisementheading-text);
	}

/** Amendment Box *************************************************************/

	.amendment, .correction, .addition {
		border-color: #330099;
		border-color: var(--amendment-border);
		background: #F5F0FF;
		background: var(--amendment-bg);
		color: black;
		color: var(--amendment-text);
	}
	.amendment.proposed, .correction.proposed, .addition.proposed {
		border-style: solid;
		border-block-width: 0.25em;
	}
	.amendment::before, .amendment > .marker,
	details.amendment > summary::before, details.amendment > summary > .marker,
	.correction::before, .correction > .marker,
	details.correction > summary::before, details.correction > summary > .marker,
	.addition::before, .addition > .marker,
	details.addition > summary::before, details.addition > summary > .marker {
		color: #220066;
		color: var(--amendmentheading-text);
	}
	.amendment.proposed::before, .amendment.proposed > .marker,
	details.amendment.proposed > summary::before, details.amendment.proposed > summary > .marker,
	.correction.proposed::before, .correction.proposed > .marker,
	details.correction.proposed > summary::before, details.correction.proposed > summary > .marker,
	.addition.proposed::before, .addition.proposed > .marker,
	details.addition.proposed > summary::before, details.addition.proposed > summary > .marker {
		font-weight: bold;
	}

/** 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: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 2em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #def;
		background: var(--def-bg);
		margin: 1.2em 0;
		border-left: 0.5em solid #8ccbf2;
		border-left: 0.5em solid var(--def-border);
		color: black;
		color: var(--def-text);
	}

/******************************************************************************/
/*                                    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;
		border-bottom: 1px solid var(--defrow-border);
	}

	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-color: var(--datacell-border);
		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;
		border-top: 1px solid var(--datacell-border);
		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;
		border: 1px solid var(--datacell-border);
		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: 0.1rem 1px 0;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Switch to using border-bottom for underlines */
		text-decoration: none;
		border-bottom: 1px solid;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:focus,
	.toc a:hover {
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	.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;
	}
	.toc {
		line-height: 1.1em;
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li			{ font-weight: bold;   }
	.toc > li li		 { font-weight: normal; }
	.toc > li li li	  { font-size:   95%;	}
	.toc > li li li li	{ font-size:   90%;	}
	.toc > li li li li li { font-size:   85%;	}

	/* @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 li li li .secno { font-size: 85%; }
		.toc > li li li li li .secno { font-size: 100%; }

		.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; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc			 { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno				 { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li			 { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno	  { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno	{ margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@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,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom: 3px solid #054572;
			border-bottom: 3px solid var(--toclink-underline);
			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 a + span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
			color: var(--indexinfo-text);
		}
	}

/** 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]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/** Outdated warning **********************************************************/

.outdated-spec {
	color: black;
	color: var(--outdatedspec-text);
	background-color: rgba(0,0,0,0.5);
	background-color: var(--outdatedspec-bg);
}

.outdated-warning {
	position: fixed;
	bottom: 50%;
	left: 0;
	right: 0;
	margin: 0 auto;
	width: 50%;
	background: maroon;
	background: var(--outdated-bg);
	color: white;
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	color: var(--outdated-text);
	border-radius: 1em;
	box-shadow: 0 0 1em red;
	box-shadow: 0 0 1em var(--outdated-shadow);
	padding: 2em;
	text-align: center;
	z-index: 2;
}

.outdated-warning a {
	color: currentcolor;
	background: transparent;
}

.edited-rec-warning {
	background: darkorange;
	background: var(--editedrec-bg);
	box-shadow: 0 0 1em;
}

.outdated-warning button {
	position: absolute;
	top: 0;
	right:0;
	margin: 0;
	border: 0;
	padding: 0.25em 0.5em;
	background: transparent;
	color: white;
	color: var(--outdated-text);
	font:1em sans-serif;
	text-align:center;
}

.outdated-warning span {
	display: block;
}

.outdated-collapsed {
	bottom: 0;
	border-radius: 0;
	width: 100%;
	padding: 0;
}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}

		.outdated-warning {
			position: absolute;
			border-style: solid;
			border-color: red;
		}

		.outdated-warning input {
			display: none;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}



/******************************************************************************/
/*                             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 item positioning:
		  "content column" is 50ems wide at max; less on smaller screens.
		  Extra space (after ToC + content) is empty on the right.

		  1. When item < content column, centers item in column.
		  2. When content < item < available, left-aligns.
		  3. When item > 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>
    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 b0de3432c, updated Thu Oct 13 09:16:59 2022 -0700" name="generator">
  <link href="https://wg21.link/P0201" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: var(--a-normal-text);
    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-colors */

/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
:root {
    color-scheme: light dark;

    --text: black;
    --bg: white;

    --unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark);

    --logo-bg: #1a5e9a;
    --logo-active-bg: #c00;
    --logo-text: white;

    --tocnav-normal-text: #707070;
    --tocnav-normal-bg: var(--bg);
    --tocnav-hover-text: var(--tocnav-normal-text);
    --tocnav-hover-bg: #f8f8f8;
    --tocnav-active-text: #c00;
    --tocnav-active-bg: var(--tocnav-normal-bg);

    --tocsidebar-text: var(--text);
    --tocsidebar-bg: #f7f8f9;
    --tocsidebar-shadow: rgba(0,0,0,.1);
    --tocsidebar-heading-text: hsla(203,20%,40%,.7);

    --toclink-text: var(--text);
    --toclink-underline: #3980b5;
    --toclink-visited-text: var(--toclink-text);
    --toclink-visited-underline: #054572;

    --heading-text: #005a9c;

    --hr-text: var(--text);

    --algo-border: #def;

    --del-text: red;
    --del-bg: transparent;
    --ins-text: #080;
    --ins-bg: transparent;

    --a-normal-text: #034575;
    --a-normal-underline: #bbb;
    --a-visited-text: var(--a-normal-text);
    --a-visited-underline: #707070;
    --a-hover-bg: rgba(75%, 75%, 75%, .25);
    --a-active-text: #c00;
    --a-active-underline: #c00;

    --blockquote-border: silver;
    --blockquote-bg: transparent;
    --blockquote-text: currentcolor;

    --issue-border: #e05252;
    --issue-bg: #fbe9e9;
    --issue-text: var(--text);
    --issueheading-text: #831616;

    --example-border: #e0cb52;
    --example-bg: #fcfaee;
    --example-text: var(--text);
    --exampleheading-text: #574b0f;

    --note-border: #52e052;
    --note-bg: #e9fbe9;
    --note-text: var(--text);
    --noteheading-text: hsl(120, 70%, 30%);
    --notesummary-underline: silver;

    --assertion-border: #aaa;
    --assertion-bg: #eee;
    --assertion-text: black;

    --advisement-border: orange;
    --advisement-bg: #fec;
    --advisement-text: var(--text);
    --advisementheading-text: #b35f00;

    --warning-border: red;
    --warning-bg: hsla(40,100%,50%,0.95);
    --warning-text: var(--text);

    --amendment-border: #330099;
    --amendment-bg: #F5F0FF;
    --amendment-text: var(--text);
    --amendmentheading-text: #220066;

    --def-border: #8ccbf2;
    --def-bg: #def;
    --def-text: var(--text);
    --defrow-border: #bbd7e9;

    --datacell-border: silver;

    --indexinfo-text: #707070;

    --indextable-hover-text: black;
    --indextable-hover-bg: #f7f8f9;

    --outdatedspec-bg: rgba(0, 0, 0, .5);
    --outdatedspec-text: black;
    --outdated-bg: maroon;
    --outdated-text: white;
    --outdated-shadow: red;

    --editedrec-bg: darkorange;
}</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-issues */

a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</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 */

:root {
    --selflink-text: white;
    --selflink-bg: gray;
    --selflink-hover-text: black;
}
.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: var(--selflink-bg);
    color: var(--selflink-text);
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: var(--selflink-hover-text);
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }
</style>
<style>/* style-syntax-highlighting */

code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }

.highlight:not(.idl) { background: rgba(0, 0, 0, .03); }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-darkmode */

@media (prefers-color-scheme: dark) {
    :root {
        --text: #ddd;
        --bg: black;

        --unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E");

        --logo-bg: #1a5e9a;
        --logo-active-bg: #c00;
        --logo-text: white;

        --tocnav-normal-text: #999;
        --tocnav-normal-bg: var(--bg);
        --tocnav-hover-text: var(--tocnav-normal-text);
        --tocnav-hover-bg: #080808;
        --tocnav-active-text: #f44;
        --tocnav-active-bg: var(--tocnav-normal-bg);

        --tocsidebar-text: var(--text);
        --tocsidebar-bg: #080808;
        --tocsidebar-shadow: rgba(255,255,255,.1);
        --tocsidebar-heading-text: hsla(203,20%,40%,.7);

        --toclink-text: var(--text);
        --toclink-underline: #6af;
        --toclink-visited-text: var(--toclink-text);
        --toclink-visited-underline: #054572;

        --heading-text: #8af;

        --hr-text: var(--text);

        --algo-border: #456;

        --del-text: #f44;
        --del-bg: transparent;
        --ins-text: #4a4;
        --ins-bg: transparent;

        --a-normal-text: #6af;
        --a-normal-underline: #555;
        --a-visited-text: var(--a-normal-text);
        --a-visited-underline: var(--a-normal-underline);
        --a-hover-bg: rgba(25%, 25%, 25%, .2);
        --a-active-text: #f44;
        --a-active-underline: var(--a-active-text);

        --borderedblock-bg: rgba(255, 255, 255, .05);

        --blockquote-border: silver;
        --blockquote-bg: var(--borderedblock-bg);
        --blockquote-text: currentcolor;

        --issue-border: #e05252;
        --issue-bg: var(--borderedblock-bg);
        --issue-text: var(--text);
        --issueheading-text: hsl(0deg, 70%, 70%);

        --example-border: hsl(50deg, 90%, 60%);
        --example-bg: var(--borderedblock-bg);
        --example-text: var(--text);
        --exampleheading-text: hsl(50deg, 70%, 70%);

        --note-border: hsl(120deg, 100%, 35%);
        --note-bg: var(--borderedblock-bg);
        --note-text: var(--text);
        --noteheading-text: hsl(120, 70%, 70%);
        --notesummary-underline: silver;

        --assertion-border: #444;
        --assertion-bg: var(--borderedblock-bg);
        --assertion-text: var(--text);

        --advisement-border: orange;
        --advisement-bg: #222218;
        --advisement-text: var(--text);
        --advisementheading-text: #f84;

        --warning-border: red;
        --warning-bg: hsla(40,100%,20%,0.95);
        --warning-text: var(--text);

        --amendment-border: #330099;
        --amendment-bg: #080010;
        --amendment-text: var(--text);
        --amendmentheading-text: #cc00ff;

        --def-border: #8ccbf2;
        --def-bg: #080818;
        --def-text: var(--text);
        --defrow-border: #136;

        --datacell-border: silver;

        --indexinfo-text: #aaa;

        --indextable-hover-text: var(--text);
        --indextable-hover-bg: #181818;

        --outdatedspec-bg: rgba(255, 255, 255, .5);
        --outdatedspec-text: black;
        --outdated-bg: maroon;
        --outdated-text: white;
        --outdated-shadow: red;

        --editedrec-bg: darkorange;
    }
    /* In case a transparent-bg image doesn't expect to be on a dark bg,
       which is quite common in practice... */
    img { background: white; }
}
@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}

@media (prefers-color-scheme: dark) {
    .highlight:not(.idl) { background: rgba(255, 255, 255, .05); }

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* 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">P0201R6<br><code class="highlight"><c- n>polymorphic_value</c-></code>: A Polymorphic Value Type for C++</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2022-10-15">2022-10-15</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/P0201">https://wg21.link/P0201</a>
     <dt>Issue Tracking:
     <dd><a href="https://github.com/jbcoe/polymorphic_value/issues">GitHub</a>
     <dt class="editor">Authors:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:jonathanbcoe@gmail.com">Jonathan B. Coe</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:ant.peacock@gmail.com">Antony Peacock</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:sparent@adobe.com">Sean Parent</a>
     <dt>Audience:
     <dd>LEWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Source:
     <dd><a href="https://github.com/jbcoe/polymorphic_value/blob/main/documentation/p0201.md">https://github.com/jbcoe/polymorphic_value/blob/main/documentation/p0201.md</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#change-history"><span class="secno">1</span> <span class="content">Change history</span></a>
    <li><a href="#tldr"><span class="secno">2</span> <span class="content">TL;DR</span></a>
    <li>
     <a href="#introduction"><span class="secno">3</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#motivation-composite-objects"><span class="secno">3.1</span> <span class="content">Motivation: Composite objects</span></a>
      <li><a href="#deep-copies"><span class="secno">3.2</span> <span class="content">Deep copies</span></a>
      <li><a href="#pointer-constructor"><span class="secno">3.3</span> <span class="content">Pointer constructor</span></a>
      <li><a href="#empty-state"><span class="secno">3.4</span> <span class="content">Empty state</span></a>
      <li><a href="#lack-of-hashing-and-comparisons"><span class="secno">3.5</span> <span class="content">Lack of hashing and comparisons</span></a>
      <li><a href="#custom-copiers-and-deleters"><span class="secno">3.6</span> <span class="content">Custom copiers and deleters</span></a>
      <li><a href="#allocator-support"><span class="secno">3.7</span> <span class="content">Allocator Support</span></a>
      <li><a href="#design-changes-from-cloned_ptr"><span class="secno">3.8</span> <span class="content">Design changes from <code class="highlight"><c- n>cloned_ptr</c-></code></span></a>
      <li><a href="#no-implicit-conversions"><span class="secno">3.9</span> <span class="content">No implicit conversions</span></a>
      <li><a href="#impact-on-the-standard"><span class="secno">3.10</span> <span class="content">Impact on the standard</span></a>
     </ol>
    <li>
     <a href="#technical-specifications"><span class="secno">4</span> <span class="content">Technical specifications</span></a>
     <ol class="toc">
      <li><a href="#additions-in-memorysyn-2022"><span class="secno">4.1</span> <span class="content">Additions in [memory.syn] 20.2.2:</span></a>
      <li><a href="#xw-class-template-copier_traits-copiertraits"><span class="secno">4.2</span> <span class="content">X.W Class template <code class="highlight"><c- n>copier_traits</c-></code> [copier.traits]</span></a>
      <li><a href="#xx-class-template-default_copy-defaultcopy"><span class="secno">4.3</span> <span class="content">X.X Class template <code class="highlight"><c- n>default_copy</c-></code> [default.copy]</span></a>
      <li><a href="#xy-class-bad_polymorphic_value_construction-bad_polymorphic_value_construction"><span class="secno">4.4</span> <span class="content">X.Y Class <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> [bad_polymorphic_value_construction]</span></a>
      <li>
       <a href="#xz-class-template-polymorphic_value-polymorphic_value"><span class="secno">4.5</span> <span class="content">X.Z Class template <code class="highlight"><c- n>polymorphic_value</c-></code> [polymorphic_value]</span></a>
       <ol class="toc">
        <li><a href="#xz1-class-template-polymorphic_value-general-polymorphic_valuegeneral"><span class="secno">4.5.1</span> <span class="content">X.Z.1 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> general [polymorphic_value.general]</span></a>
        <li><a href="#xz2-class-template-polymorphic_value-synopsis-polymorphic_valuesynopsis"><span class="secno">4.5.2</span> <span class="content">X.Z.2 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> synopsis [polymorphic_value.synopsis]</span></a>
        <li><a href="#xz3-class-template-polymorphic_value-constructors-polymorphic_valuector"><span class="secno">4.5.3</span> <span class="content">X.Z.3 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> constructors [polymorphic_value.ctor]</span></a>
        <li><a href="#xz4-class-template-polymorphic_value-destructor-polymorphic_valuedtor"><span class="secno">4.5.4</span> <span class="content">X.Z.4 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> destructor [polymorphic_value.dtor]</span></a>
        <li><a href="#xz5-class-template-polymorphic_value-assignment-polymorphic_valueassignment"><span class="secno">4.5.5</span> <span class="content">X.Z.5 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> assignment [polymorphic_value.assignment]</span></a>
        <li><a href="#xz6-class-template-polymorphic_value-modifiers-polymorphic_valuemodifiers"><span class="secno">4.5.6</span> <span class="content">X.Z.6 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> modifiers [polymorphic_value.modifiers]</span></a>
        <li><a href="#xz7-class-template-polymorphic_value-observers-polymorphic_valueobservers"><span class="secno">4.5.7</span> <span class="content">X.Z.7 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> observers [polymorphic_value.observers]</span></a>
        <li><a href="#xz8-class-template-polymorphic_value-creation-polymorphic_valuecreation"><span class="secno">4.5.8</span> <span class="content">X.Z.8 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> creation [polymorphic_value.creation]</span></a>
        <li><a href="#xz9-class-template-polymorphic_value-specialized-algorithms-polymorphic_valuespec"><span class="secno">4.5.9</span> <span class="content">X.Z.9 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> specialized algorithms [polymorphic_value.spec]</span></a>
       </ol>
     </ol>
    <li>
     <a href="#acknowledgements"><span class="secno">5</span> <span class="content">Acknowledgements</span></a>
     <ol class="toc">
      <li><a href="#references"><span class="secno">5.1</span> <span class="content">References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="change-history"><span class="secno">1. </span><span class="content">Change history</span><a class="self-link" href="#change-history"></a></h2>
   <p>Changes in P0201R6</p>
   <ul>
    <li data-md>
     <p>Further clarifications to formal wording.</p>
    <li data-md>
     <p>Allocator support.</p>
    <li data-md>
     <p>Remove note suggesting that a small object optimisation is allowed.</p>
    <li data-md>
     <p><code class="highlight"><c- k>constexpr</c-></code> support.</p>
   </ul>
   <p>Changes in P0201R5</p>
   <ul>
    <li data-md>
     <p>Make constructor of <code class="highlight"><c- n>default_copy</c-></code> <code class="highlight"><c- k>noexcept</c-></code> and <code class="highlight"><c- k>constexpr</c-></code>.</p>
    <li data-md>
     <p>Clarifications to formal wording.</p>
   </ul>
   <p>Changes in P0201R4</p>
   <ul>
    <li data-md>
     <p>Clarify authors' agreement with LEWG design changes.</p>
    <li data-md>
     <p>Add wording to clarify meaning of custom copier and deleter.</p>
    <li data-md>
     <p>Make constructors explicit and remove converting assignment.</p>
    <li data-md>
     <p>Add a second template parameter to <code class="highlight"><c- n>make_polymorphic_value</c-></code> to facilitate
  construction of objects of derived classes.</p>
   </ul>
   <p>Changes in P0201R3</p>
   <ul>
    <li data-md>
     <p>Add rationale for absence of allocator support.</p>
   </ul>
   <p>Changes in P0201R2</p>
   <ul>
    <li data-md>
     <p>Change name to <code class="highlight"><c- n>polymorphic_value</c-></code>.</p>
    <li data-md>
     <p>Remove <code class="highlight"><c- k>operator</c-> <c- o>&lt;&lt;</c-></code>.</p>
    <li data-md>
     <p>Add construction and assignment from values.</p>
    <li data-md>
     <p>Use <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>default_delete</c-></code>.</p>
    <li data-md>
     <p>Rename <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>default_copier</c-></code> to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>default_copy</c-></code>.</p>
    <li data-md>
     <p>Add notes on empty state and pointer constructor.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> exception when static and dynamic
  type of pointee mismatch and no custom copier or deleter are supplied.</p>
    <li data-md>
     <p>Add clarifying note to say that a small object optimisation is allowed.</p>
   </ul>
   <p>Changes in P0201R1</p>
   <ul>
    <li data-md>
     <p>Change name to <code class="highlight"><c- n>indirect</c-></code>.</p>
    <li data-md>
     <p>Remove <code class="highlight"><c- k>static_cast</c-></code>, <code class="highlight"><c- k>dynamic_cast</c-></code> and <code class="highlight"><c- k>const_cast</c-></code> as <code class="highlight"><c- n>polymorphic_value</c-></code> is
  modelled on a value not a pointer.</p>
    <li data-md>
     <p>Add <code class="highlight"><c- k>const</c-></code> accessors which return <code class="highlight"><c- k>const</c-></code> references/pointers.</p>
    <li data-md>
     <p>Remove pointer-accessor <code class="highlight"><c- n>get</c-></code>.</p>
    <li data-md>
     <p>Remove specialization of <code class="highlight"><c- n>propagate_const</c-></code>.</p>
    <li data-md>
     <p>Amended authorship and acknowledgements.</p>
    <li data-md>
     <p>Added support for custom copiers and custom deleters.</p>
    <li data-md>
     <p>Removed hash and comparison operators.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="tldr"><span class="secno">2. </span><span class="content">TL;DR</span><a class="self-link" href="#tldr"></a></h2>
   <p>Add a class template, <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>, to the standard library to support
polymorphic objects with value-like semantics.</p>
   <h2 class="heading settled" data-level="3" id="introduction"><span class="secno">3. </span><span class="content">Introduction</span><a class="self-link" href="#introduction"></a></h2>
   <p>The class template, <code class="highlight"><c- n>polymorphic_value</c-></code>, confers value-like semantics on a
free-store allocated object.  A <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> may hold an object of a
class publicly derived from T, and copying the <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> will copy
the object of the derived type.</p>
   <h3 class="heading settled" data-level="3.1" id="motivation-composite-objects"><span class="secno">3.1. </span><span class="content">Motivation: Composite objects</span><a class="self-link" href="#motivation-composite-objects"></a></h3>
   <p>Use of components in the design of object-oriented class hierarchies can aid
modular design as components can be potentially re-used as building-blocks for
other composite classes.</p>
   <p>We can write a simple composite object formed from two components as follows:</p>
<pre class="language-cpp highlight"><c- c1>// Simple composite</c->
<c- k>class</c-> <c- nc>CompositeObject_1</c-> <c- p>{</c->
  <c- n>Component1</c-> <c- n>c1_</c-><c- p>;</c->
  <c- n>Component2</c-> <c- n>c2_</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
  <c- n>CompositeObject_1</c-><c- p>(</c-><c- k>const</c-> <c- n>Component1</c-><c- o>&amp;</c-> <c- n>c1</c-><c- p>,</c->
                    <c- k>const</c-> <c- n>Component2</c-><c- o>&amp;</c-> <c- n>c2</c-><c- p>)</c-> <c- o>:</c->
                    <c- n>c1_</c-><c- p>(</c-><c- n>c1</c-><c- p>),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>c2</c-><c- p>)</c-> <c- p>{}</c->

  <c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-> <c- n>c1_</c-><c- p>.</c-><c- n>foo</c-><c- p>();</c-> <c- p>}</c->
  <c- b>void</c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c-> <c- n>c2_</c-><c- p>.</c-><c- n>bar</c-><c- p>();</c-> <c- p>}</c->
<c- p>};</c->
</pre>
   <p>The composite object can be made more flexible by storing pointers to objects
allowing it to take derived components in its constructor.  (We store pointers
to the components rather than references so that we can take ownership of
them).</p>
<pre class="language-cpp highlight"><c- c1>// Non-copyable composite with polymorphic components (BAD)</c->
<c- k>class</c-> <c- nc>CompositeObject_2</c-> <c- p>{</c->
  <c- n>IComponent1</c-><c- o>*</c-> <c- n>c1_</c-><c- p>;</c->
  <c- n>IComponent2</c-><c- o>*</c-> <c- n>c2_</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
  <c- n>CompositeObject_2</c-><c- p>(</c-><c- n>IComponent1</c-><c- o>*</c-> <c- n>c1</c-><c- p>,</c->
                    <c- n>IComponent2</c-><c- o>*</c-> <c- n>c2</c-><c- p>)</c-> <c- o>:</c->
                    <c- n>c1_</c-><c- p>(</c-><c- n>c1</c-><c- p>),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>c2</c-><c- p>)</c-> <c- p>{}</c->

  <c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-> <c- n>c1_</c-><c- o>-></c-><c- n>foo</c-><c- p>();</c-> <c- p>}</c->
  <c- b>void</c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c-> <c- n>c2_</c-><c- o>-></c-><c- n>bar</c-><c- p>();</c-> <c- p>}</c->

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

  <c- n>CompositeObject_2</c-><c- p>(</c-><c- n>CompositeObject_2</c-><c- o>&amp;&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- o>:</c-> <c- n>c1_</c-><c- p>(</c-><c- n>o</c-><c- p>.</c-><c- n>c1_</c-><c- p>),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>o</c-><c- p>.</c-><c- n>c2_</c-><c- p>)</c-> <c- p>{</c->
    <c- n>o</c-><c- p>.</c-><c- n>c1_</c-> <c- o>=</c-> <c- k>nullptr</c-><c- p>;</c->
    <c- n>o</c-><c- p>.</c-><c- n>c2_</c-> <c- o>=</c-> <c- k>nullptr</c-><c- p>;</c->
  <c- p>}</c->

  <c- n>CompositeObject_2</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>CompositeObject_2</c-><c- o>&amp;&amp;</c-> <c- n>o</c-><c- p>)</c-> <c- p>{</c->
    <c- k>delete</c-> <c- n>c1_</c-><c- p>;</c->
    <c- k>delete</c-> <c- n>c2_</c-><c- p>;</c->
    <c- n>c1_</c-> <c- o>=</c-> <c- n>o</c-><c- p>.</c-><c- n>c1_</c-><c- p>;</c->
    <c- n>c2_</c-> <c- o>=</c-> <c- n>o</c-><c- p>.</c-><c- n>c2_</c-><c- p>;</c->
    <c- n>o</c-><c- p>.</c-><c- n>c1_</c-> <c- o>=</c-> <c- k>nullptr</c-><c- p>;</c->
    <c- n>o</c-><c- p>.</c-><c- n>c2_</c-> <c- o>=</c-> <c- k>nullptr</c-><c- p>;</c->
  <c- p>}</c->

  <c- o>~</c-><c- n>CompositeObject_2</c-><c- p>()</c->
  <c- p>{</c->
    <c- k>delete</c-> <c- n>c1_</c-><c- p>;</c->
    <c- k>delete</c-> <c- n>c2_</c-><c- p>;</c->
  <c- p>}</c->
<c- p>};</c->
</pre>
   <p><code class="highlight"><c- n>CompositeObject_2</c-></code>'s constructor API is unclear without knowing that the class
takes ownership of the objects. We are forced to explicitly suppress the
compiler-generated copy constructor and copy assignment operator to avoid
double-deletion of the components <code class="highlight"><c- n>c1_</c-></code> and <code class="highlight"><c- n>c2_</c-></code>. We also need to write a move
constructor and move assignment operator.</p>
   <p>Using <code class="highlight"><c- n>unique_ptr</c-></code> makes ownership clear and saves us writing or deleting
compiler generated functions:</p>
<pre class="language-cpp highlight"><c- c1>// Non-copyable composite with polymorphic components</c->
<c- k>class</c-> <c- nc>CompositeObject_3</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>IComponent1</c-><c- o>></c-> <c- n>c1_</c-><c- p>;</c->
  <c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>IComponent2</c-><c- o>></c-> <c- n>c2_</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
  <c- n>CompositeObject_3</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>IComponent1</c-><c- o>></c-> <c- n>c1</c-><c- p>,</c->
                    <c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>&lt;</c-><c- n>IComponent2</c-><c- o>></c-> <c- n>c2</c-><c- p>)</c-> <c- o>:</c->
                    <c- n>c1_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c1</c-><c- p>)),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c2</c-><c- p>))</c-> <c- p>{}</c->

  <c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-> <c- n>c1_</c-><c- o>-></c-><c- n>foo</c-><c- p>();</c-> <c- p>}</c->
  <c- b>void</c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c-> <c- n>c2_</c-><c- o>-></c-><c- n>bar</c-><c- p>();</c-> <c- p>}</c->
<c- p>};</c->
</pre>
   <p>The design of <code class="highlight"><c- n>CompositeObject_3</c-></code> is good unless we want to copy the object.</p>
   <p>We can avoid having to define our own copy constructor by using shared
pointers.  As <code class="highlight"><c- n>shared</c-><c- o>-</c-><c- n>ptr</c-></code>'s copy constructor is shallow, we need to modify the
component pointers to be pointers-to <code class="highlight"><c- k>const</c-></code> to avoid introducing shared mutable
state [S.Parent].</p>
<pre class="language-cpp highlight"><c- c1>// Copyable composite with immutable polymorphic components class</c->
<c- k>class</c-> <c- nc>CompositeObject_4</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>IComponent1</c-><c- o>></c-> <c- n>c1_</c-><c- p>;</c->
  <c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>IComponent2</c-><c- o>></c-> <c- n>c2_</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
  <c- n>CompositeObject_4</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>IComponent1</c-><c- o>></c-> <c- n>c1</c-><c- p>,</c->
                    <c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-><c- o>&lt;</c-><c- k>const</c-> <c- n>IComponent2</c-><c- o>></c-> <c- n>c2</c-><c- p>)</c-> <c- o>:</c->
                    <c- n>c1_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c1</c-><c- p>)),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c2</c-><c- p>))</c-> <c- p>{}</c->

  <c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-> <c- n>c1_</c-><c- o>-></c-><c- n>foo</c-><c- p>();</c-> <c- p>}</c->
  <c- b>void</c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c-> <c- n>c2_</c-><c- o>-></c-><c- n>bar</c-><c- p>();</c-> <c- p>}</c->
<c- p>};</c->
</pre>
   <p><code class="highlight"><c- n>CompositeObject_4</c-></code> has polymorphism and compiler-generated destructor, copy,
move and assignment operators. As long as the components are not mutated, this
design is good. If non-const functions of components are used then this won’t
compile.</p>
   <p>Using <code class="highlight"><c- n>polymorphic_value</c-></code> a copyable composite object with polymorphic
components can be written as:</p>
<pre class="language-cpp highlight"><c- c1>// Copyable composite with mutable polymorphic components</c->
<c- k>class</c-> <c- nc>CompositeObject_5</c-> <c- p>{</c->
  <c- n>std</c-><c- o>::</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>IComponent1</c-><c- o>></c-> <c- n>c1_</c-><c- p>;</c->
  <c- n>std</c-><c- o>::</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>IComponent2</c-><c- o>></c-> <c- n>c2_</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
  <c- n>CompositeObject_5</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>IComponent1</c-><c- o>></c-> <c- n>c1</c-><c- p>,</c->
                    <c- n>std</c-><c- o>::</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>IComponent2</c-><c- o>></c-> <c- n>c2</c-><c- p>)</c-> <c- o>:</c->
                    <c- n>c1_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c1</c-><c- p>)),</c-> <c- n>c2_</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c2</c-><c- p>))</c-> <c- p>{}</c->

  <c- b>void</c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-> <c- n>c1_</c-><c- o>-></c-><c- n>foo</c-><c- p>();</c-> <c- p>}</c->
  <c- b>void</c-> <c- n>bar</c-><c- p>()</c-> <c- p>{</c-> <c- n>c2_</c-><c- o>-></c-><c- n>bar</c-><c- p>();</c-> <c- p>}</c->
<c- p>};</c->
</pre>
   <p>The component <code class="highlight"><c- n>c1_</c-></code> can be constructed from an instance of any class that
inherits from <code class="highlight"><c- n>IComponent1</c-></code>.  Similarly, <code class="highlight"><c- n>c2_</c-></code> can be constructed from an
instance of any class that inherits from <code class="highlight"><c- n>IComponent2</c-></code>.</p>
   <p><code class="highlight"><c- n>CompositeObject_5</c-></code> has a compiler-generated destructor, copy constructor, move
constructor, assignment operator and move assignment operator. All of these
compiler-generated functions will behave correctly.</p>
   <h3 class="heading settled" data-level="3.2" id="deep-copies"><span class="secno">3.2. </span><span class="content">Deep copies</span><a class="self-link" href="#deep-copies"></a></h3>
   <p>To allow correct copying of polymorphic objects, <code class="highlight"><c- n>polymorphic_value</c-></code> uses the
copy constructor of the owned derived-type object when copying a base type <code class="highlight"><c- n>polymorphic_value</c-></code>.  Similarly, to allow correct destruction of polymorphic
component objects, <code class="highlight"><c- n>polymorphic_value</c-></code> uses the destructor of the owned
derived-type object in the destructor of a base type <code class="highlight"><c- n>polymorphic_value</c-></code>.</p>
   <p>The requirements of deep-copying can be illustrated by some simple test code:</p>
<pre class="language-cpp highlight"><c- c1>// GIVEN base and derived classes.</c->
<c- k>class</c-> <c- nc>Base</c-> <c- p>{</c-> <c- k>virtual</c-> <c- b>void</c-> <c- nf>foo</c-><c- p>()</c-> <c- k>const</c-> <c- o>=</c-> <c- mi>0</c-><c- p>;</c-> <c- p>};</c->
<c- k>class</c-> <c- nc>Derived</c-> <c- o>:</c-> <c- k>public</c-> <c- n>Base</c-> <c- p>{</c-> <c- b>void</c-> <c- nf>foo</c-><c- p>()</c-> <c- k>const</c-> <c- k>override</c-> <c- p>{}</c-> <c- p>};</c->

<c- c1>// WHEN a polymorphic_value to base is formed from a derived object</c->
<c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>poly</c-><c- p>(</c-><c- n>Derived</c-><c- p>());</c->
<c- c1>// AND the polymorphic_value to base is copied.</c->
<c- k>auto</c-> <c- n>poly_copy</c-> <c- o>=</c-> <c- n>poly</c-><c- p>;</c->

<c- c1>// THEN the copy owns a distinct object</c->
<c- n>assert</c-><c- p>(</c-><c- o>&amp;*</c-><c- n>poly</c-> <c- o>!=</c-> <c- o>&amp;*</c-><c- n>poly_copy</c-><c- p>);</c->
<c- c1>// AND the copy owns a derived type.</c->
<c- n>assert</c-><c- p>(</c-><c- k>dynamic_cast</c-><c- o>&lt;</c-><c- n>Derived</c-><c- o>*></c-><c- p>(</c-><c- o>*&amp;</c-><c- n>poly_copy</c-><c- p>));</c->
</pre>
   <p>Note that while deep-destruction of a derived class object from a base class
pointer can be performed with a virtual destructor, the same is not true for
deep-copying. <code class="highlight"><c- n>C</c-><c- o>++</c-></code> has no concept of a virtual copy constructor and we are not
proposing its addition.  The class template <code class="highlight"><c- n>shared_ptr</c-></code> already implements
deep-destruction without needing virtual destructors; deep-destruction and
deep-copying can be implemented using type-erasure [Impl].</p>
   <h3 class="heading settled" data-level="3.3" id="pointer-constructor"><span class="secno">3.3. </span><span class="content">Pointer constructor</span><a class="self-link" href="#pointer-constructor"></a></h3>
   <p><code class="highlight"><c- n>polymorphic_value</c-></code> can be constructed from a pointer and optionally a copier
and/or deleter. The <code class="highlight"><c- n>polymorphic_value</c-></code> constructed in this manner takes
ownership of the pointer. This constructor is potentially dangerous as a
mismatch in the dynamic and static type of the pointer will result in
incorrectly synthesized copiers and deleters, potentially resulting in slicing
when copying and incomplete deletion during destruction.</p>
<pre class="language-cpp highlight"><c- k>class</c-> <c- nc>Base</c-> <c- p>{</c-> <c- d>/* functions and members */</c-> <c- p>};</c->
<c- k>class</c-> <c- nc>Derived</c-> <c- o>:</c-> <c- k>public</c-> <c- n>Base</c-> <c- p>{</c-> <c- d>/* functions and members */</c-> <c- p>};</c->

<c- n>Derived</c-><c- o>*</c-> <c- n>d</c-> <c- o>=</c-> <c- k>new</c-> <c- n>Derived</c-><c- p>();</c->
<c- n>Base</c-><c- o>*</c-> <c- n>p</c-> <c- o>=</c-> <c- n>d</c-><c- p>;</c-> <c- c1>// static type and dynamic type differ</c->
<c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>poly</c-><c- p>(</c-><c- n>p</c-><c- p>);</c->

<c- c1>// This copy will have been made using Base’s copy constructor.</c->
<c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>poly_copy</c-> <c- o>=</c-> <c- n>poly</c-><c- p>;</c->

<c- c1>// Destruction of poly and poly_copy uses Base’s destructor.</c->
</pre>
   <p>While this is potentially error prone, we have elected to trust users with the
tools they are given. <code class="highlight"><c- n>shared_ptr</c-></code> and <code class="highlight"><c- n>unique_ptr</c-></code> have similar constructors
and issues.  There are more constructors for <code class="highlight"><c- n>polymorphic_value</c-></code> of a less
expert-friendly nature that do not present such dangers including a factory
function <code class="highlight"><c- n>make_polymorphic_value</c-></code>.</p>
   <p>Static analysis tools can be written to find cases where static and dynamic
types for pointers passed in to <code class="highlight"><c- n>polymorphic_value</c-></code> constructors are not
provably identical.</p>
   <p>If the user has not supplied a custom copier or deleter, an exception <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> is thrown from the pointer-constructor if
the dynamic and static types of the pointer argument do not agree.
In cases where the user has supplied a custom copier and deleter it is assumed
that they will do so to avoid slicing and incomplete destruction: a class
heirarchy with a custom <code class="highlight"><c- n>Clone</c-></code> function and virtual destructor would make use
of <code class="highlight"><c- n>Clone</c-></code> in a user-supplied copier.</p>
   <h3 class="heading settled" data-level="3.4" id="empty-state"><span class="secno">3.4. </span><span class="content">Empty state</span><a class="self-link" href="#empty-state"></a></h3>
   <p><code class="highlight"><c- n>polymorphic_value</c-></code> presents an empty state as it is desirable for it to be
cheaply constructed and then later assigned.  In addition, it may not be
possible to construct the <code class="highlight"><c- n>T</c-></code> of a <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> if it is an abstract
class (a common intended use pattern).  While permitting an empty state will
necessitate occasional checks for <code class="highlight"><c- n>null</c-></code>, <code class="highlight"><c- n>polymorphic_value</c-></code> is intended to
replace the uses of pointers or smart pointers where such checks are also
necessary. The benefits of default constructability (use in vectors and maps)
outweigh the costs of a possible empty state.</p>
   <p>A nullable <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> could be mimicked with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c-></code> but this is verbose and would require partial template specialization of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> to avoid the overhead that would be incurred by a nullable <code class="highlight"><c- n>polymorphic_value</c-></code>.  But perhaps
the most unfortunate side effect of this approach is that to access the underlying <code class="highlight"><c- n>T</c-></code> the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> must be dereferenced to get to the <code class="highlight"><c- n>polymorphic_value</c-></code>, which then requires
a second dereference to get to the underlying <code class="highlight"><c- n>T</c-></code>.  This access pattern is undesirable.</p>
   <h3 class="heading settled" data-level="3.5" id="lack-of-hashing-and-comparisons"><span class="secno">3.5. </span><span class="content">Lack of hashing and comparisons</span><a class="self-link" href="#lack-of-hashing-and-comparisons"></a></h3>
   <p>For a given user-defined type, <code class="highlight"><c- n>T</c-></code>, there are multiple strategies to make <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> hashable and comparable.  Without requiring additional
named member functions on the type, <code class="highlight"><c- n>T</c-></code>, or mandating that <code class="highlight"><c- n>T</c-></code> has virtual
functions and RTTI, the authors do not see how <code class="highlight"><c- n>polymorphic_value</c-></code> can
generically support hashing or comparisons. Incurring a cost for functionality
that is not required goes against the 'pay for what you use' philosophy of <code class="highlight"><c- n>C</c-><c- o>++</c-></code>.</p>
   <p>For a given user-defined type <code class="highlight"><c- n>T</c-></code> the user is free to specialize <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>hash</c-></code> and implement comparison operators for <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>.</p>
   <h3 class="heading settled" data-level="3.6" id="custom-copiers-and-deleters"><span class="secno">3.6. </span><span class="content">Custom copiers and deleters</span><a class="self-link" href="#custom-copiers-and-deleters"></a></h3>
   <p>The resource management performed by <code class="highlight"><c- n>polymorphic_value</c-></code> - copying and
destruction of the managed object - can be customized by supplying a _copier_
and _deleter_.  If no copier or deleter is supplied then a default copier or
deleter may be used.</p>
   <p>A custom copier and deleter are _not_ required, if no custom copier and deleter
are provided then the copy constructor and destructor of the managed object
will be used.</p>
   <p>The default deleter is already defined by the standard library and used by <code class="highlight"><c- n>unique_ptr</c-></code>.</p>
   <p>We define the default copier in technical specifications below.</p>
   <h3 class="heading settled" data-level="3.7" id="allocator-support"><span class="secno">3.7. </span><span class="content">Allocator Support</span><a class="self-link" href="#allocator-support"></a></h3>
   <p>Previous revisions of this paper did not support allocators.  However, support
is desirable as it offers an opportunity to mitigate the cost of allocations.
There is existing precedence for allocator support of types in the memory
management library; <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code> supports allocators via <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>allocate_shared</c-></code>, [M. Knejp] suggested the introduction of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>allocate_unique</c-></code> to support allocator use with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-></code>.</p>
   <p><code class="highlight"><c- n>polymorphic_value</c-></code> internally uses type-erased to create an internal control
block object responsible for cloning itself and the actual type derived from <code class="highlight"><c- n>T</c-></code>.
It is possible to provide different types of control blocks to support allocation
from multiple sources [Impl].</p>
   <p>Memory management for <code class="highlight"><c- n>polymorphic_value</c-></code> can be fully controlled via the <code class="highlight"><c- n>allocate_polymorphic_value</c-></code> function which allows passing in an allocator
to control the source of memory.  Custom copier and deleter then use the
allocator for allocations and deallocations.</p>
   <h3 class="heading settled" data-level="3.8" id="design-changes-from-cloned_ptr"><span class="secno">3.8. </span><span class="content">Design changes from <code class="highlight"><c- n>cloned_ptr</c-></code></span><a class="self-link" href="#design-changes-from-cloned_ptr"></a></h3>
   <p>The design of <code class="highlight"><c- n>polymorphic_value</c-></code> is based upon <code class="highlight"><c- n>cloned_ptr</c-></code> (from an early
revision of this paper) and modified following advice from LEWG. The authors
(who unreservedly agree with the design direction suggested by LEWG) would
like to make explicit the cost of these design changes.</p>
   <p><code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> has value-like semantics: copies are deep and <code class="highlight"><c- k>const</c-></code> is
propagated to the owned object. The first revision of this paper presented <code class="highlight"><c- n>cloned_ptr</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> which had mixed pointer/value semantics: copies are deep but <code class="highlight"><c- k>const</c-></code> is not propagated to the owned object. <code class="highlight"><c- n>polymorphic_value</c-></code> can be built
from <code class="highlight"><c- n>cloned_ptr</c-></code> and <code class="highlight"><c- n>propagate_const</c-></code> but there is no way to remove <code class="highlight"><c- k>const</c-></code> propagation from <code class="highlight"><c- n>polymorphic_value</c-></code>.</p>
   <p>As <code class="highlight"><c- n>polymorphic_value</c-></code> is a value, <code class="highlight"><c- n>dynamic_pointer_cast</c-></code>, <code class="highlight"><c- n>static_pointer_cast</c-></code> and <code class="highlight"><c- n>const_pointer_cast</c-></code> are not provided.  If a <code class="highlight"><c- n>polymorphic_value</c-></code> is constructed with a custom copier or deleter, then there
is no way for a user to implement cast operations like those that are provided
by the standard for <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>shared_ptr</c-></code>.</p>
   <h3 class="heading settled" data-level="3.9" id="no-implicit-conversions"><span class="secno">3.9. </span><span class="content">No implicit conversions</span><a class="self-link" href="#no-implicit-conversions"></a></h3>
   <p>Following design feedback, <code class="highlight"><c- n>polymorphic_value</c-></code>'s constructors have been made
explicit so that surprising implicit conversions cannot take place. Any
conversion to a <code class="highlight"><c- n>polymorphic_value</c-></code> must be explicitly requested by user-code.</p>
   <p>The converting assignment operators that were present in earlier drafts have
also been removed.</p>
   <p>For a base class, <code class="highlight"><c- n>BaseClass</c-></code>, and derived class, <code class="highlight"><c- n>DerivedClass</c-></code>, the
converting assignment</p>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>DerivedClass</c-><c- o>></c-> <c- n>derived</c-><c- p>;</c->
<c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>base</c-> <c- o>=</c-> <c- n>derived</c-><c- p>;</c->
</pre>
   <p>is no longer valid, the conversion must be made explicit:</p>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>DerivedClass</c-><c- o>></c-> <c- n>derived</c-><c- p>;</c->
<c- k>auto</c-> <c- n>base</c-> <c- o>=</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-><c- p>(</c-><c- n>derived</c-><c- p>);</c->
</pre>
   <p>The removal of converting assigments makes <code class="highlight"><c- n>make_polymorphic_value</c-></code> slightly
more verbose to use:</p>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>base</c-> <c- o>=</c-> <c- n>make_polymorphic_value</c-><c- o>&lt;</c-><c- n>DerivedClass</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>);</c->
</pre>
   <p>is not longer valid and must be written as</p>
<pre class="language-cpp highlight"><c- k>auto</c-> <c- n>base</c-> <c- o>=</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-><c- p>(</c-><c- n>make_polymorphic_value</c-><c- o>&lt;</c-><c- n>DerivedClass</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>));</c->
</pre>
   <p>This is somewhat cumbersome so <code class="highlight"><c- n>make_polymorphic_value</c-></code> has been modified to
take an optional extra template argument allowing users to write</p>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- o>></c-> <c- n>base</c-> <c- o>=</c-> <c- n>make_polymorphic_value</c-><c- o>&lt;</c-><c- n>Base</c-><c- p>,</c-> <c- n>DerivedClass</c-><c- o>></c-><c- p>(</c-><c- n>args</c-><c- p>);</c->
</pre>
   <p>The change from implicit to explicit construction is deliberately conservative.
One can change explicit constructors into implicit constructors without
breaking code (other than SFINAE checks), the reverse is not true. Similarly,
converting assignments could be added non-disruptively but not so readily
removed.</p>
   <h3 class="heading settled" data-level="3.10" id="impact-on-the-standard"><span class="secno">3.10. </span><span class="content">Impact on the standard</span><a class="self-link" href="#impact-on-the-standard"></a></h3>
   <p>This proposal is a pure library extension. It requires additions to be made to
the standard library header <code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code>.</p>
   <h2 class="heading settled" data-level="4" id="technical-specifications"><span class="secno">4. </span><span class="content">Technical specifications</span><a class="self-link" href="#technical-specifications"></a></h2>
   <p>Add the following entry to [tab:support.ft]</p>
   <p><var>Macro Name</var>Value|Header(s)|
|:-:|:-:|:-:|
|<code class="highlight"><c- n>__cpp_lib_polymorphic_value</c-></code>|<code class="highlight"><c- n>xxxxxxL</c-></code>|<code class="highlight"><c- o>&lt;</c-><c- n>memory</c-><c- o>></c-></code>|</p>
   <h3 class="heading settled" data-level="4.1" id="additions-in-memorysyn-2022"><span class="secno">4.1. </span><span class="content">Additions in [memory.syn] 20.2.2:</span><a class="self-link" href="#additions-in-memorysyn-2022"></a></h3>
<pre class="highlight"><c- c1>// [indirect.value], class template indirect_value</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- nc>default_copy</c-><c- p>;</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- nc>copier_traits</c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>class</c-> <c- nc>polymorphic_value</c-><c- p>;</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- p>...</c-><c- n>Ts</c-><c- o>></c-> 
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>make_polymorphic_value</c-><c- p>(</c-><c- n>Ts</c-><c- o>&amp;&amp;</c-> <c- p>...</c-><c- n>ts</c-><c- p>);</c-> 

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>allocate_polymorphic_value</c-><c- p>(</c-><c- n>A</c-><c- o>&amp;</c-> <c- n>a</c-><c- p>,</c-> <c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>ts</c-><c- p>);</c-> 

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>constexpr</c-> <c- b>void</c-> <c- n>swap</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>&amp;</c-> <c- n>p</c-><c- p>,</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="4.2" id="xw-class-template-copier_traits-copiertraits"><span class="secno">4.2. </span><span class="content">X.W Class template <code class="highlight"><c- n>copier_traits</c-></code> [copier.traits]</span><a class="self-link" href="#xw-class-template-copier_traits-copiertraits"></a></h3>
<pre class="highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->
  <c- k>struct</c-> <c- nc>copier_traits</c-> <c- p>{</c->
    <c- k>using</c-> <c- n>deleter_type</c-> <c- o>=</c-> <c- o>*</c-><c- n>see</c-> <c- n>below</c-><c- o>*</c-><c- p>;</c->
  <c- p>};</c->
<c- p>}</c->
</pre>
   <code class="highlight"><c- k>using</c-> <c- n>deleter_type</c-> <c- o>=</c-> <em><c- n>see</c-> <c- n>below</c-></em><c- p>;</c-></code> 
   <ul>
    <li data-md>
     <p>Type: <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>deleter_type</c-></code> if the <em>qualified-id</em> <code class="highlight"><c- n>T</c-><c- o>::</c-><c- n>deleter_type</c-></code> is valid and denotes a type;
otherwise, <code class="highlight"><c- b>void</c-> <c- p>(</c-><c- o>*</c-><c- p>)(</c-><c- n>U</c-><c- o>*</c-><c- p>)</c-></code> if <code class="highlight"><c- n>T</c-></code> is of the form <code class="highlight"><c- n>U</c-><c- o>*</c-> <c- p>(</c-><c- o>*</c-><c- p>)(</c-><c- n>V</c-><c- p>)</c-></code> for types <code class="highlight"><c- n>U</c-></code> and <code class="highlight"><c- n>V</c-></code>;
otherwise, there is no member <code class="highlight"><c- n>deleter_type</c-></code>.</p>
   </ul>
   <h3 class="heading settled" data-level="4.3" id="xx-class-template-default_copy-defaultcopy"><span class="secno">4.3. </span><span class="content">X.X Class template <code class="highlight"><c- n>default_copy</c-></code> [default.copy]</span><a class="self-link" href="#xx-class-template-default_copy-defaultcopy"></a></h3>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>struct</c-> <c- nc>default_copy</c-> <c- p>{</c->
  <c- k>using</c-> <c- n>deleter_type</c-> <c- o>=</c-> <c- n>default_delete</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-><c- p>;</c->
  <c- k>constexpr</c-> <c- n>default_copy</c-><c- p>()</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
  <c- k>constexpr</c-> <c- n>T</c-><c- o>*</c-> <c- nf>operator</c-><c- p>()(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
<c- p>};</c->

<c- p>}</c-> <c- c1>// namespace std</c->
</pre>
   <p>The class template <code class="highlight"><c- n>default_copy</c-></code> [p1950r1] serves as the default copier for the class
template <code class="highlight"><c- n>polymorphic_value</c-></code>.</p>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- n>T</c-><c- o>*</c-> <c- nf>operator</c-><c- p>()(</c-><c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- n>t</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Effects: Equivalent to: <code class="highlight"><c- k>return</c-> <c- k>new</c-> <c- n>T</c-><c- p>(</c-><c- n>t</c-><c- p>);</c-></code></p>
   </ul>
   <h3 class="heading settled" data-level="4.4" id="xy-class-bad_polymorphic_value_construction-bad_polymorphic_value_construction"><span class="secno">4.4. </span><span class="content">X.Y Class <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> [bad_polymorphic_value_construction]</span><a class="self-link" href="#xy-class-bad_polymorphic_value_construction-bad_polymorphic_value_construction"></a></h3>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
<c- k>class</c-> <c- nc>bad_polymorphic_value_construction</c-> <c- o>:</c-> <c- k>public</c-> <c- n>exception</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- n>bad_polymorphic_value_construction</c-><c- p>()</c-> <c- k>noexcept</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->

    <c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- nf>what</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c->
<c- p>};</c->
<c- p>}</c->
</pre>
   <p>Objects of type <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> are thrown to report
invalid construction of a <code class="highlight"><c- n>polymorphic_value</c-></code>.</p>
<pre class="language-cpp highlight"><c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- nf>what</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-> <c- k>override</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Returns: An implementation-defined NTBS.</p>
   </ul>
   <h3 class="heading settled" data-level="4.5" id="xz-class-template-polymorphic_value-polymorphic_value"><span class="secno">4.5. </span><span class="content">X.Z Class template <code class="highlight"><c- n>polymorphic_value</c-></code> [polymorphic_value]</span><a class="self-link" href="#xz-class-template-polymorphic_value-polymorphic_value"></a></h3>
   <h4 class="heading settled" data-level="4.5.1" id="xz1-class-template-polymorphic_value-general-polymorphic_valuegeneral"><span class="secno">4.5.1. </span><span class="content">X.Z.1 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> general [polymorphic_value.general]</span><a class="self-link" href="#xz1-class-template-polymorphic_value-general-polymorphic_valuegeneral"></a></h4>
   <p>A <code class="highlight"><c- n>polymorphic_value</c-></code> is an object that manages the lifetime of an owned object.
A <code class="highlight"><c- n>polymorphic_value</c-></code> object may own objects of different types at different points in its
lifetime. A <code class="highlight"><c- n>polymorphic_value</c-></code> object is empty if it has no owned object. <code class="highlight"><c- n>polymorphic_value</c-></code> implements value semantics: the owned object (if any) is
copied or destroyed when the <code class="highlight"><c- n>polymorphic_value</c-></code> is copied or destroyed.
Copying and destruction of the owned object can be customized by supplying a
copier and a deleter, respectively.</p>
   <p>The template parameter <code class="highlight"><c- n>T</c-></code> of <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> shall be a non-union class
type; otherwise the program is ill-formed.
The template parameter <code class="highlight"><c- n>T</c-></code> of <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> may be an incomplete type.</p>
   <p>A copier and deleter are said to be _present_ if and only if a <code class="highlight"><c- n>polymorphic_value</c-></code> object is constructed from a non-null pointer, or from a <code class="highlight"><c- n>polymorphic_value</c-></code> object where a copier and a deleter are present.</p>
   <h4 class="heading settled" data-level="4.5.2" id="xz2-class-template-polymorphic_value-synopsis-polymorphic_valuesynopsis"><span class="secno">4.5.2. </span><span class="content">X.Z.2 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> synopsis [polymorphic_value.synopsis]</span><a class="self-link" href="#xz2-class-template-polymorphic_value-synopsis-polymorphic_valuesynopsis"></a></h4>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-> <c- p>{</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-> <c- k>class</c-> <c- nc>polymorphic_value</c-> <c- p>{</c->
 <c- k>public</c-><c- o>:</c->
  <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>T</c-><c- p>;</c->

  <c- c1>// Constructors</c->
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>nullptr_t</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-> <c- n>u</c-><c- p>);</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- p>,</c-> <c- k>class</c-> <c- nc>C</c-><c- o>=</c-><c- n>default_copy</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>,</c->
            <c- k>class</c-> <c- nc>D</c-><c- o>=</c-><c- k>typename</c-> <c- nc>copier_traits</c-><c- o>&lt;</c-><c- n>C</c-><c- o>>::</c-><c- n>deleter_type</c-><c- o>></c->
    <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>U</c-><c- o>*</c-> <c- n>p</c-><c- p>,</c-> <c- n>C</c-> <c- n>c</c-><c- o>=</c-><c- n>C</c-><c- p>(),</c-> <c- n>D</c-> <c- n>d</c-><c- o>=</c-><c- n>D</c-><c- p>());</c->

  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>);</c->
  
  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->
    <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>&amp;</c-> <c- n>p</c-><c- p>);</c->
  
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->
    <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>&amp;&amp;</c-> <c- n>p</c-><c- p>);</c->

  <c- c1>// Destructor</c->
  <c- k>constexpr</c-> <c- o>~</c-><c- n>polymorphic_value</c-><c- p>();</c->

  <c- c1>// Assignment</c->
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>);</c->
  <c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// Modifiers</c->
  <c- k>constexpr</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// Observers</c->
  <c- k>constexpr</c-> <c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>*</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
  <c- k>constexpr</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>*</c-><c- p>();</c->
  <c- k>constexpr</c-> <c- k>const</c-> <c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>-></c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
  <c- k>constexpr</c-> <c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>-></c-><c- p>();</c->
  <c- k>constexpr</c-> <c- k>explicit</c-> <c- k>operator</c-> <c- b>bool</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- c1>// polymorphic_value specialized algorithms</c->
  <c- k>friend</c-> <c- k>constexpr</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>,</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
<c- p>};</c->

<c- c1>// polymorphic_value creation</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-><c- o>=</c-><c- n>T</c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>make_polymorphic_value</c-><c- p>(</c-><c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>ts</c-><c- p>);</c->

<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-> <c- o>=</c-> <c- n>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>allocator</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>allocate_polymorphic_value</c-><c- p>(</c-><c- n>allocator_arg_t</c-><c- p>,</c-> <c- n>A</c-><c- o>&amp;</c-> <c- n>a</c-><c- p>,</c-> <c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>ts</c-><c- p>);</c->

<c- p>}</c-> <c- c1>// end namespace std</c->
</pre>
   <h4 class="heading settled" data-level="4.5.3" id="xz3-class-template-polymorphic_value-constructors-polymorphic_valuector"><span class="secno">4.5.3. </span><span class="content">X.Z.3 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> constructors [polymorphic_value.ctor]</span><a class="self-link" href="#xz3-class-template-polymorphic_value-constructors-polymorphic_valuector"></a></h4>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->
<c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>nullptr_t</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Postconditions: <code class="highlight"><c- o>*</c-><c- k>this</c-></code> is empty.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-> <c- n>u</c-><c- p>);</c->
</pre>
   <p>Let <code class="highlight"><c- n>V</c-></code> be <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code>.</p>
   <ul>
    <li data-md>
     <p>Constraints: <code class="highlight"><c- n>is_convertible_v</c-><c- o>&lt;</c-><c- n>V</c-><c- o>*</c-><c- p>,</c-> <c- n>T</c-><c- o>*></c-></code> is true. <code class="highlight"><c- n>is_constructible_v</c-><c- o>&lt;</c-><c- n>V</c-><c- p>,</c-> <c- n>U</c-><c- o>></c-></code> is true.</p>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- n>V</c-></code> meets the <code class="highlight"><c- n>Cpp17CopyConstructible</c-></code> requirements.</p>
    <li data-md>
     <p>Effects: Constructs a <code class="highlight"><c- n>polymorphic_value</c-></code> which owns an object of type <code class="highlight"><c- n>V</c-></code>,
  direct-non-list-initialized with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>(</c-><c- n>u</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Throws: Any exception thrown by the selected constructor of <code class="highlight"><c- n>V</c-></code> or <code class="highlight"><c- n>bad_alloc</c-></code> if required storage cannot be obtained.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- p>,</c-> <c- k>class</c-> <c- nc>C</c-><c- o>=</c-><c- n>default_copy</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>,</c->
          <c- k>class</c-> <c- nc>D</c-><c- o>=</c-><c- k>typename</c-> <c- nc>copier_traits</c-><c- o>&lt;</c-><c- n>C</c-><c- o>>::</c-><c- n>deleter_type</c-><c- o>></c->
  <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>U</c-><c- o>*</c-> <c- n>p</c-><c- p>,</c-> <c- n>C</c-> <c- n>c</c-><c- o>=</c-><c- n>C</c-><c- p>(),</c-> <c- n>D</c-> <c- n>d</c-><c- o>=</c-><c- n>D</c-><c- p>());</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: <code class="highlight"><c- n>is_convertible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- o>*</c-><c- p>,</c-> <c- n>T</c-><c- o>*></c-></code> is true.</p>
   </ul>
   <p>If the arguments <code class="highlight"><c- n>c</c-></code> and/or <code class="highlight"><c- n>d</c-></code> are not supplied, then <code class="highlight"><c- n>C</c-></code> and/or <code class="highlight"><c- n>D</c-></code> respectively are default constructible types that are not pointer types.</p>
   <ul>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- n>C</c-></code> and <code class="highlight"><c- n>D</c-></code> meet the <code class="highlight"><c- n>Cpp17CopyConstructible</c-></code> and <code class="highlight"><c- n>Cpp17Destructible</c-></code> requirements.</p>
   </ul>
   <p>If <code class="highlight"><c- n>p</c-></code> is non-null then invoking the expression <code class="highlight"><c- n>c</c-><c- p>(</c-><c- o>*</c-><c- n>p</c-><c- p>)</c-></code> returns a
  non-null <code class="highlight"><c- n>U</c-><c- o>*</c-></code> is as if copy constructed from *p. The expression <code class="highlight"><c- n>d</c-><c- p>(</c-><c- n>p</c-><c- p>)</c-></code> is well formed, has well-defined behavior, and does not throw exceptions.
  Where <code class="highlight"><c- n>q</c-><c- o>=</c-><c- n>c</c-><c- p>(</c-><c- o>*</c-><c- n>p</c-><c- p>)</c-></code>, the expression <code class="highlight"><c- n>d</c-><c- p>(</c-><c- n>q</c-><c- p>)</c-></code> is well-defined and does
  not throw exceptions.</p>
   <ul>
    <li data-md>
     <p>Effects: If <code class="highlight"><c- n>p</c-></code> is null, creates an empty object otherwise
  creates an object that owns the object <code class="highlight"><c- o>*</c-><c- n>p</c-></code>,  with a copier of
  type C initialized from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c</c-><c- p>)</c-></code> and a deleter of type D
  initialized from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>d</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Throws: <code class="highlight"><c- n>bad_alloc</c-></code> if required storage cannot be obtained; <code class="highlight"><c- n>bad_polymorphic_value_construction</c-></code> if <code class="highlight"><c- n>is_same_v</c-><c- o>&lt;</c-><c- n>C</c-><c- p>,</c-> <c- n>default_copy</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>></c-></code>, <code class="highlight"><c- n>is_same_v</c-><c- o>&lt;</c-><c- n>D</c-><c- p>,</c-> <c- n>default_delete</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>></c-></code> and <code class="highlight"><c- k>typeid</c-><c- p>(</c-><c- o>*</c-><c- n>p</c-><c- p>)</c-><c- o>!=</c-><c- k>typeid</c-><c- p>(</c-><c- n>U</c-><c- p>)</c-></code> are all <code class="highlight">true</code>.</p>
    <li data-md>
     <p>Postconditions: If <code class="highlight"><c- n>p</c-></code> is null, the empty object created has no copier and no deleter.
  Otherwise the object created owns the object <code class="highlight"><c- o>*</c-><c- n>p</c-></code> and has a copier and a deleter
  present, initialized from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>c</c-><c- p>)</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>d</c-><c- p>)</c-></code> respectively.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-><c- o>></c->
<c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>U</c-><c- o>*</c-> <c- n>u</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator_arg_t</c-><c- p>,</c-> <c- k>const</c-> <c- n>A</c-><c- o>&amp;</c-> <c- n>alloc</c-><c- p>)</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: <code class="highlight"><c- n>is_convertible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- o>*</c-><c- p>,</c-> <c- n>T</c-><c- o>*></c-></code> is true.</p>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- n>A</c-></code> meets the Cpp17Allocator requirements.</p>
    <li data-md>
     <p>Effects: Constructs a polymorphic_value­ that owns the object <a class="property css" data-link-type="property">u</a>.
  Construction shall use a copy of <code class="highlight"><c- n>a</c-></code> to allocate memory for
  internal use.</p>
    <li data-md>
     <p>Throws: <code class="highlight"><c- n>bad_alloc</c-></code> if required storage cannot be obtained;</p>
   </ul>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>pv</c-><c- p>);</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>&amp;</c-> <c- n>pv</c-><c- p>);</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: For the second constructor, <code class="highlight"><c- n>is_convertible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- o>*</c-><c- p>,</c-> <c- n>T</c-><c- o>*></c-></code> is true.</p>
    <li data-md>
     <p>Effects: If <code class="highlight"><c- n>pv</c-></code> is empty, constructs an empty object. Otherwise
  creates an object that owns a copy of the object managed by <code class="highlight"><c- n>pv</c-></code>.
  If a copier and deleter are present in <code class="highlight"><c- n>pv</c-></code> then
  the copy is created by the copier in <code class="highlight"><c- n>pv</c-></code>. Otherwise the copy is created by copy
  construction of the owned object.  If a copier and deleter are present
  in <code class="highlight"><c- n>pv</c-></code> then the copier and deleter of the object constructed
  are copied from those in <code class="highlight"><c- n>pv</c-></code> so that they are present and of type <code class="highlight"><c- n>C</c-></code> and <code class="highlight"><c- n>D</c-></code> respectively.</p>
    <li data-md>
     <p>Postconditions: <code class="highlight"><c- b>bool</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- o>==</c-> <c- b>bool</c-><c- p>(</c-><c- n>pv</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Throws: Any exception thrown by invocation of the copier, copying the
  copier and deleter, or <code class="highlight"><c- n>bad_alloc</c-></code> if required storage cannot be obtained.</p>
   </ul>
<pre class="language-cpp highlight"><c- n>polymorphic_value</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;&amp;</c-> <c- n>pv</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
<c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>explicit</c-> <c- n>polymorphic_value</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>U</c-><c- o>>&amp;&amp;</c-> <c- n>pv</c-><c- p>);</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: For the second constructor, <code class="highlight"><c- n>is_convertible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- o>*</c-><c- p>,</c-> <c- n>T</c-><c- o>*></c-></code> is true.</p>
    <li data-md>
     <p>Effects: If <code class="highlight"><c- n>pv</c-></code> is empty, constructs an empty object. Otherwise the object
  owned by <code class="highlight"><c- n>pv</c-></code> is transferred to the constructed object. If a copier and deleter
  are present in <code class="highlight"><c- n>pv</c-></code> then the copier and deleter are transferred to the
  constructed object so that they are present and of type <code class="highlight"><c- n>C</c-></code> and <code class="highlight"><c- n>D</c-></code> respectively.</p>
    <li data-md>
     <p>Postconditions: <code class="highlight"><c- o>*</c-><c- k>this</c-></code> owns the object previously owned by <code class="highlight"><c- n>pv</c-></code> (if any). <code class="highlight"><c- n>pv</c-></code> is empty.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.4" id="xz4-class-template-polymorphic_value-destructor-polymorphic_valuedtor"><span class="secno">4.5.4. </span><span class="content">X.Z.4 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> destructor [polymorphic_value.dtor]</span><a class="self-link" href="#xz4-class-template-polymorphic_value-destructor-polymorphic_valuedtor"></a></h4>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- o>~</c-><c- n>polymorphic_value</c-><c- p>();</c->
</pre>
   <ul>
    <li data-md>
     <p>Effects: If a copier <code class="highlight"><c- n>c</c-></code> and a deleter <code class="highlight"><c- n>d</c-></code> are present,
evaluates <code class="highlight"><c- n>d</c-><c- p>(</c-><c- k>operator</c-><c- o>-></c-><c- p>())</c-></code> and destroys <code class="highlight"><c- n>c</c-></code> and <code class="highlight"><c- n>d</c-></code>.
Otherwise destroys the owned object (if any) and frees its storage.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.5" id="xz5-class-template-polymorphic_value-assignment-polymorphic_valueassignment"><span class="secno">4.5.5. </span><span class="content">X.Z.5 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> assignment [polymorphic_value.assignment]</span><a class="self-link" href="#xz5-class-template-polymorphic_value-assignment-polymorphic_valueassignment"></a></h4>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- k>const</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>pv</c-><c- p>);</c->
</pre>
   <ul>
    <li data-md>
     <p>Effects: Equivalent to <code class="highlight"><c- n>polymorphic_value</c-><c- p>(</c-><c- n>pv</c-><c- p>).</c-><c- n>swap</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-></code>.
  No effects if an exception is thrown.</p>
    <li data-md>
     <p>Throws: Any exception thrown by the copier or <code class="highlight"><c- n>bad_alloc</c-></code> if required
  storage cannot be obtained.</p>
    <li data-md>
     <p>Returns: <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.</p>
    <li data-md>
     <p>Postconditions: The state of <code class="highlight"><c- o>*</c-><c- k>this</c-></code> is as if copy constructed from <code class="highlight"><c- n>pv</c-></code>.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>=</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;&amp;</c-> <c- n>pv</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Effects: Equivalent to <code class="highlight"><c- n>polymorphic_value</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>pv</c-><c- p>)).</c-><c- n>swap</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Returns: <code class="highlight"><c- o>*</c-><c- k>this</c-></code>.</p>
    <li data-md>
     <p>Postconditions: The state <code class="highlight"><c- o>*</c-><c- k>this</c-></code> is equivalent to the original state of <code class="highlight"><c- n>pv</c-></code>.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.6" id="xz6-class-template-polymorphic_value-modifiers-polymorphic_valuemodifiers"><span class="secno">4.5.6. </span><span class="content">X.Z.6 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> modifiers [polymorphic_value.modifiers]</span><a class="self-link" href="#xz6-class-template-polymorphic_value-modifiers-polymorphic_valuemodifiers"></a></h4>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>
      Constraints: is_­is_nothrow_swappable­v
      <c>
        is true. is_­is_nothrow_swappable­v
       <d> is true.</d>
      </c>
     </p>
    <li data-md>
     <p>Effects: Invokes swap on the stored pointers and on the stored copiers and deleters of *this and <code class="highlight"><c- n>p</c-></code>.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.7" id="xz7-class-template-polymorphic_value-observers-polymorphic_valueobservers"><span class="secno">4.5.7. </span><span class="content">X.Z.7 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> observers [polymorphic_value.observers]</span><a class="self-link" href="#xz7-class-template-polymorphic_value-observers-polymorphic_valueobservers"></a></h4>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- k>const</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>*</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
<c- k>constexpr</c-> <c- n>T</c-><c- o>&amp;</c-> <c- k>operator</c-><c- o>*</c-><c- p>();</c->
</pre>
   <ul>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- b>bool</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p>Returns: A reference to the owned object.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- k>const</c-> <c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>-></c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
<c- k>constexpr</c-> <c- n>T</c-><c- o>*</c-> <c- k>operator</c-><c- o>-></c-><c- p>();</c->
</pre>
   <ul>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- b>bool</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-></code> is <code class="highlight">true</code>.</p>
    <li data-md>
     <p>Returns: A pointer to the owned object.</p>
   </ul>
<pre class="language-cpp highlight"><c- k>explicit</c-> <c- k>operator</c-> <c- b>bool</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Returns: <code class="highlight">false</code> if the <code class="highlight"><c- n>polymorphic_value</c-></code> is empty, otherwise <code class="highlight">true</code>.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.8" id="xz8-class-template-polymorphic_value-creation-polymorphic_valuecreation"><span class="secno">4.5.8. </span><span class="content">X.Z.8 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> creation [polymorphic_value.creation]</span><a class="self-link" href="#xz8-class-template-polymorphic_value-creation-polymorphic_valuecreation"></a></h4>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-><c- o>=</c-><c- n>T</c-><c- p>,</c-> <c- k>class</c-> <c- p>...</c-><c- n>Ts</c-><c- o>></c-> 
<c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>make_polymorphic_value</c-><c- p>(</c-><c- n>Ts</c-><c- o>&amp;&amp;</c-> <c- p>...</c-><c- n>ts</c-><c- p>);</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: <code class="highlight"><c- n>is_constructible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- p>,</c-> <c- n>Ts</c-><c- p>...</c-><c- o>></c-></code> is true.</p>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- n>U</c-></code> meets the <code class="highlight"><c- n>Cpp17CopyConstructible</c-></code> requirements.</p>
    <li data-md>
     <p>Returns: A <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> owning an object of type <code class="highlight"><c- n>U</c-></code> direct-non-list-initialized with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>(</c-><c- n>ts</c-><c- p>)...</c-></code>.</p>
   </ul>
   <p>[Note: Implementations are encouraged to avoid multiple allocations. - end note]</p>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>U</c-> <c- o>=</c-> <c- n>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>allocator</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>,</c-> <c- k>class</c-><c- p>...</c-> <c- n>Ts</c-><c- o>></c->
<c- k>constexpr</c-> <c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>allocate_polymorphic_value</c-><c- p>(</c-><c- k>const</c-> <c- n>A</c-><c- o>&amp;</c-> <c- n>a</c-><c- p>,</c-> <c- n>Ts</c-><c- o>&amp;&amp;</c-><c- p>...</c-> <c- n>ts</c-><c- p>);</c->
</pre>
   <ul>
    <li data-md>
     <p>Constraints: <code class="highlight"><c- n>is_constructible_v</c-><c- o>&lt;</c-><c- n>U</c-><c- p>,</c-> <c- n>Ts</c-><c- p>...</c-><c- o>></c-></code> is true.</p>
    <li data-md>
     <p>Preconditions: <code class="highlight"><c- n>U</c-></code> meets the <code class="highlight"><c- n>Cpp17CopyConstructible</c-></code> requirements.</p>
    <li data-md>
     <p>Effects: Constructs a polymorphic_value­ that shall use a copy of <code class="highlight"><c- n>a</c-></code> to allocate memory for internal use.</p>
    <li data-md>
     <p>Returns: A <code class="highlight"><c- n>polymorphic_value</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> owning an object of type <code class="highlight"><c- n>U</c-></code> direct-non-list-initialized with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>Ts</c-><c- o>></c-><c- p>(</c-><c- n>ts</c-><c- p>)...</c-></code>.</p>
   </ul>
   <h4 class="heading settled" data-level="4.5.9" id="xz9-class-template-polymorphic_value-specialized-algorithms-polymorphic_valuespec"><span class="secno">4.5.9. </span><span class="content">X.Z.9 Class template <code class="highlight"><c- n>polymorphic_value</c-></code> specialized algorithms [polymorphic_value.spec]</span><a class="self-link" href="#xz9-class-template-polymorphic_value-specialized-algorithms-polymorphic_valuespec"></a></h4>
<pre class="language-cpp highlight"><c- k>friend</c-> <c- k>constexpr</c-> <c- b>void</c-> <c- nf>swap</c-><c- p>(</c-><c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>p</c-><c- p>,</c-> <c- n>polymorphic_value</c-><c- o>&amp;</c-> <c- n>u</c-><c- p>)</c-> <c- k>noexcept</c-><c- p>;</c->
</pre>
   <ul>
    <li data-md>
     <p>Effects: Equivalent to <code class="highlight"><c- n>p</c-><c- p>.</c-><c- n>swap</c-><c- p>(</c-><c- n>u</c-><c- p>)</c-></code>.</p>
   </ul>
   <h2 class="heading settled" data-level="5" id="acknowledgements"><span class="secno">5. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>The authors would like to thank Maciej Bogus, Matthew Calabrese, Casey Carter,
Germán Diago, Louis Dionne, Bengt Gustafsson, Tom Hudson, Stephan T Lavavej,
Tomasz Kamiński, David Krauss, Thomas Koeppe, LanguageLawyer, Nevin Liber,
Nathan Myers, Roger Orr, Geoff Romer, Patrice Roy, Tony van Eerd and
Ville Voutilainen for suggestions and useful discussion.</p>
   <p>The authors would also extend thanks for contributions to the reference
implementation which has driven the design, including Anthony Williams,
Ed Catmur, and Marcell Kiss.</p>
   <h3 class="heading settled" data-level="5.1" id="references"><span class="secno">5.1. </span><span class="content">References</span><a class="self-link" href="#references"></a></h3>
   <p>[N3339] <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3339.pdf">"A Preliminary Proposal for a Deep-Copying Smart Pointer", W.E.Brown, 2012</a></p>
   <p>[p1950r1] <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1950r1.html">indirect_value: A Free-Store-Allocated Value Type For C++</a></p>
   <p>[P0302r1] <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1950r1.html">"Removing Allocator support in std::function", Jonathan Wakely</a></p>
   <p>[M. Knejp] <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0316r0.html">P0316R0: allocate_unique and allocator_delete</a></p>
   <p>[S.Parent] <a href="https://github.com/sean-parent/sean-parent.github.io/wiki/Papers-and-Presentations">"C++ Seasoning", Sean Parent, 2013</a></p>
   <p>[Impl] <a href="https://github.com/jbcoe/polymorphic_value">Reference implementation: polymorphic_value, J.B.Coe</a></p>
   <p>[P0302r1] <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r1.html">"Removing Allocator support in std::function", Jonathan Wakely</a></p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>