<!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>p0798R6: Monadic operations for std::optional</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;
		text-decoratin
	}
	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 span:not(.dfn-paneled) {
			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 type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

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

:root {
    --highlight-hover-bg: rgba(0, 0, 0, .05);
}
.line-numbered {
    display: grid !important;
    grid-template-columns: min-content 1fr;
    grid-auto-flow: row;
}
.line-numbered > *,
.line-numbered::before,
.line-numbered::after {
    grid-column: 1/-1;
}
.line-no {
    grid-column: 1;
    color: gray;
}
.line {
    grid-column: 2;
}
.line:hover {
    background: var(--highlight-hover-bg);
}
.line-no[data-line]::before {
    padding: 0 .5em 0 .1em;
    content: attr(data-line);
}
.line-no[data-line-end]::after {
    padding: 0 .5em 0 .1em;
    content: attr(data-line-end);
}
</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

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

@media (prefers-color-scheme: dark) {
    :root {
        --highlight-hover-bg: rgba(255, 255, 255, .05);
    }
}
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">p0798R6<br>Monadic operations for std::optional</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="2021-04-27">2021-04-27</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="wg21.tartanllama.xyz/monadic-optional">wg21.tartanllama.xyz/monadic-optional</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:sybrand@microsoft.com">Sy Brand</a>
     <dt>Audience:
     <dd>LWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>std::optional is a very important vocabulary type in C++17 and up. Some uses of it can be very verbose and would benefit from operations which allow functional composition. I propose adding map, and_then, and or_else member functions to std::optional to support this monadic style of programming.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#changes-from-r5"><span class="secno">1</span> <span class="content">Changes from r5</span></a>
    <li><a href="#changes-from-r4"><span class="secno">2</span> <span class="content">Changes from r4</span></a>
    <li><a href="#changes-from-r3"><span class="secno">3</span> <span class="content">Changes from r3</span></a>
    <li><a href="#changes-from-r2"><span class="secno">4</span> <span class="content">Changes from r2</span></a>
    <li><a href="#changes-from-r1"><span class="secno">5</span> <span class="content">Changes from r1</span></a>
    <li><a href="#changes-from-r0"><span class="secno">6</span> <span class="content">Changes from r0</span></a>
    <li><a href="#motivation"><span class="secno">7</span> <span class="content">Motivation</span></a>
    <li>
     <a href="#proposed-solution"><span class="secno">8</span> <span class="content">Proposed solution</span></a>
     <ol class="toc">
      <li><a href="#transform"><span class="secno">8.1</span> <span class="content"><code class="highlight"><c- n>transform</c-></code></span></a>
      <li><a href="#and_then"><span class="secno">8.2</span> <span class="content"><code class="highlight"><c- n>and_then</c-></code></span></a>
      <li><a href="#or_else"><span class="secno">8.3</span> <span class="content"><code class="highlight"><c- n>or_else</c-></code></span></a>
      <li><a href="#chaining"><span class="secno">8.4</span> <span class="content">Chaining</span></a>
     </ol>
    <li><a href="#how-other-languages-handle-this"><span class="secno">9</span> <span class="content">How other languages handle this</span></a>
    <li>
     <a href="#considerations"><span class="secno">10</span> <span class="content">Considerations</span></a>
     <ol class="toc">
      <li><a href="#disallowing-function-pointers"><span class="secno">10.1</span> <span class="content">Disallowing function pointers</span></a>
      <li><a href="#mapping-functions-returning-void"><span class="secno">10.2</span> <span class="content">Mapping functions returning <code class="highlight"><c- b>void</c-></code></span></a>
      <li><a href="#more-functions"><span class="secno">10.3</span> <span class="content">More functions</span></a>
      <li><a href="#transform-only"><span class="secno">10.4</span> <span class="content"><code class="highlight"><c- n>transform</c-></code> only</span></a>
      <li><a href="#operator-overloading"><span class="secno">10.5</span> <span class="content">Operator overloading</span></a>
      <li><a href="#applicative-functors"><span class="secno">10.6</span> <span class="content">Applicative Functors</span></a>
      <li><a href="#sfinae-friendliness"><span class="secno">10.7</span> <span class="content">SFINAE-friendliness</span></a>
     </ol>
    <li>
     <a href="#pitfalls"><span class="secno">11</span> <span class="content">Pitfalls</span></a>
     <ol class="toc">
      <li><a href="#other-solutions"><span class="secno">11.1</span> <span class="content">Other solutions</span></a>
      <li><a href="#interaction-with-other-proposals"><span class="secno">11.2</span> <span class="content">Interaction with other proposals</span></a>
     </ol>
    <li><a href="#implementation-experience"><span class="secno">12</span> <span class="content">Implementation experience</span></a>
    <li>
     <a href="#proposed-wording"><span class="secno">13</span> <span class="content">Proposed Wording</span></a>
     <ol class="toc">
      <li><a href="#add-feature-test-macro-to-table-36-in-supportlimitsgeneral"><span class="secno">13.1</span> <span class="content">Add feature test macro to Table 36 in [support.limits.general]</span></a>
      <li><a href="#add-declarations-for-the-monadic-operations-to-the-synopsis-of-class-template-optional-in-optionaloptional"><span class="secno">13.2</span> <span class="content">Add declarations for the monadic operations to the synopsis of class template optional in [optional.optional]</span></a>
      <li><a href="#add-new-subclause-monadic-operations-optionalmonadic-between-optionalobserve-and-optionalmod"><span class="secno">13.3</span> <span class="content">Add new subclause "Monadic operations [optional.monadic]" between [optional.observe] and [optional.mod]</span></a>
      <li><a href="#acknowledgements"><span class="secno">13.4</span> <span class="content">Acknowledgements</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="changes-from-r5"><span class="secno">1. </span><span class="content">Changes from r5</span><a class="self-link" href="#changes-from-r5"></a></h2>
   <ul>
    <li data-md>
     <p>Respecify wording in terms of "Equivalent to"</p>
    <li data-md>
     <p>Add constraints for all invocables</p>
    <li data-md>
     <p>Use <code class="highlight"><c- n>decay_t</c-></code> for <code class="highlight"><c- n>transform</c-></code></p>
    <li data-md>
     <p>Remove function bodies from synopsis</p>
    <li data-md>
     <p>Make rvalue <code class="highlight"><c- n>or_else</c-></code> overload require <em>Cpp17CopyConstructible</em></p>
   </ul>
   <h2 class="heading settled" data-level="2" id="changes-from-r4"><span class="secno">2. </span><span class="content">Changes from r4</span><a class="self-link" href="#changes-from-r4"></a></h2>
   <ul>
    <li data-md>
     <p>Remove non-<code class="highlight"><c- k>const</c-></code> lvalue and <code class="highlight"><c- k>const</c-></code> rvalue overloads for <code class="highlight"><c- n>or_else</c-></code></p>
    <li data-md>
     <p>Remove special-casing of <code class="highlight"><c- b>void</c-></code> from <code class="highlight"><c- n>or_else</c-></code>:
Mandates: <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-></code> is <span style="background: lightcoral"><code class="highlight"><c- b>void</c-></code> or</span> convertible to <code class="highlight"><c- n>optional</c-></code>.</p>
     <p>Effects: If <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has a value, returns <code class="highlight"><c- o>*</c-><c- k>this</c-></code>. <span style="background: lightcoral">Otherwise, if <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-></code> is <code class="highlight"><c- b>void</c-></code>, calls <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)</c-></code> and returns <code class="highlight"><c- n>nullopt</c-></code>.</span> Otherwise, returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)()</c-></code>.</p>
     <p>Effects: If <code class="highlight"><c- o>*</c-><c- k>this</c-></code> has a value, returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-></code>. <span style="background: lightcoral">Otherwise, if <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-></code> is <code class="highlight"><c- b>void</c-></code>, calls <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)</c-></code> and returns <code class="highlight"><c- n>nullopt</c-></code>.</span> Otherwise, returns <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)()</c-></code>.</p>
    <li data-md>
     <p>Use <code class="highlight"><c- n>remove_cv_ref_t</c-></code> instead of <code class="highlight"><c- n>decay_t</c-></code></p>
    <li data-md>
     <p>Add feature test macro</p>
    <li data-md>
     <p>Add function bodies to synopsis</p>
    <li data-md>
     <p>Formatting changes</p>
   </ul>
   <h2 class="heading settled" data-level="3" id="changes-from-r3"><span class="secno">3. </span><span class="content">Changes from r3</span><a class="self-link" href="#changes-from-r3"></a></h2>
   <ul>
    <li data-md>
     <p>Wording improvements</p>
   </ul>
   <h2 class="heading settled" data-level="4" id="changes-from-r2"><span class="secno">4. </span><span class="content">Changes from r2</span><a class="self-link" href="#changes-from-r2"></a></h2>
   <ul>
    <li data-md>
     <p>Rename <code class="highlight"><c- n>map</c-></code> to <code class="highlight"><c- n>transform</c-></code></p>
    <li data-md>
     <p>Remove "Alternative Names" section</p>
    <li data-md>
     <p>Address feedback on disallowing function pointers</p>
    <li data-md>
     <p>Remove capability for mapping void-returning functions</p>
    <li data-md>
     <p>Tighten wording</p>
    <li data-md>
     <p>Discuss SFINAE-friendliness</p>
   </ul>
   <h2 class="heading settled" data-level="5" id="changes-from-r1"><span class="secno">5. </span><span class="content">Changes from r1</span><a class="self-link" href="#changes-from-r1"></a></h2>
   <ul>
    <li data-md>
     <p>Add list of programming languages to proposed solution section</p>
    <li data-md>
     <p>Change map example code to not take address of stdlib function</p>
    <li data-md>
     <p>Update wording to use <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>monostate</c-></code> on <code class="highlight"><c- b>void</c-></code>-returning callables</p>
   </ul>
   <h2 class="heading settled" data-level="6" id="changes-from-r0"><span class="secno">6. </span><span class="content">Changes from r0</span><a class="self-link" href="#changes-from-r0"></a></h2>
   <ul>
    <li data-md>
     <p>More notes on P0650</p>
    <li data-md>
     <p>Discussion about mapping of functions returning <code class="highlight"><c- b>void</c-></code></p>
   </ul>
   <h2 class="heading settled" data-level="7" id="motivation"><span class="secno">7. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h2>
   <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> aims to be a "vocabulary type", i.e. the canonical type to represent some programming concept. As such, <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> will become widely used to represent an object which may or may not contain a value. Unfortunately, chaining together many computations which may or may not produce a value can be verbose, as empty-checking code will be mixed in with the actual programming logic. As an example, the following code automatically extracts cats from images and makes them more cute:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>image</c-> <c- nf>get_cute_cat</c-> <c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-> <c- n>add_rainbow</c-><c- p>(</c-></span><span class="line-no" data-line="3"></span><span class="line">             <c- n>make_smaller</c-><c- p>(</c-></span><span class="line-no" data-line="4"></span><span class="line">               <c- n>make_eyes_sparkle</c-><c- p>(</c-></span><span class="line-no" data-line="5"></span><span class="line">                 <c- n>add_bow_tie</c-><c- p>(</c-></span><span class="line-no" data-line="6"></span><span class="line">                   <c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>))));</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <p>But there’s a problem. What if there’s not a cat in the picture? What if there’s no good place to add a bow tie? What if it has its back turned and we can’t make its eyes sparkle? Some of these operations could fail.</p>
   <p>One option would be to throw exceptions on failure. However, there are many code bases which do not use exceptions for a variety of reasons. There’s also the possibility that we’re going to get <em>lots</em> of pictures without cats in them, in which case we’d be using exceptions for control flow. This is commonly seen as bad practice, and has an item warning against it in the <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e3-use-exceptions-for-error-handling-only">C++ Core Guidelines</a>.</p>
   <p>Another option would be to make those operations which could fail return a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code>:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>image</c-><c- o>></c-> <c- n>get_cute_cat</c-> <c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>auto</c-> <c- n>cropped</c-> <c- o>=</c-> <c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>);</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>cropped</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="4"></span><span class="line">      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>nullopt</c-><c- p>;</c-></span><span class="line-no" data-line="5"></span><span class="line">    <c- p>}</c-></span><span class="line-no" data-line="6"></span><span class="line"></span><span class="line-no" data-line="7"></span><span class="line">    <c- k>auto</c-> <c- n>with_tie</c-> <c- o>=</c-> <c- n>add_bow_tie</c-><c- p>(</c-><c- o>*</c-><c- n>cropped</c-><c- p>);</c-></span><span class="line-no" data-line="8"></span><span class="line">    <c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>with_tie</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="9"></span><span class="line">      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>nullopt</c-><c- p>;</c-></span><span class="line-no" data-line="10"></span><span class="line">    <c- p>}</c-></span><span class="line-no" data-line="11"></span><span class="line"></span><span class="line-no" data-line="12"></span><span class="line">    <c- k>auto</c-> <c- n>with_sparkles</c-> <c- o>=</c-> <c- n>make_eyes_sparkle</c-><c- p>(</c-><c- o>*</c-><c- n>with_tie</c-><c- p>);</c-></span><span class="line-no" data-line="13"></span><span class="line">    <c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>with_sparkles</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="14"></span><span class="line">      <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>nullopt</c-><c- p>;</c-></span><span class="line-no" data-line="15"></span><span class="line">    <c- p>}</c-></span><span class="line-no" data-line="16"></span><span class="line"></span><span class="line-no" data-line="17"></span><span class="line">    <c- k>return</c-> <c- n>add_rainbow</c-><c- p>(</c-><c- n>make_smaller</c-><c- p>(</c-><c- o>*</c-><c- n>with_sparkles</c-><c- p>));</c-></span><span class="line-no" data-line="18"></span><span class="line"><c- p>}</c-></span></pre>
   <p>Our code now has a lot of boilerplate to deal with the case where a step fails. Not only does this increase the noise and cognitive load of the function, but if we forget to put in a check, then suddenly we’re down the hole of undefined behaviour if we <code class="highlight"><c- o>*</c-><c- n>empty_optional</c-></code>.</p>
   <p>Another possibility would be to call <code class="highlight"><c- p>.</c-><c- n>value</c-><c- p>()</c-></code> on the optionals and let the exception be thrown and caught like so:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>image</c-><c- o>></c-> <c- n>get_cute_cat</c-> <c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>try</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">        <c- k>auto</c-> <c- n>cropped</c-> <c- o>=</c-> <c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>);</c-></span><span class="line-no" data-line="4"></span><span class="line">        <c- k>auto</c-> <c- n>with_tie</c-> <c- o>=</c-> <c- n>add_bow_tie</c-><c- p>(</c-><c- n>cropped</c-><c- p>.</c-><c- n>value</c-><c- p>());</c-></span><span class="line-no" data-line="5"></span><span class="line">        <c- k>auto</c-> <c- n>with_sparkles</c-> <c- o>=</c-> <c- n>make_eyes_sparkle</c-><c- p>(</c-><c- n>with_tie</c-><c- p>.</c-><c- n>value</c-><c- p>());</c-></span><span class="line-no" data-line="6"></span><span class="line">        <c- k>return</c-> <c- nf>add_rainbow</c-><c- p>(</c-><c- n>make_smaller</c-><c- p>(</c-><c- n>with_sparkles</c-><c- p>.</c-><c- n>value</c-><c- p>()));</c-></span><span class="line-no" data-line="7"></span><span class="line">    <c- k>catch</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>bad_optional_access</c-><c- o>&amp;</c-> <c- n>e</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="8"></span><span class="line">        <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>nullopt</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line">    <c- p>}</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- p>}</c-></span></pre>
   <p>Again, this is using exceptions for control flow. There must be a better way.</p>
   <h2 class="heading settled" data-level="8" id="proposed-solution"><span class="secno">8. </span><span class="content">Proposed solution</span><a class="self-link" href="#proposed-solution"></a></h2>
   <p>This paper proposes adding additional member functions to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> in order to push the handling of empty states off to the side. The proposed additions are <code class="highlight"><c- n>map</c-></code>, <code class="highlight"><c- n>and_then</c-></code> and <code class="highlight"><c- n>or_else</c-></code>. Using these new functions, the code above becomes this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>image</c-><c- o>></c-> <c- n>get_cute_cat</c-> <c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-> <c- nf>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>)</c-></span><span class="line-no" data-line="3"></span><span class="line">           <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>add_bow_tie</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">           <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>make_eyes_sparkle</c-><c- p>)</c-></span><span class="line-no" data-line="5"></span><span class="line">           <c- p>.</c-><c- n>map</c-><c- p>(</c-><c- n>make_smaller</c-><c- p>)</c-></span><span class="line-no" data-line="6"></span><span class="line">           <c- p>.</c-><c- n>map</c-><c- p>(</c-><c- n>add_rainbow</c-><c- p>);</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <p>We’ve successfully got rid of all the manual checking. We’ve even improved on the clarity of the non-<code class="highlight"><c- n>optional</c-></code> example, which needed to either be read inside-out or split into multiple declarations.</p>
   <p>This is common in other programming languages. Here is a list of programming languages which have a <code class="highlight"><c- n>optional</c-></code>-like type with a monadic interface or some similar syntactic sugar:</p>
   <ul>
    <li data-md>
     <p>Java: <code class="highlight"><c- n>Optional</c-></code></p>
    <li data-md>
     <p>Swift: <code class="highlight"><c- n>Optional</c-></code></p>
    <li data-md>
     <p>Haskell: <code class="highlight"><c- n>Maybe</c-></code></p>
    <li data-md>
     <p>Rust: <code class="highlight"><c- n>Option</c-></code></p>
    <li data-md>
     <p>OCaml: <code class="highlight"><c- n>option</c-></code></p>
    <li data-md>
     <p>Scala: <code class="highlight"><c- n>Option</c-></code></p>
    <li data-md>
     <p>Agda: <code class="highlight"><c- n>Maybe</c-></code></p>
    <li data-md>
     <p>Idris: <code class="highlight"><c- n>Maybe</c-></code></p>
    <li data-md>
     <p>Kotlin: <code class="highlight"><c- n>T</c-><c- o>?</c-></code></p>
    <li data-md>
     <p>StandardML: <code class="highlight"><c- n>option</c-></code></p>
    <li data-md>
     <p>C#: <code class="highlight"><c- n>Nullable</c-></code></p>
   </ul>
   <p>Here is a list of programming languages which have a <code class="highlight"><c- n>optional</c-></code>-like type without a monadic interface or syntactic sugar:</p>
   <ul>
    <li data-md>
     <p>C++</p>
    <li data-md>
     <p>I couldn’t find any others</p>
   </ul>
   <p>All that we need now is an understanding of what <code class="highlight"><c- n>transform</c-></code> and <code class="highlight"><c- n>and_then</c-></code> do and how to use them.</p>
   <h3 class="heading settled" data-level="8.1" id="transform"><span class="secno">8.1. </span><span class="content"><code class="highlight"><c- n>transform</c-></code></span><a class="self-link" href="#transform"></a></h3>
   <p><code class="highlight"><c- n>transform</c-></code> is used to apply a function to change the value (and possibly the type) stored in an optional. It applies a function to the value stored in the optional and returns the result wrapped in an optional. If there is no stored value, then it returns an empty optional.</p>
   <p>For example, if you have a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-></code> and you want to get a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- b>size_t</c-><c- o>></c-></code> giving the size of the string if one is available, you could write this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>auto</c-> <c- n>s</c-> <c- o>=</c-> <c- n>opt_string</c-><c- p>.</c-><c- n>transform</c-><c- p>([](</c-><c- k>auto</c-><c- o>&amp;&amp;</c-> <c- n>s</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>s</c-><c- p>.</c-><c- n>size</c-><c- p>();</c-> <c- p>});</c-></span></pre>
   <p>which is somewhat equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- n>opt_string</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>s</c-> <c- o>=</c-> <c- n>opt_string</c-><c- o>-></c-><c- n>size</c-><c- p>();</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span></pre>
   <p><code class="highlight"><c- n>transform</c-></code> has one overload (expositional):</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>class</c-> <c- nc>optional</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Return</c-><c- o>></c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>Return</c-><c- o>></c-> <c- n>transform</c-> <c- p>(</c-><c- n>function</c-><c- o>&lt;</c-><c- n>Return</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-><c- o>></c-> <c- n>func</c-><c- p>);</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>};</c-></span></pre>
   <p>It takes any invocable. If the optional does not have a value stored, then an empty optional is returned. Otherwise, the given function is called with the stored value as an argument, and the return value is returned inside an optional.</p>
   <p>If you come from a functional programming or category theory background, you may recognise this as a functor map.</p>
   <h3 class="heading settled" data-level="8.2" id="and_then"><span class="secno">8.2. </span><span class="content"><code class="highlight"><c- n>and_then</c-></code></span><a class="self-link" href="#and_then"></a></h3>
   <p><code class="highlight"><c- n>and_then</c-></code> is used to compose functions which return <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code>.</p>
   <p>For example, say you have <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>string</c-><c- o>></c-></code> and a function like <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>stoi</c-></code> which returns a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-></code> instead of throwing on failure. Rather than manually checking the optional string before calling, you could do this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>i</c-> <c- o>=</c-> <c- n>opt_string</c-><c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>stoi</c-><c- p>);</c-></span></pre>
   <p>Which is roughly equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- n>opt_string</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">   <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>i</c-> <c- o>=</c-> <c- n>stoi</c-><c- p>(</c-><c- o>*</c-><c- n>opt_string</c-><c- p>);</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span></pre>
   <p><code class="highlight"><c- n>and_then</c-></code> has one overload which looks like this (again, expositional):</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>class</c-> <c- nc>optional</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Return</c-><c- o>></c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>Return</c-><c- o>></c-> <c- n>and_then</c-> <c- p>(</c-><c- n>function</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>Return</c-><c- o>></c-><c- p>(</c-><c- n>T</c-><c- p>)</c-><c- o>></c-> <c- n>func</c-><c- p>);</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>};</c-></span></pre>
   <p>It takes any callable object which returns a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code>. If the <code class="highlight"><c- n>optional</c-></code> does not have a value stored, then an empty <code class="highlight"><c- n>optional</c-></code> is returned. Otherwise, the given function is called with the stored value as an argument, and the return value is returned.</p>
   <p>Again, those from an FP background will recognise this as a monadic bind.</p>
   <h3 class="heading settled" data-level="8.3" id="or_else"><span class="secno">8.3. </span><span class="content"><code class="highlight"><c- n>or_else</c-></code></span><a class="self-link" href="#or_else"></a></h3>
   <p><code class="highlight"><c- n>or_else</c-></code> returns the optional if it has a value, otherwise it calls a given function. This allows you do things like logging or throwing exceptions in monadic contexts:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>get_opt</c-><c- p>().</c-><c- n>or_else</c-><c- p>([]{</c-><c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"get_opt failed"</c-><c- p>;});</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- n>get_opt</c-><c- p>().</c-><c- n>or_else</c-><c- p>([]{</c-><c- k>throw</c-> <c- n>std</c-><c- o>::</c-><c- n>runtime_error</c-><c- p>(</c-><c- s>"get_opt_failed"</c-><c- p>)});</c-></span></pre>
   <p>Users can easily abstract these patterns if they are common:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- b>void</c-> <c- nf>opt_log</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>string_view</c-> <c- n>msg</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">     <c- k>return</c-> <c- p>[</c-><c- o>=</c-><c- p>]</c-> <c- p>{</c-> <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- n>msg</c-><c- p>;</c-> <c- p>};</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"></span><span class="line-no" data-line="5"></span><span class="line"><c- b>void</c-> <c- nf>opt_throw</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>string_view</c-> <c- n>msg</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="6"></span><span class="line">     <c- k>return</c-> <c- p>[</c-><c- o>=</c-><c- p>]</c-> <c- p>{</c-> <c- k>throw</c-> <c- n>std</c-><c- o>::</c-><c- n>runtime_error</c-><c- p>(</c-><c- n>msg</c-><c- p>);</c-> <c- p>};</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="8"></span><span class="line"></span><span class="line-no" data-line="9"></span><span class="line"><c- n>get_opt</c-><c- p>().</c-><c- n>or_else</c-><c- p>(</c-><c- n>opt_log</c-><c- p>(</c-><c- s>"get_opt failed"</c-><c- p>));</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- n>get_opt</c-><c- p>().</c-><c- n>or_else</c-><c- p>(</c-><c- n>opt_throw</c-><c- p>(</c-><c- s>"get_opt failed"</c-><c- p>));</c-></span></pre>
   <p>It has one overload (expositional):</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>class</c-> <c- nc>optional</c-> <c- p>{</c-></span><span class="line-no" data-line="3"></span><span class="line">    <c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Return</c-><c- o>></c-></span><span class="line-no" data-line="4"></span><span class="line">    <c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-> <c- n>or_else</c-> <c- p>(</c-><c- n>function</c-><c- o>&lt;</c-><c- n>Return</c-><c- p>()</c-><c- o>></c-> <c- n>func</c-><c- p>);</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>};</c-></span></pre>
   <p><code class="highlight"><c- n>func</c-></code> will be called if <code class="highlight"><c- o>*</c-><c- k>this</c-></code> is empty. <code class="highlight"><c- n>Return</c-></code> will either be convertible to <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code>, or <code class="highlight"><c- b>void</c-></code>. In the former case, the return of <code class="highlight"><c- n>func</c-></code> will be returned from <code class="highlight"><c- n>or_else</c-></code>; in the second case <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>nullopt</c-></code> will be returned.</p>
   <h3 class="heading settled" data-level="8.4" id="chaining"><span class="secno">8.4. </span><span class="content">Chaining</span><a class="self-link" href="#chaining"></a></h3>
   <p>With these two functions, doing a lot of chaining of functions which could fail becomes very clean:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>foo</c-><c- p>()</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-></span><span class="line-no" data-line="3"></span><span class="line">      <c- nf>a</c-><c- p>().</c-><c- n>and_then</c-><c- p>(</c-><c- n>b</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">         <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>c</c-><c- p>)</c-></span><span class="line-no" data-line="5"></span><span class="line">         <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>d</c-><c- p>)</c-></span><span class="line-no" data-line="6"></span><span class="line">         <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>e</c-><c- p>);</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <p>Taking the example of <code class="highlight"><c- n>stoi</c-></code> from earlier, we could carry out mathematical operations on the result by just adding <code class="highlight"><c- n>map</c-></code> calls:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>i</c-> <c- o>=</c-> <c- n>opt_string</c-></span><span class="line-no" data-line="2"></span><span class="line">                       <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>stoi</c-><c- p>)</c-></span><span class="line-no" data-line="3"></span><span class="line">                       <c- p>.</c-><c- n>transform</c-><c- p>([](</c-><c- k>auto</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>i</c-> <c- o>*</c-> <c- mi>2</c-><c- p>;</c-> <c- p>});</c-></span></pre>
   <p>We can also intersperse our chain with error checking code:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>i</c-> <c- o>=</c-> <c- n>opt_string</c-></span><span class="line-no" data-line="2"></span><span class="line">                       <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>stoi</c-><c- p>)</c-></span><span class="line-no" data-line="3"></span><span class="line">                       <c- p>.</c-><c- n>or_else</c-><c- p>(</c-><c- n>opt_throw</c-><c- p>(</c-><c- s>"stoi failed"</c-><c- p>))</c-></span><span class="line-no" data-line="4"></span><span class="line">                       <c- p>.</c-><c- n>transform</c-><c- p>([](</c-><c- k>auto</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c-> <c- k>return</c-> <c- n>i</c-> <c- o>*</c-> <c- mi>2</c-><c- p>;</c-> <c- p>});</c-></span></pre>
   <h2 class="heading settled" data-level="9" id="how-other-languages-handle-this"><span class="secno">9. </span><span class="content">How other languages handle this</span><a class="self-link" href="#how-other-languages-handle-this"></a></h2>
   <p><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> is known as <code class="highlight"><c- n>Maybe</c-></code> in Haskell and it provides much the same functionality. <code class="highlight"><c- n>transform</c-></code> is in <code class="highlight"><c- n>Functor</c-></code> and named <code class="highlight"><c- n>fmap</c-></code>, and <code class="highlight"><c- n>and_then</c-></code> is in <code class="highlight"><c- n>Monad</c-></code> and named <code class="highlight"><c- o>>>=</c-></code> (bind).</p>
   <p>Rust has an <code class="highlight"><c- n>Option</c-></code> class, and uses the same names as are proposed in this paper. It also provides many additional member functions like <code class="highlight"><c- n>or</c-></code>, <code class="highlight"><c- n>and</c-></code>, <code class="highlight"><c- n>map_or_else</c-></code>.</p>
   <h2 class="heading settled" data-level="10" id="considerations"><span class="secno">10. </span><span class="content">Considerations</span><a class="self-link" href="#considerations"></a></h2>
   <h3 class="heading settled" data-level="10.1" id="disallowing-function-pointers"><span class="secno">10.1. </span><span class="content">Disallowing function pointers</span><a class="self-link" href="#disallowing-function-pointers"></a></h3>
   <p>In San Diego, a straw poll on disallowing passing function pointers to the functions proposed was made with the following results:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- o>|</c-><c- n>SF</c-><c- o>|</c-><c- n>F</c-><c- o>|</c-><c- n>N</c-><c- o>|</c-><c- n>A</c-><c- o>|</c-><c- n>SA</c-><c- o>|</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- o>|</c-><c- mi>3</c-> <c- o>|</c-><c- mi>6</c-><c- o>|</c-><c- mi>1</c-><c- o>|</c-><c- mi>0</c-><c- o>|</c-><c- mi>1</c-> <c- o>|</c-> </span></pre>
   <p>This poll was carried out with the understanding that some parts of Ranges (in particular <code class="highlight"><c- n>ranges</c-><c- o>::</c-><c- n>transform_view</c-></code>) disallow function pointers. However, this is not the case. From p0896r2:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-><c- o>&lt;</c-><c- n>InputRange</c-> <c- n>R</c-><c- p>,</c-> <c- n>CopyConstructible</c-> <c- n>F</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>requires</c-> <c- n>View</c-><c- o>&lt;</c-><c- n>R</c-><c- o>></c-> <c- o>&amp;&amp;</c-> <c- n>is_object_v</c-><c- o>&lt;</c-><c- n>F</c-><c- o>&amp;&amp;></c-> <c- n>Invocable</c-><c- o>&lt;</c-><c- n>F</c-><c- o>&amp;</c-><c- p>,</c-><c- n>iter_reference_t</c-><c- o>&lt;</c-><c- n>iterator_t</c-><c- o>&lt;</c-><c- n>R</c-><c- o>>>></c-></span><span class="line-no" data-line="3"></span><span class="line"><c- k>class</c-> <c- nc>transform_view</c-><c- p>;</c-></span></pre>
   <p>I imagine the confusion comes from <code class="highlight"><c- n>is_object_v</c-><c- o>&lt;</c-><c- n>F</c-><c- o>&amp;&amp;></c-></code>, but function pointers are object types. From n4460 (C++17):</p>
   <blockquote>
    <p>An object type is a (possibly cv-qualiﬁed) type that is not a function type, not a reference type, and not cv void.</p>
   </blockquote>
   <p>As far as I am aware, if we disallowed passing function pointers here then this would be the only place in the standard library which does so. Alongside the issue of consistency, ease-of-use is damaged. For example:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- b>int</c-> <c- nf>this_will_never_be_overloaded</c-><c- p>(</c-><c- b>double</c-><c- p>);</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- n>my_optional_double</c-><c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>this_will_never_be_overloaded</c-><c- p>);</c-> <c- c1>//not allowed</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- c1>//have to write this instead</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- n>my_optional_double</c-><c- p>.</c-><c- n>transform</c-><c- p>([](</c-><c- b>double</c-> <c- n>d</c-><c- p>){</c-> <c- k>return</c-> <c- nf>this_will_never_be_overloaded</c-><c- p>(</c-><c- n>d</c-><c- p>);</c-> <c- p>});</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- c1>//or use some sort of macro</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- n>my_optional_double</c-><c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>LIFT</c-><c- p>(</c-><c- n>this_will_never_be_overloaded</c-><c- p>));</c-></span></pre>
   <p>For library extensions which are supposed to aid ergonomics and simplify code, this goes in the opposite direction.</p>
   <p>The benefit of disallowing function pointers is avoidance of build breakages when a previously non-overloaded function is overloaded. This is not a new issue: it applies to practically every single higher order function in the C++ standard library, including functions in <code class="highlight"><c- o>&lt;</c-><c- n>algorithm</c-><c- o>></c-></code>, <code class="highlight"><c- o>&lt;</c-><c- n>numeric</c-><c- o>></c-></code>, and ranges. There are papers in flight to address this issue in other ways (such as p1170), but in the meantime it remains a problem. While I see the desire to avoid this issue, I think the cost of consistency and ease-of-use far outweighs the benefits. As such, this paper still allows function pointers to be passed.</p>
   <h3 class="heading settled" data-level="10.2" id="mapping-functions-returning-void"><span class="secno">10.2. </span><span class="content">Mapping functions returning <code class="highlight"><c- b>void</c-></code></span><a class="self-link" href="#mapping-functions-returning-void"></a></h3>
   <p>There are three main options for handling <code class="highlight"><c- b>void</c-></code>-returning functions for <code class="highlight"><c- n>transform</c-></code>. The simplest is to disallow it (this is what <code class="highlight"><c- n>boost</c-><c- o>::</c-><c- n>optional</c-></code> does). One is to return <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>monostate</c-><c- o>></c-></code> (or some other unit type) instead of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>void</c-><c- o>></c-></code> (this is what <code class="highlight"><c- n>tl</c-><c- o>::</c-><c- n>optional</c-></code> does). Another option is to add a <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>void</c-><c- o>></c-></code> specialization. This functionality can be desirable since it allows chaining functions which are used purely for side effects.</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>get_optional</c-><c- p>()</c->                <c- c1>// returns std::optional&lt;T></c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>print_value</c-><c- p>)</c->     <c- c1>// returns std::optional&lt;std::monostate></c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>notify_success</c-><c- p>);</c-> <c- c1>// Is only called when get_optional returned a value</c-></span></pre>
   <p>This proposal disallows mapping void-returning functions.</p>
   <h3 class="heading settled" data-level="10.3" id="more-functions"><span class="secno">10.3. </span><span class="content">More functions</span><a class="self-link" href="#more-functions"></a></h3>
   <p>Rust’s <a href="https://doc.rust-lang.org/std/option/enum.Option.html">Option</a> class provides a lot more than <code class="highlight"><c- n>map</c-></code>, <code class="highlight"><c- n>and_then</c-></code> and <code class="highlight"><c- n>or_else</c-></code>. If the idea to add these is received favourably, then we can think about what other additions we may want to make.</p>
   <h3 class="heading settled" data-level="10.4" id="transform-only"><span class="secno">10.4. </span><span class="content"><code class="highlight"><c- n>transform</c-></code> only</span><a class="self-link" href="#transform-only"></a></h3>
   <p>It would be possible to merge all of these into a single function which handles all use cases. However, I think this would make the function more difficult to teach and understand.</p>
   <h3 class="heading settled" data-level="10.5" id="operator-overloading"><span class="secno">10.5. </span><span class="content">Operator overloading</span><a class="self-link" href="#operator-overloading"></a></h3>
   <p>We could provide operator overloads with the same semantics as the functions. For example, <code class="highlight"><c- o>|</c-></code> could mean <code class="highlight"><c- n>transform</c-></code>, <code class="highlight"><c- o>>=</c-></code> <code class="highlight"><c- n>and_then</c-></code>, and <code class="highlight"><c- o>&amp;</c-></code> <code class="highlight"><c- n>or_else</c-></code>. Rewriting the original example gives this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- c1>// original</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>)</c-></span><span class="line-no" data-line="3"></span><span class="line">  <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>add_bow_tie</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">  <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>make_eyes_sparkle</c-><c- p>)</c-></span><span class="line-no" data-line="5"></span><span class="line">  <c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>make_smaller</c-><c- p>)</c-></span><span class="line-no" data-line="6"></span><span class="line">  <c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>add_rainbow</c-><c- p>);</c-></span><span class="line-no" data-line="7"></span><span class="line"></span><span class="line-no" data-line="8"></span><span class="line"><c- c1>// rewritten</c-></span><span class="line-no" data-line="9"></span><span class="line"><c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>)</c-></span><span class="line-no" data-line="10"></span><span class="line">   <c- o>>=</c-> <c- n>add_bow_tie</c-></span><span class="line-no" data-line="11"></span><span class="line">   <c- o>>=</c-> <c- n>make_eyes_sparkle</c-></span><span class="line-no" data-line="12"></span><span class="line">    <c- o>|</c-> <c- n>make_smaller</c-></span><span class="line-no" data-line="13"></span><span class="line">    <c- o>|</c-> <c- n>add_rainbow</c-><c- p>;</c-></span></pre>
   <p>Another option would be <code class="highlight"><c- o>>></c-></code> for <code class="highlight"><c- n>and_then</c-></code>.</p>
   <h3 class="heading settled" data-level="10.6" id="applicative-functors"><span class="secno">10.6. </span><span class="content">Applicative Functors</span><a class="self-link" href="#applicative-functors"></a></h3>
   <p><code class="highlight"><c- n>transform</c-></code> could be overloaded to accept callables wrapped in <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optionals</c-></code>. This fits the <em>applicative functor</em> concept. It would look like this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>Return</c-><c- o>></c-></span><span class="line-no" data-line="2"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>Return</c-><c- o>></c-> <c- n>map</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>function</c-><c- o>&lt;</c-><c- n>Return</c-><c- p>(</c-><c- n>T</c-><c- p>)</c-><c- o>>></c-> <c- n>func</c-><c- p>);</c-></span></pre>
   <p>This would give functional programmers the set of operations which they may expect from a monadic-style interface. However, I couldn’t think of many use-cases of this in C++. If some are found then we could add the extra overload.</p>
   <h3 class="heading settled" data-level="10.7" id="sfinae-friendliness"><span class="secno">10.7. </span><span class="content">SFINAE-friendliness</span><a class="self-link" href="#sfinae-friendliness"></a></h3>
   <p><code class="highlight"><c- n>transform</c-></code> and <code class="highlight"><c- n>and_then</c-></code> are specified to return <code class="highlight"><c- k>auto</c-></code>. This makes them not SFINAE-friendly. This is required because of the issue described in <a href="https://wg21.link/p0826">p0826</a>: if the callable which is passed in has an SFINAE-unfriendly call operator template, it could produce a hard error when instantiated in the <code class="highlight"><c- k>const</c-></code> and non-<code class="highlight"><c- k>const</c-></code> overloads of <code class="highlight"><c- n>transform</c-></code> and <code class="highlight"><c- n>and_then</c-></code> during overload resolution. For example, if <code class="highlight"><c- n>transform</c-></code> was SFINAE-friendly, the following code would result in a hard error:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>struct</c-> <c- nc>foo</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">  <c- b>void</c-> <c- nf>non_const</c-><c- p>()</c-> <c- p>{}</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>};</c-></span><span class="line-no" data-line="4"></span><span class="line"></span><span class="line-no" data-line="5"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- n>foo</c-><c- o>></c-> <c- n>f</c-> <c- o>=</c-> <c- n>foo</c-><c- p>{};</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- k>auto</c-> <c- n>l</c-> <c- o>=</c-> <c- p>[](</c-><c- k>auto</c-> <c- o>&amp;&amp;</c-><c- n>x</c-><c- p>)</c-> <c- p>{</c-> <c- n>x</c-><c- p>.</c-><c- n>non_const</c-><c- p>();</c-> <c- p>};</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- c1>//error: passing 'const foo' as 'this' argument discards qualifiers</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- n>f</c-><c- p>.</c-><c- n>transform</c-><c- p>(</c-><c- n>l</c-><c- p>);</c-> </span></pre>
   <p>If p0847 is accepted and this proposal is rebased on top of it, then this would no longer be an issue, and <code class="highlight"><c- n>transform</c-></code> and <code class="highlight"><c- n>and_then</c-></code> could be made SFINAE-friendly.</p>
   <h2 class="heading settled" data-level="11" id="pitfalls"><span class="secno">11. </span><span class="content">Pitfalls</span><a class="self-link" href="#pitfalls"></a></h2>
   <p>Users may want to write code like this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>foo</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-></span><span class="line-no" data-line="3"></span><span class="line">      <c- nf>a</c-><c- p>().</c-><c- n>and_then</c-><c- p>(</c-><c- n>b</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">         <c- p>.</c-><c- n>and_then</c-><c- p>(</c-><c- n>get_func</c-><c- p>(</c-><c- n>i</c-><c- p>));</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>}</c-></span></pre>
   <p>The problem with this is <code class="highlight"><c- n>get_func</c-></code> will be called regardless of whether <code class="highlight"><c- n>b</c-></code> returns an empty <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>optional</c-></code> or not. If it has side effects, then this may not be what the user wants.</p>
   <p>One possible solution to this would be to add an additional function, <code class="highlight"><c- n>bind_with</c-></code> which will take a callable which provides what you want to bind to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>foo</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-></span><span class="line-no" data-line="3"></span><span class="line">      <c- nf>a</c-><c- p>().</c-><c- n>and_then</c-><c- p>(</c-><c- n>b</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">         <c- p>.</c-><c- n>bind_with</c-><c- p>([</c-><c- n>i</c-><c- p>](){</c-><c- k>return</c-> <c- n>get_func</c-><c- p>(</c-><c- n>i</c-><c- p>)});</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- p>}</c-></span></pre>
   <h3 class="heading settled" data-level="11.1" id="other-solutions"><span class="secno">11.1. </span><span class="content">Other solutions</span><a class="self-link" href="#other-solutions"></a></h3>
   <p>There is a proposal for adding a <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0650r0.pdf">general monadic interface</a> to C++. Unfortunately doing the kind of composition described above would be very verbose with the current proposal without some kind of Haskell-style <code class="highlight"><c- k>do</c-></code> notation. The code for my first solution above would look like this:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>get_cute_cat</c-><c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-></span><span class="line-no" data-line="3"></span><span class="line">      <c- n>functor</c-><c- o>::</c-><c- n>map</c-><c- p>(</c-></span><span class="line-no" data-line="4"></span><span class="line">        <c- n>functor</c-><c- o>::</c-><c- n>map</c-><c- p>(</c-></span><span class="line-no" data-line="5"></span><span class="line">          <c- n>monad</c-><c- o>::</c-><c- n>bind</c-><c- p>(</c-></span><span class="line-no" data-line="6"></span><span class="line">            <c- n>monad</c-><c- o>::</c-><c- n>bind</c-><c- p>(</c-><c- n>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>),</c-></span><span class="line-no" data-line="7"></span><span class="line">              <c- n>add_bow_tie</c-><c- p>),</c-></span><span class="line-no" data-line="8"></span><span class="line">            <c- n>make_eyes_sparkle</c-><c- p>),</c-></span><span class="line-no" data-line="9"></span><span class="line">         <c- n>make_smaller</c-><c- p>),</c-></span><span class="line-no" data-line="10"></span><span class="line">      <c- n>add_rainbow</c-><c- p>);</c-></span><span class="line-no" data-line="11"></span><span class="line"><c- p>}</c-></span></pre>
   <p>My proposal is not necessarily an alternative to this proposal; compatibility between the two could be ensured and the generic proposal could use my proposal as part of its implementation. This would allow users to use both the generic syntax for flexibility and extensibility, and the member-function syntax for brevity and clarity.</p>
   <p>If <code class="highlight"><c- k>do</c-></code> notation or <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0301r1.html">unified call syntax</a> is accepted, then my proposal may not be necessary, as use of the generic monadic functionality would allow the same or similarly concise syntax.</p>
   <p>Another option would be to use a ranges-style interface for the general monadic interface:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- n>std</c-><c- o>::</c-><c- n>optional</c-><c- o>&lt;</c-><c- b>int</c-><c- o>></c-> <c- n>get_cute_cat</c-><c- p>(</c-><c- k>const</c-> <c- n>image</c-><c- o>&amp;</c-> <c- n>img</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line">    <c- k>return</c-> <c- nf>crop_to_cat</c-><c- p>(</c-><c- n>img</c-><c- p>)</c-></span><span class="line-no" data-line="3"></span><span class="line">         <c- o>|</c-> <c- n>monad</c-><c- o>::</c-><c- n>bind</c-><c- p>(</c-><c- n>add_bow_tie</c-><c- p>)</c-></span><span class="line-no" data-line="4"></span><span class="line">         <c- o>|</c-> <c- n>monad</c-><c- o>::</c-><c- n>bind</c-><c- p>(</c-><c- n>make_eyes_sparkle</c-><c- p>)</c-></span><span class="line-no" data-line="5"></span><span class="line">         <c- o>|</c-> <c- n>functor</c-><c- o>::</c-><c- n>map</c-><c- p>(</c-><c- n>make_smaller</c-><c- p>)</c-></span><span class="line-no" data-line="6"></span><span class="line">         <c- o>|</c-> <c- n>functor</c-><c- o>::</c-><c- n>map</c-><c- p>(</c-><c- n>add_rainbow</c-><c- p>);</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- p>}</c-></span></pre>
   <h3 class="heading settled" data-level="11.2" id="interaction-with-other-proposals"><span class="secno">11.2. </span><span class="content">Interaction with other proposals</span><a class="self-link" href="#interaction-with-other-proposals"></a></h3>
   <p><a href="https://wg21.link/p0847">p0847</a> would ease implementation and solve the issue of SFINAE-friendliness for <code class="highlight"><c- n>transform</c-></code> and <code class="highlight"><c- n>and_then</c-></code>.</p>
   <p>There is a proposal for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r2.pdf">std::expected</a> which would benefit from many of these same ideas. If the idea to add monadic interfaces to standard library classes on a case-by-case basis is chosen rather than a unified non-member function interface, then compatibility between this proposal and the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>expected</c-></code> one should be maintained.</p>
   <p>Mapping functions which return <code class="highlight"><c- b>void</c-></code> can be supported, but is a pain to implement since <code class="highlight"><c- b>void</c-></code> is not a regular type. If the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0146r1.html">Regular Void</a> proposal was accepted, implementation would be simpler and the results of the operation would conform to users' expectations better.</p>
   <p>Any proposals which make lambdas or overload sets easier to write and pass around will greatly improve this proposal. In particular, proposals for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3617.htm">lift operators</a> and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r0.html">abbreviated lambdas</a> would ensure that the clean style is preserved in the face of many anonymous functions and overloads.</p>
   <h2 class="heading settled" data-level="12" id="implementation-experience"><span class="secno">12. </span><span class="content">Implementation experience</span><a class="self-link" href="#implementation-experience"></a></h2>
   <p>This proposal has been implemented <a href="https://github.com/TartanLlama/monadic-optional">here</a>.</p>
   <hr>
   <h2 class="heading settled" data-level="13" id="proposed-wording"><span class="secno">13. </span><span class="content">Proposed Wording</span><a class="self-link" href="#proposed-wording"></a></h2>
   <h3 class="heading settled" data-level="13.1" id="add-feature-test-macro-to-table-36-in-supportlimitsgeneral"><span class="secno">13.1. </span><span class="content">Add feature test macro to Table 36 in [support.limits.general]</span><a class="self-link" href="#add-feature-test-macro-to-table-36-in-supportlimitsgeneral"></a></h3>
   <table>
    <tbody>
     <tr>
      <td><b>Macro name</b>
      <td><b>Value</b>
      <td><b>Header(s)</b>
     <tr>
      <td> ... 
      <td> ... 
      <td> ... 
     <tr>
      <td>_­_­cpp_­lib_­memory_­resource 
      <td>201603L 
      <td>&lt;memory_resource> 
     <tr>
      <td style="background: palegreen;">__cpp_lib_monadic_optional 
      <td style="background: palegreen;">201907L 
      <td style="background: palegreen;">&lt;optional> 
     <tr>
      <td>__cpp_lib_node_extract 
      <td>201606L 
      <td>&lt;map> &lt;set> &lt;unordered_map> &lt;unordered_set> 
     <tr>
      <td> ... 
      <td> ... 
      <td> ... 
   </table>
   <h3 class="heading settled" data-level="13.2" id="add-declarations-for-the-monadic-operations-to-the-synopsis-of-class-template-optional-in-optionaloptional"><span class="secno">13.2. </span><span class="content">Add declarations for the monadic operations to the synopsis of class template optional in [optional.optional]</span><a class="self-link" href="#add-declarations-for-the-monadic-operations-to-the-synopsis-of-class-template-optional-in-optionaloptional"></a></h3>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- c1>//...</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>T</c-> <c- n>value_or</c-><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>T</c-> <c- n>value_or</c-><c- p>(</c-><c- n>U</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- c1>// [optional.monadic], monadic operations</c-></span><span class="line-no" data-line="5"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="7"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="8"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="9"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="10"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="11"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="12"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="13"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>optional</c-> <c- n>or_else</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="14"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>optional</c-> <c- n>or_else</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="15"></span><span class="line"><c- c1>// [optional.mod], modifiers</c-></span><span class="line-no" data-line="16"></span><span class="line"><c- b>void</c-> <c- nf>reset</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c-></span><span class="line-no" data-line="17"></span><span class="line"><c- c1>//...</c-></span></pre>
   <h3 class="heading settled" data-level="13.3" id="add-new-subclause-monadic-operations-optionalmonadic-between-optionalobserve-and-optionalmod"><span class="secno">13.3. </span><span class="content">Add new subclause "Monadic operations [optional.monadic]" between [optional.observe] and [optional.mod]</span><a class="self-link" href="#add-new-subclause-monadic-operations-optionalmonadic-between-optionalobserve-and-optionalmod"></a></h3>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p>Let <code class="highlight"><c- n>U</c-></code> be <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- k>decltype</c-><c- p>(</c-><c- n>value</c-><c- p>())</c-><c- o>></c-></code>.</p>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>value</c-><c- p>())</c-><c- o>></c-></code>.</p>
    <p><em>Mandates</em>: <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code> is a specialization of <code class="highlight"><c- n>optional</c-></code>.</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- nf>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>),</c-> <c- n>value</c-><c- p>());</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>and_then</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p>Let <code class="highlight"><c- n>U</c-></code> be <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- k>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>()))</c-><c- o>></c-></code>.</p>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>()))</c-><c- o>></c-></code>.</p>
    <p><em>Mandates</em>: <code class="highlight"><c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code> is a specialization of <code class="highlight"><c- n>optional</c-></code>.</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- nf>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>()));</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>remove_cvref_t</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p>Let <code class="highlight"><c- n>U</c-></code> be <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- k>decltype</c-><c- p>(</c-><c- n>value</c-><c- p>())</c-><c- o>></c-></code>.</p>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>value</c-><c- p>())</c-><c- o>></c-></code>.</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>(</c-><c- n>in_place</c-><c- p>,</c-> <c- n>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>),</c-> <c- n>value</c-><c- p>()));</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span><span class="line-no" data-line="2"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- k>auto</c-> <c- n>transform</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p>Let <code class="highlight"><c- n>U</c-></code> be <code class="highlight"><c- n>invoke_result_t</c-><c- o>&lt;</c-><c- n>F</c-><c- p>,</c-> <c- k>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>()))</c-><c- o>></c-></code>.</p>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;</c-><c- k>decltype</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>()))</c-><c- o>></c-></code>.</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>(</c-><c- n>in_place</c-><c- p>,</c-> <c- n>invoke</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>),</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- n>value</c-><c- p>())));</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>optional</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-><c- p>();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>optional</c-> <c- n>or_else</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;></c-></code>.</p>
    <p><em>Expects</em>: <code class="highlight"><c- n>T</c-></code> meets the <em>Cpp17CopyConstructible</em> requirements (Table 27).</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- o>*</c-><c- k>this</c-><c- p>;</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>template</c-> <c- o>&lt;</c-><c- k>class</c-> <c- nc>F</c-><c- o>></c-> <c- k>constexpr</c-> <c- n>optional</c-> <c- n>or_else</c-><c- p>(</c-><c- n>F</c-><c- o>&amp;&amp;</c-> <c- n>f</c-><c- p>)</c-> <c- o>&amp;&amp;</c-><c- p>;</c-></span></pre>
   <blockquote>
    <p><em>Constraints</em>: <code class="highlight"><c- n>F</c-></code> models <code class="highlight"><c- n>invocable</c-><c- o>&lt;></c-></code>.</p>
    <p><em>Expects</em>: <code class="highlight"><c- n>T</c-></code> meets the <em>Cpp17CopyConstructible</em> requirements (Table 27).</p>
    <p><em>Effects</em>: Equivalent to:</p>
<pre class="highlight line-numbered"><span class="line-no" data-line="1"></span><span class="line"><c- k>if</c-> <c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>)</c-> <c- p>{</c-></span><span class="line-no" data-line="2"></span><span class="line"> <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>move</c-><c- p>(</c-><c- o>*</c-><c- k>this</c-><c- p>);</c-></span><span class="line-no" data-line="3"></span><span class="line"><c- p>}</c-></span><span class="line-no" data-line="4"></span><span class="line"><c- k>else</c-> <c- p>{</c-></span><span class="line-no" data-line="5"></span><span class="line"> <c- k>return</c-> <c- n>std</c-><c- o>::</c-><c- n>forward</c-><c- o>&lt;</c-><c- n>F</c-><c- o>></c-><c- p>(</c-><c- n>f</c-><c- p>)();</c-></span><span class="line-no" data-line="6"></span><span class="line"><c- p>}</c-></span></pre>
   </blockquote>
   <hr>
   <h3 class="heading settled" data-level="13.4" id="acknowledgements"><span class="secno">13.4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h3>
   <p>Thank you to Michael Wong and Chris Di Bella for representing this paper to the committee. Thanks to Kenneth Benzie, Vittorio Romeo, Jonathan Müller, Adi Shavit, Nicol Bolas, Vicente Escribá, Barry Revzin, Tim Song, and especially Casey Carter for review and suggestions.</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>