<!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>P0701r0: Back to the std2::future</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

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

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

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

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

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

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

	del { color: red !important;  background-color: #FFB0B0; text-decoration: line-through; }
	ins { color: #080 !important; background-color: #B0FFB0; text-decoration: none;         }

	del code, del pre, .del code, .del pre, code del, pre del, code .del, pre .del { background-color: #FFB0B0 !important; text-decoration: line-through; }
	ins code, ins pre, .ins code, .ins pre, code ins, pre ins, code .ins, pre .ins { background-color: #B0FFB0 !important; text-decoration: none;         }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

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

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

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

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

	blockquote {
		border-color: silver;
	}

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

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

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

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

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

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

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

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

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

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

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

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

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

	.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%;
	}

	: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; }
	}
	@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; }
	}
	body.toc-sidebar #toc :not(li) > .toc              { margin-left:  4rem; }
	body.toc-sidebar #toc .toc .secno                  { margin-left: -4rem; }
	body.toc-sidebar #toc .toc > li li li              { margin-left:  1rem; }
	body.toc-sidebar #toc .toc > li li li .secno       { margin-left: -5rem; }
	body.toc-sidebar #toc .toc > li li li li .secno    { margin-left: -6rem; }
	body.toc-sidebar #toc .toc > li li li li li .secno { margin-left: -7rem; }

	.toc li {
		clear: both;
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

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

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

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

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
  <meta content="Bikeshed 1.0.0" name="generator">
<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-hidedel */

            #hidedel:checked ~ del, #hidedel:checked ~ * del { display:none; }
            #hidedel ~ #hidedel-label::before, #hidedel ~ * #hidedel-label::before { content: "☐ "; }
            #hidedel:checked ~ #hidedel-label::before, #hidedel:checked ~ * #hidedel-label::before { content: "☑ "; }
        </style>
<style>/* style-selflinks */

            .heading, .issue, .note, .example, li, dt {
                position: relative;
            }
            a.self-link {
                position: absolute;
                top: 0;
                left: calc(-1 * (3.5rem - 26px));
                width: calc(3.5rem - 26px);
                height: 2em;
                text-align: center;
                border: none;
                transition: opacity .2s;
                opacity: .5;
            }
            a.self-link:hover {
                opacity: 1;
            }
            .heading > a.self-link {
                font-size: 83%;
            }
            li > a.self-link {
                left: calc(-1 * (3.5rem - 26px) - 2em);
            }
            dfn > a.self-link {
                top: auto;
                left: auto;
                opacity: 0;
                width: 1.5em;
                height: 1.5em;
                background: gray;
                color: white;
                font-style: normal;
                transition: opacity .2s, background-color .2s, color .2s;
            }
            dfn:hover > a.self-link {
                opacity: 1;
            }
            dfn > a.self-link:hover {
                color: black;
            }

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

            body {
                counter-reset: example figure issue;
            }
            .issue {
                counter-increment: issue;
            }
            .issue:not(.no-marker)::before {
                content: "Issue " counter(issue);
            }

            .example {
                counter-increment: example;
            }
            .example:not(.no-marker)::before {
                content: "Example " counter(example);
            }
            .invalid.example:not(.no-marker)::before,
            .illegal.example:not(.no-marker)::before {
                content: "Invalid Example" counter(example);
            }

            figcaption {
                counter-increment: figure;
            }
            figcaption:not(.no-marker)::before {
                content: "Figure " counter(figure) " ";
            }</style>
<style>/* style-autolinks */

            .css.css, .property.property, .descriptor.descriptor {
                color: #005a9c;
                font-size: inherit;
                font-family: inherit;
            }
            .css::before, .property::before, .descriptor::before {
                content: "‘";
            }
            .css::after, .property::after, .descriptor::after {
                content: "’";
            }
            .property, .descriptor {
                /* Don't wrap property and descriptor names */
                white-space: nowrap;
            }
            .type { /* CSS value <type> */
                font-style: italic;
            }
            pre .property::before, pre .property::after {
                content: "";
            }
            [data-link-type="property"]::before,
            [data-link-type="propdesc"]::before,
            [data-link-type="descriptor"]::before,
            [data-link-type="value"]::before,
            [data-link-type="function"]::before,
            [data-link-type="at-rule"]::before,
            [data-link-type="selector"]::before,
            [data-link-type="maybe"]::before {
                content: "‘";
            }
            [data-link-type="property"]::after,
            [data-link-type="propdesc"]::after,
            [data-link-type="descriptor"]::after,
            [data-link-type="value"]::after,
            [data-link-type="function"]::after,
            [data-link-type="at-rule"]::after,
            [data-link-type="selector"]::after,
            [data-link-type="maybe"]::after {
                content: "’";
            }

            [data-link-type].production::before,
            [data-link-type].production::after,
            .prod [data-link-type]::before,
            .prod [data-link-type]::after {
                content: "";
            }

            [data-link-type=element],
            [data-link-type=element-attr] {
                font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
                font-size: .9em;
            }
            [data-link-type=element]::before { content: "<" }
            [data-link-type=element]::after  { content: ">" }

            [data-link-type=biblio] {
                white-space: pre;
            }</style>
<style>/* style-syntax-highlighting */

        .highlight:not(.idl) { background: hsl(24, 20%, 95%); }
        code.highlight { padding: .1em; border-radius: .3em; }
        pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
        .highlight .c { color: #708090 } /* Comment */
        .highlight .k { color: #990055 } /* Keyword */
        .highlight .l { color: #000000 } /* Literal */
        .highlight .n { color: #0077aa } /* Name */
        .highlight .o { color: #999999 } /* Operator */
        .highlight .p { color: #999999 } /* Punctuation */
        .highlight .cm { color: #708090 } /* Comment.Multiline */
        .highlight .cp { color: #708090 } /* Comment.Preproc */
        .highlight .c1 { color: #708090 } /* Comment.Single */
        .highlight .cs { color: #708090 } /* Comment.Special */
        .highlight .kc { color: #990055 } /* Keyword.Constant */
        .highlight .kd { color: #990055 } /* Keyword.Declaration */
        .highlight .kn { color: #990055 } /* Keyword.Namespace */
        .highlight .kp { color: #990055 } /* Keyword.Pseudo */
        .highlight .kr { color: #990055 } /* Keyword.Reserved */
        .highlight .kt { color: #990055 } /* Keyword.Type */
        .highlight .ld { color: #000000 } /* Literal.Date */
        .highlight .m { color: #000000 } /* Literal.Number */
        .highlight .s { color: #a67f59 } /* Literal.String */
        .highlight .na { color: #0077aa } /* Name.Attribute */
        .highlight .nc { color: #0077aa } /* Name.Class */
        .highlight .no { color: #0077aa } /* Name.Constant */
        .highlight .nd { color: #0077aa } /* Name.Decorator */
        .highlight .ni { color: #0077aa } /* Name.Entity */
        .highlight .ne { color: #0077aa } /* Name.Exception */
        .highlight .nf { color: #0077aa } /* Name.Function */
        .highlight .nl { color: #0077aa } /* Name.Label */
        .highlight .nn { color: #0077aa } /* Name.Namespace */
        .highlight .py { color: #0077aa } /* Name.Property */
        .highlight .nt { color: #669900 } /* Name.Tag */
        .highlight .nv { color: #222222 } /* Name.Variable */
        .highlight .ow { color: #999999 } /* Operator.Word */
        .highlight .mb { color: #000000 } /* Literal.Number.Bin */
        .highlight .mf { color: #000000 } /* Literal.Number.Float */
        .highlight .mh { color: #000000 } /* Literal.Number.Hex */
        .highlight .mi { color: #000000 } /* Literal.Number.Integer */
        .highlight .mo { color: #000000 } /* Literal.Number.Oct */
        .highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
        .highlight .sc { color: #a67f59 } /* Literal.String.Char */
        .highlight .sd { color: #a67f59 } /* Literal.String.Doc */
        .highlight .s2 { color: #a67f59 } /* Literal.String.Double */
        .highlight .se { color: #a67f59 } /* Literal.String.Escape */
        .highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
        .highlight .si { color: #a67f59 } /* Literal.String.Interpol */
        .highlight .sx { color: #a67f59 } /* Literal.String.Other */
        .highlight .sr { color: #a67f59 } /* Literal.String.Regex */
        .highlight .s1 { color: #a67f59 } /* Literal.String.Single */
        .highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
        .highlight .vc { color: #0077aa } /* Name.Variable.Class */
        .highlight .vg { color: #0077aa } /* Name.Variable.Global */
        .highlight .vi { color: #0077aa } /* Name.Variable.Instance */
        .highlight .il { color: #000000 } /* Literal.Number.Integer.Long */
        </style>
 <body class="h-entry">
  <input id="hidedel" style="display:none" type="checkbox">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P0701r0<br>Back to the std2::future</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2017-06-18">18 June 2017</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P0701r0">http://wg21.link/P0701r0</a>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:brycelelbach@gmail.com">Bryce Adelstein Lelbach</a> (<span class="p-org org">Lawrence Berkeley National Laboratory</span>)
     <dt>Audience:
     <dd>SG1
     <dt>Toggle Diffs:
     <dd>
      <label for="hidedel" id="hidedel-label">Hide deleted text</label>
     <dt>Project:
     <dd><span>ISO JTC1/SC22/WG21: Programming Language C++</span>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract"></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="#overview"><span class="secno">1</span> <span class="content">Overview</span></a>
    <li>
     <a href="#problems"><span class="secno">2</span> <span class="content">Problems with the Existing Design</span></a>
     <ol class="toc">
      <li><a href="#single-consumer-future-vs-multiple-consumers-shared_future"><span class="secno">2.1</span> <span class="content">Single Consumer (<code class="highlight"><span class="n">future</span></code>) vs Multiple Consumers (<code class="highlight"><span class="n">shared_future</span></code>)</span></a>
      <li><a href="#concurrent-producer-consumer-s-vs-non-concurrent-producer-consumer-s"><span class="secno">2.2</span> <span class="content">Concurrent Producer/Consumer(s) vs Non-Concurrent Producer/Consumer(s)</span></a>
      <li>
       <a href="#coupling-with-scheduling-and-genericity"><span class="secno">2.3</span> <span class="content">Coupling with Scheduling and Genericity</span></a>
       <ol class="toc">
        <li><a href="#future-promise-are-too-tightly-coupled-to-scheduling"><span class="secno">2.3.1</span> <span class="content"><code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> are Too Tightly Coupled to Scheduling</span></a>
        <li><a href="#future-promise-are-not-tightly-enough-coupled-to-scheduling"><span class="secno">2.3.2</span> <span class="content"><code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> are Not Tightly Enough Coupled to Scheduling</span></a>
        <li><a href="#where-does-a-then-continuation-run"><span class="secno">2.3.3</span> <span class="content">Where Does a <code class="highlight"><span class="p">.</span><span class="n">then</span></code> Continuation Run?</span></a>
       </ol>
      <li>
       <a href="#composability"><span class="secno">2.4</span> <span class="content">Composability</span></a>
       <ol class="toc">
        <li><a href="#passing-futures-to-then-continuations-is-unwieldy"><span class="secno">2.4.1</span> <span class="content">Passing <code class="highlight"><span class="n">future</span></code>s to <code class="highlight"><span class="p">.</span><span class="n">then</span></code> Continuations is Unwieldy</span></a>
        <li><a href="#when_all-and-when_any-return-types-are-unwieldy"><span class="secno">2.4.2</span> <span class="content"><code class="highlight"><span class="n">when_all</span></code> and <code class="highlight"><span class="n">when_any</span></code> Return Types are Unwieldy</span></a>
        <li><a href="#immediate-values"><span class="secno">2.4.3</span> <span class="content">Immediate Values</span></a>
       </ol>
     </ol>
    <li><a href="#hpx-berkeley-inspired-future"><span class="secno">3</span> <span class="content">HPX/Berkeley Inspired Future</span></a>
    <li><a href="#acknowledgements"><span class="secno">4</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="overview"><span class="secno">1. </span><span class="content">Overview</span><a class="self-link" href="#overview"></a></h2>
   <p>C++11 introduced asynchronous programming facilities:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">shared_future</span></code> - Provides access to an asynchronous value.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">promise</span></code> -  Produces an asynchronous value.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">async</span></code> - Runs a function asynchronously, producing an asynchronous value.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">packaged_task</span></code> - Packages a function to store its result as an asynchronous value.</p>
   </ul>
   <p>The Concurrency TS v1 extended these interfaces, adding:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">future</span><span class="o">:</span><span class="o">:</span><span class="n">then</span></code> - Attach continuations to asynchronous values.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">when_all</span></code>/<code class="highlight"><span class="n">when_any</span></code> - Combine and select asynchronous values.</p>
   </ul>
   <p>I think many of us would agree with the following statements regarding these features:</p>
   <ul>
    <li data-md="">
     <p>The programming model is correct.</p>
    <li data-md="">
     <p>The current design is fatally flawed.</p>
   </ul>
   <p><strong>E.g. We want composable futures, but the ones we have today are broken.</strong> Fixing
what we have today would be challenging without introducing backwards incompatible changes.
So, the premise of this paper is that we should introduce new asynchronous
programming primitives in conjunction with executors <a data-link-type="biblio" href="#biblio-p0443r1">[P0443r1]</a> instead of
trying to "fix" what we have today.</p>
   <p>This paper has two sections:</p>
   <ul>
    <li data-md="">
     <p>First, I enumerate what I perceive to be problems with the current design.</p>
    <li data-md="">
     <p>Then, I briefly describe a future design I’ve been toying around with, based
some existing libraries I work on.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="problems"><span class="secno">2. </span><span class="content">Problems with the Existing Design</span><a class="self-link" href="#problems"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="single-consumer-future-vs-multiple-consumers-shared_future"><span class="secno">2.1. </span><span class="content">Single Consumer (<code class="highlight"><span class="n">future</span></code>) vs Multiple Consumers (<code class="highlight"><span class="n">shared_future</span></code>)</span><a class="self-link" href="#single-consumer-future-vs-multiple-consumers-shared_future"></a></h3>
   <p>When retrieving a value from a <code class="highlight"><span class="n">future</span></code> (<code class="highlight"><span class="p">.</span><span class="n">get</span></code>), we have two options:</p>
   <ul>
    <li data-md="">
     <p>Move the value out of the shared state and return it, preventing any
  additional retrievals and avoiding copies. <code class="highlight"><span class="n">future</span></code> has these semantics (33.6.7 [<strong>futures.unique_futures</strong>] p14-18).</p>
    <li data-md="">
     <p>Return a reference, constant reference or copy of the value, allowing
  additional retrievals at the cost of copies. <code class="highlight"><span class="n">shared_future</span></code> has these semantics (returns a reference or constant
  reference; 33.6.5 [<strong>futures.shared_futures</strong>] p16-20).</p>
   </ul>
   <p>The difference in semantics goes beyond <code class="highlight"><span class="p">.</span><span class="n">get</span></code>; <code class="highlight"><span class="n">future</span></code> is not <code class="highlight"><span class="n">Copyable</span></code>,
while <code class="highlight"><span class="n">shared_future</span></code> is <code class="highlight"><span class="n">Copyable</span></code>.</p>
   <p>What happens if you call <code class="highlight"><span class="p">.</span><span class="n">get</span></code> twice on a <code class="highlight"><span class="n">future</span></code>?</p>
<pre class="highlight"><span class="n">promise</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">p</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">f</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">get_future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">set_value</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">)</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>The answer is undefined behavior. Today:</p>
   <ul>
    <li data-md="">
     <p><a href="https://wandbox.org/permlink/1jlH8hMtU3npBOIZ">libc++ seg faults.</a>.</p>
    <li data-md="">
     <p><a href="https://wandbox.org/permlink/UeMDUvDaOl4ZFI8l">libstdc++ throws an exception.</a>.</p>
    <li data-md="">
     <p><a href="https://wandbox.org/permlink/BrZs8TniwcjxXn3P">Boost prints "hello" and then "" (non-conforming).</a>.</p>
   </ul>
   <p>While I do find undefined behavior and the implementation divergence that stems
  from it troubling, I think there’s a bigger problem. <code class="highlight"><span class="p">.</span><span class="n">get</span></code> is not a read-only accessor; it is a destructive, mutating operation.
This is unintuitive!
The user didn’t ask to move out of <code class="highlight"><span class="n">f</span></code>, e.g. they didn’t write:</p>
<pre class="highlight"><span class="n">promise</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">p</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">f</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">get_future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">set_value</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">)</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>By using <code class="highlight"><span class="n">shared_future</span></code> instead of <code class="highlight"><span class="n">future</span></code> in the above examples, we get the
  behavior we desire.</p>
   <p>We have the same limitation with <code class="highlight"><span class="p">.</span><span class="n">then</span></code>. A <code class="highlight"><span class="n">future</span></code> may only have a single
  continuation attached to it. E.g. the following is undefined behavior:</p>
<pre class="highlight"><span class="n">promise</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">></span> <span class="n">p</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">></span> <span class="n">f</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">get_future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">set_value</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>

<span class="n">future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">a</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">></span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">}</span><span class="p">)</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">b</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">></span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">2</span><span class="p">;</span> <span class="p">}</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>Again, the above example works fine if you use <code class="highlight"><span class="n">shared_future</span></code>.</p>
   <p>Alternatively, we could have a <code class="highlight"><span class="n">future</span></code> like this:</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">struct</span> <span class="n">future</span>
<span class="p">{</span>
  <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">get</span><span class="p">(</span><span class="p">)</span> <span class="k">const</span><span class="o">&amp;</span><span class="p">;</span>
  <span class="n">T</span><span class="o">&amp;</span> <span class="n">get</span><span class="p">(</span><span class="p">)</span> <span class="o">&amp;</span><span class="p">;</span>
  <span class="n">T</span> <span class="nf">get</span><span class="p">(</span><span class="p">)</span> <span class="o">&amp;</span><span class="o">&amp;</span><span class="p">;</span>

  <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">func</span><span class="p">)</span> <span class="o">&amp;</span><span class="p">;</span>
  <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">func</span><span class="p">)</span> <span class="o">&amp;</span><span class="o">&amp;</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>
</pre>
   <p>Such a <code class="highlight"><span class="n">future</span></code> would still support non-<code class="highlight"><span class="n">Copyable</span></code> types, as long as you don’t
try to copy the <code class="highlight"><span class="n">future</span></code>. <code class="highlight"><span class="p">.</span><span class="n">then</span></code> continuations that take their <code class="highlight"><span class="n">future</span></code> by
value are still optimal, since the non-rvalue-reference overloads return by
reference:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">f</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>

<span class="n">move</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span>
  <span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">v</span><span class="p">)</span> <span class="c1">// v is move constructed from f.
</span>  <span class="p">{</span>
    <span class="k">return</span> <span class="n">v</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="c1">// T&amp; get() &amp; called; no copy.
</span>  <span class="p">}</span>
<span class="p">)</span><span class="p">;</span>
</pre>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">g</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>

<span class="n">g</span><span class="p">.</span><span class="n">then</span><span class="p">(</span>
  <span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">v</span><span class="p">)</span> <span class="c1">// v is copy constructed from f.
</span>  <span class="p">{</span>
    <span class="k">return</span> <span class="n">v</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="c1">// T&amp; get() &amp; called; no copy.
</span>  <span class="p">}</span>
<span class="p">)</span><span class="p">;</span>
<span class="n">g</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>Alternatively, a more explicit interface for operations that move out of the
shared state could be adopted:</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">struct</span> <span class="n">future</span>
<span class="p">{</span>
  <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">get</span><span class="p">(</span><span class="p">)</span> <span class="k">const</span><span class="o">&amp;</span><span class="p">;</span>
  <span class="n">T</span><span class="o">&amp;</span> <span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>

  <span class="n">T</span> <span class="nf">move</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>

  <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">func</span><span class="p">)</span><span class="p">;</span>

  <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">move_then</span><span class="p">(</span><span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">func</span><span class="p">)</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>
</pre>
   <p>By combining <code class="highlight"><span class="n">future</span></code> and <code class="highlight"><span class="n">shared_future</span></code> into a single type, we can move away
from single consumer by default (which is often not what users want) while
still providing the capability to move out of the shared state upon request.</p>
   <p>Admittedly, both of my suggested approaches have downsides as well, when
compared with the current model. With both approaches, you can move out of the
shared state while other consumers (e.g. other <code class="highlight"><span class="n">future</span></code>s pointing to the same
shared state) still exist. The unique ownership model of <code class="highlight"><span class="n">future</span></code> makes this
much harder to do today.</p>
   <h3 class="heading settled" data-level="2.2" id="concurrent-producer-consumer-s-vs-non-concurrent-producer-consumer-s"><span class="secno">2.2. </span><span class="content">Concurrent Producer/Consumer(s) vs Non-Concurrent Producer/Consumer(s)</span><a class="self-link" href="#concurrent-producer-consumer-s-vs-non-concurrent-producer-consumer-s"></a></h3>
   <p>Both <code class="highlight"><span class="n">future</span></code> and <code class="highlight"><span class="n">shared_future</span></code> are designed to support scenarios where the
producer of an asynchronous value is a different thread of execution than
the consumer of an asynchronous value and both threads may concurrently access
the shared state.</p>
   <p>While this is the common case for <code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">shared_future</span></code>s when they are used
  in asynchronous tasking systems (e.g. <code class="highlight"><span class="n">async</span></code>-like interfaces), it pessimizes
  users who want to produce and consume asynchronous values within a single
  thread (e.g. lazy evaluation).
This is a common pattern in applications interacting with a network or with
  user input. <code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">shared_future</span></code> are typically implemented using heavyweight
  synchronization primitives (condition variable + mutex), and those who do not
  need the synchronization are always forced to pay these costs.</p>
   <h3 class="heading settled" data-level="2.3" id="coupling-with-scheduling-and-genericity"><span class="secno">2.3. </span><span class="content">Coupling with Scheduling and Genericity</span><a class="self-link" href="#coupling-with-scheduling-and-genericity"></a></h3>
   <h4 class="heading settled" data-level="2.3.1" id="future-promise-are-too-tightly-coupled-to-scheduling"><span class="secno">2.3.1. </span><span class="content"><code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> are Too Tightly Coupled to Scheduling</span><a class="self-link" href="#future-promise-are-too-tightly-coupled-to-scheduling"></a></h4>
   <p>One issue that has come up during the evolution of executors is the need for a
future concept, since some executors will need their own future type.</p>
   <p>Why?</p>
   <p>Notionally, a <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span></code> is a <code class="highlight"><span class="n">variant</span></code> of <code class="highlight"><span class="n">T</span></code> and <code class="highlight"><span class="n">exception_ptr</span></code>, and a state.
What prevents different executors from using the same fundamental <code class="highlight"><span class="n">future</span></code> type.</p>
   <p>The answer is that our current <code class="highlight"><span class="n">future</span></code> is tightly coupled with one particular
scheduling mechanism today:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">future</span></code> needs a way to <strong>block</strong> so that <code class="highlight"><span class="p">.</span><span class="n">get</span></code> and <code class="highlight"><span class="p">.</span><span class="n">wait</span><span class="o">*</span></code> can be implemented.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">future</span></code>'s destructor needs to block if the shared state was created by <code class="highlight"><span class="n">async</span></code>, the shared state is not ready and this <code class="highlight"><span class="n">future</span></code> was holding the last
reference to the shared state (I will refrain from discussing this particular
subject in detail; I hope we can all agree that conditionally blocking in the
destructor is confusing and not ideal).</p>
   </ul>
   <p>Blocking is the problem here.
Each executor type may have a different way to block.
A typical implementation of <code class="highlight"><span class="n">future</span></code> uses <code class="highlight"><span class="n">condition_variable</span></code> and <code class="highlight"><span class="n">mutex</span></code> for synchronization and blocking.</p>
   <p>For a parallel tasking system like HPX, these primitives are problematic,
  because they block at the OS-thread level, not the task level, and thus
  interfere with our userspace scheduling.
Thus, we need an <code class="highlight"><span class="n">hpx</span><span class="o">:</span><span class="o">:</span><span class="n">future</span></code>.
Libraries that manage asynchronous operations on accelerators or GPUs will also
need their own <code class="highlight"><span class="n">future</span></code> types.</p>
   <p>Likewise, for a networking library, we might need to check for new messages and
  process outstanding work items while blocking - otherwise, we might never 
  receive and process the message that will change the state of the future we
  are blocking on:</p>
<pre class="highlight">  <span class="n">T</span> <span class="nf">get</span><span class="p">(</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">ready</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="c1">// Poll my endpoint to see if I have any messages;
</span>      <span class="c1">// If so, enqueue the tasks described by the messages.
</span>      <span class="n">check_messages</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>

      <span class="c1">// If my task queue is not empty, dequeue some tasks
</span>      <span class="c1">// and execute them.
</span>      <span class="n">run_tasks</span><span class="p">(</span><span class="p">)</span><span class="p">;</span> 
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">shared_state</span><span class="o">-</span><span class="o">></span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
  <span class="p">}</span>
</pre>
   <p>Thus, we need our own <code class="highlight"><span class="n">future</span></code> type.</p>
   <p>If we could either remove blocking interfaces from <code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> or
  parameterize the blocking mechanism, I suspect we could create a <code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> that could be used by most executors.
There is still the issue of synchronizing the shared state between consumers and
  the producer, but this could be done with atomics.
I believe this would be fine for parallel tasking systems, but atomics would
  still introduce unnecessary overheads for the non-concurrent producer/consumer
  use case.</p>
   <h4 class="heading settled" data-level="2.3.2" id="future-promise-are-not-tightly-enough-coupled-to-scheduling"><span class="secno">2.3.2. </span><span class="content"><code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> are Not Tightly Enough Coupled to Scheduling</span><a class="self-link" href="#future-promise-are-not-tightly-enough-coupled-to-scheduling"></a></h4>
   <p>On the other hand, <code class="highlight"><span class="n">future</span></code>/<code class="highlight"><span class="n">promise</span></code> are not enough coupled to scheduling. <code class="highlight"><span class="n">future</span></code> often serves a dual role as a handle to both a value and an implicit
  handle to the task that will produce that value.
However, there are some operations that we may wish to perform on a task, such 
  as cancellation, that are not supported by the current <code class="highlight"><span class="n">future</span></code>.</p>
   <h4 class="heading settled" data-level="2.3.3" id="where-does-a-then-continuation-run"><span class="secno">2.3.3. </span><span class="content">Where Does a <code class="highlight"><span class="p">.</span><span class="n">then</span></code> Continuation Run?</span><a class="self-link" href="#where-does-a-then-continuation-run"></a></h4>
   <p>In our current pre-executor world, it is unspecified where a <code class="highlight"><span class="p">.</span><span class="n">then</span></code> continuation will be run.
There are a number of possible answers:</p>
   <ul>
    <li data-md="">
     <p>If the shared state is ready when the continuation is set, the consumer thread
executes the continuation.</p>
    <li data-md="">
     <p>If the shared state is not ready when the continuation is set, the producer
thread executes the continuation.</p>
    <li data-md="">
     <p>Alternatively, a new thread could be created which executes the continuation.</p>
   </ul>
   <p>Executors do not entirely alleviate this problem; the question simply becomes
  "Where does a <code class="highlight"><span class="p">.</span><span class="n">then</span></code> continuation get passed to the executor?"</p>
   <p>Consider, for example, an executor that always enqueues a work item into a task
  queue associated with the current OS-thread.
If the continuation is added to the executor on the consumer thread, the consumer
  thread will execute it.
Otherwise, the producer thread will execute the continuation.
Should people simply avoid writing such executors?</p>
   <p>There is also the question of what should be done in the case that an executor
  parameter is omitted.
I favor the third option, of spawning a new thread that executes the
  continuation.</p>
   <h3 class="heading settled" data-level="2.4" id="composability"><span class="secno">2.4. </span><span class="content">Composability</span><a class="self-link" href="#composability"></a></h3>
   <h4 class="heading settled" data-level="2.4.1" id="passing-futures-to-then-continuations-is-unwieldy"><span class="secno">2.4.1. </span><span class="content">Passing <code class="highlight"><span class="n">future</span></code>s to <code class="highlight"><span class="p">.</span><span class="n">then</span></code> Continuations is Unwieldy</span><a class="self-link" href="#passing-futures-to-then-continuations-is-unwieldy"></a></h4>
   <p>The signature for <code class="highlight"><span class="p">.</span><span class="n">then</span></code> continuations in the Concurrency TS v1 is:</p>
<pre class="highlight"><span class="n">ReturnType</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="p">)</span>
</pre>
   <p>The <code class="highlight"><span class="n">future</span></code> gets passed to the continuation instead of the value so that
  continuation can handle <code class="highlight"><span class="n">future</span></code>s that contain exceptions.
The <code class="highlight"><span class="n">future</span></code> passed to the continuation is always ready; <code class="highlight"><span class="p">.</span><span class="n">get</span></code> can be used to
  retrieve the value, and will not block.
Unfortunately, this can make <code class="highlight"><span class="p">.</span><span class="n">then</span></code> quite unwieldy to work with, especially
  when you want to use existing functions that cannot be modified as
  continuations:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">f</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">f</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">abs</span><span class="p">)</span><span class="p">;</span> <span class="c1">// ERROR: No std::abs(future&lt;double>) overload.
</span><span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">f</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">abs</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span> <span class="p">}</span><span class="p">)</span><span class="p">;</span> <span class="c1">// OK.
</span></pre>
   <p><code class="highlight"><span class="n">future</span></code>s would be far more composable if <code class="highlight"><span class="p">.</span><span class="n">then</span></code> passed the value to the
  continuation instead of the future itself.
There are a few ways that exceptions could be handled if <code class="highlight"><span class="p">.</span><span class="n">then</span></code> behaved this
  way:</p>
   <ul>
    <li data-md="">
     <p>If the <code class="highlight"><span class="n">future</span></code> that the continuation is being attached to contains an exception,
the exception could be propagated to the future returned by <code class="highlight"><span class="p">.</span><span class="n">then</span></code> and the 
continuation could never run.</p>
    <li data-md="">
     <p><code class="highlight"><span class="p">.</span><span class="n">then</span></code> could invoke the continuation with the <code class="highlight"><span class="n">exception_ptr</span></code> contained in the <code class="highlight"><span class="n">future</span></code> in the event of an error if the continuation is invocable with an <code class="highlight"><span class="n">exception_ptr</span></code>.
Otherwise, the exception could be propagated as described
  above.</p>
    <li data-md="">
     <p><code class="highlight"><span class="p">.</span><span class="n">then</span></code> could take a second, optional parameter - a <code class="highlight"><span class="n">Callable</span></code> that will be
  invoked with the <code class="highlight"><span class="n">future</span></code>'s exception in the case of an error. 
Otherwise, the exception could be propagated as described above.</p>
   </ul>
   <h4 class="heading settled" data-level="2.4.2" id="when_all-and-when_any-return-types-are-unwieldy"><span class="secno">2.4.2. </span><span class="content"><code class="highlight"><span class="n">when_all</span></code> and <code class="highlight"><span class="n">when_any</span></code> Return Types are Unwieldy</span><a class="self-link" href="#when_all-and-when_any-return-types-are-unwieldy"></a></h4>
   <p><code class="highlight"><span class="n">when_all</span></code> has the following signature (Concurrency TS v1, 2.7
[<strong>futures.when_all</strong>] p2):</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">InputIterator</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">InputIterator</span><span class="o">></span><span class="o">:</span><span class="o">:</span><span class="n">value_type</span><span class="o">></span><span class="o">></span>
<span class="n">when_all</span><span class="p">(</span><span class="n">InputIterator</span> <span class="n">first</span><span class="p">,</span> <span class="n">InputIterator</span> <span class="n">last</span><span class="p">)</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Futures</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">Futures</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span>
<span class="n">when_all</span><span class="p">(</span><span class="n">Futures</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">futures</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>And <code class="highlight"><span class="n">when_any</span></code> has the following signature (Concurrency TS v1, 2.9
[<strong>futures.when_any</strong>] p2):</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Sequence</span><span class="o">></span>
<span class="k">struct</span> <span class="n">when_any_result</span>
<span class="p">{</span>
  <span class="n">std</span><span class="o">:</span><span class="o">:</span><span class="kt">size_t</span> <span class="n">index</span><span class="p">;</span>
  <span class="n">Sequence</span> <span class="n">futures</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">InputIterator</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">when_any_result</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">InputIterator</span><span class="o">></span><span class="o">:</span><span class="o">:</span><span class="n">value_type</span><span class="o">></span><span class="o">></span><span class="o">></span>
<span class="n">when_any</span><span class="p">(</span><span class="n">InputIterator</span> <span class="n">first</span><span class="p">,</span> <span class="n">InputIterator</span> <span class="n">last</span><span class="p">)</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Futures</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">when_any_result</span><span class="o">&lt;</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">Futures</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span><span class="o">></span>
<span class="n">when_any</span><span class="p">(</span><span class="n">Futures</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">futures</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>The TL;DR version:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">when_all</span></code> either returns a <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">></span><span class="o">></span></code> or a <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">future</span><span class="o">&lt;</span><span class="n">Ts</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span></code>.</p>
    <li data-md="">
     <p>Likewise for <code class="highlight"><span class="n">when_any</span></code>, with the added complication of the future value type
being wrapped in <code class="highlight"><span class="n">when_any_result</span></code>, which really wants to be a <code class="highlight"><span class="n">variant</span></code> instead.</p>
   </ul>
   <p>Again, the reason for the complexity here is error reporting.
If <code class="highlight"><span class="n">when_all</span></code>'s return type was simplified from <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">></span><span class="o">></span></code> to <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">></span></code>, what would we do if some of the <code class="highlight"><span class="n">future</span></code>s being combined
  threw exceptions?
One possible answer would be for <code class="highlight"><span class="p">.</span><span class="n">get</span></code> on the result of <code class="highlight"><span class="n">when_all</span></code> to throw
  something like an <code class="highlight"><span class="n">exception_list</span></code>, where each element of the list would be a <code class="highlight"><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">size_t</span><span class="p">,</span> <span class="n">exception_ptr</span><span class="o">></span></code>.
An error that occurs during the combination of the <code class="highlight"><span class="n">future</span></code>s (e.g. in <code class="highlight"><span class="n">when_all</span></code> itself) could be distinguished by using a distinct exception type.</p>
   <p>One benefit of this simplification is that it would enable this pattern:</p>
<pre class="highlight"><span class="kt">bool</span> <span class="nf">f</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">int</span><span class="p">)</span><span class="p">;</span>


<span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">a</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">b</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span>    <span class="n">c</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>

<span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span>
  <span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">double</span><span class="p">,</span> <span class="n">string</span><span class="o">></span><span class="o">></span> <span class="n">v</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">apply</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span><span class="p">;</span> <span class="c1">// f(a.get(), b.get(), c.get());
</span>  <span class="p">}</span>
<span class="p">)</span><span class="p">;</span>
</pre>
   <p>If <code class="highlight"><span class="p">.</span><span class="n">then</span></code> passed a value to the continuation instead of a <code class="highlight"><span class="n">future</span></code>, this would
  become:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span>
  <span class="p">[</span><span class="p">]</span><span class="p">(</span><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">double</span><span class="p">,</span> <span class="n">string</span><span class="o">></span> <span class="n">v</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">apply</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span><span class="p">;</span> <span class="c1">// f(a.get(), b.get(), c.get());
</span>  <span class="p">}</span>
<span class="p">)</span><span class="p">;</span>
</pre>
   <p><code class="highlight"><span class="p">.</span><span class="n">then</span></code> could be extended even further, to handle <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">Ts</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span></code> specially:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="p">;</span> <span class="c1">// f(a.get(), b.get(), c.get());
</span></pre>
   <p>Alternatively, the above example could be enabled by making <code class="highlight"><span class="n">future</span></code> variadic
and making <code class="highlight"><span class="n">when_all</span></code>'s heterogeneous signature:</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Futures</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">Futures</span><span class="o">:</span><span class="o">:</span><span class="n">value_type</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span>
<span class="n">when_all</span><span class="p">(</span><span class="n">Futures</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">futures</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p><code class="highlight"><span class="n">when_any</span></code>, clearly, can be updated to use <code class="highlight"><span class="n">variant</span></code>, which is a natural fit for
  its interface.</p>
   <p><code class="highlight"><span class="p">.</span><span class="n">then</span></code> could be extended to have <code class="highlight"><span class="n">visit</span></code> like semantics for <code class="highlight"><span class="n">when_any</span></code> <code class="highlight"><span class="n">future</span></code>s
  (e.g. <code class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">Ts</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span></code>) in the same way that <code class="highlight"><span class="p">.</span><span class="n">then</span></code> could be extended to
  have <code class="highlight"><span class="n">apply</span></code> like semantics for <code class="highlight"><span class="n">when_all</span></code>.</p>
   <h4 class="heading settled" data-level="2.4.3" id="immediate-values"><span class="secno">2.4.3. </span><span class="content">Immediate Values</span><a class="self-link" href="#immediate-values"></a></h4>
   <p>In C++11, there was no convenience function for creating a future that is ready
and contains a particular value (e.g. <strong>immediate values</strong>). You’d have to
write:</p>
<pre class="highlight"><span class="n">promise</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">p</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">a</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">get_future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">set_value</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>The Concurrency TS v1 adds such a function, <code class="highlight"><span class="n">make_ready_future</span></code> (Concurrency TS v1, 2.10 [<strong>futures.make_ready_future</strong>]):</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">a</span> <span class="o">=</span> <span class="n">make_ready_future</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>However, it is still unnecessarily verbose to work with immediate values.
  Consider:</p>
<pre class="highlight"><span class="kt">bool</span> <span class="nf">f</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">int</span><span class="p">)</span><span class="p">;</span>


<span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">a</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span>    <span class="n">c</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>

<span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">make_ready_future</span><span class="p">(</span><span class="mf">3.14</span><span class="p">)</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="cm">/* Call f. */</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>Why not allow both <code class="highlight"><span class="n">future</span></code> and non-<code class="highlight"><span class="n">future</span></code> arguments to <code class="highlight"><span class="n">when_all</span></code>?
Then we could write:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mf">3.14</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="cm">/* Call f. */</span><span class="p">)</span><span class="p">;</span>
</pre>
   <p>In combination with the direction described in the previous section, we’d be
  able to write:</p>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">></span> <span class="n">d</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mf">3.14</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="p">;</span> <span class="c1">// f(a.get(), 3.14, c.get());
</span></pre>
   <p>Additionally, with C++17 class template deduction, instead of <code class="highlight"><span class="n">make_ready_future</span></code>, we could just have a ready <code class="highlight"><span class="n">future</span></code> constructor:</p>
<pre class="highlight"><span class="k">auto</span> <span class="n">f</span> <span class="o">=</span> <span class="n">future</span><span class="p">(</span><span class="mf">3.14</span><span class="p">)</span><span class="p">;</span>
</pre>
   <h2 class="heading settled" data-level="3" id="hpx-berkeley-inspired-future"><span class="secno">3. </span><span class="content">HPX/Berkeley Inspired Future</span><a class="self-link" href="#hpx-berkeley-inspired-future"></a></h2>
   <p>This <code class="highlight"><span class="n">future</span></code> design is based on some ideas from HPX and a few projects that use <code class="highlight"><span class="n">future</span></code>s at my work place.
The goal is to create a future without blocking interfaces that can be used by
  different executors in lieu of a single unified future concept.
The design has evolved a lot in the past few weeks, so please forgive the rough
  edges.</p>
   <p>Note that <code class="highlight"><span class="n">when_any</span></code> is omitted due to time constraints; I hope to have it
  hammered out for the Toronto meeting.
This design does not surface the notion of a task, unlike Sean Parent’s design
  from stlab; I am hoping to address this (and cancellation) in the future.</p>
   <p>First, some example usage:</p>
<pre class="highlight"><span class="c1">// Ready futures.
</span><span class="k">auto</span> <span class="n">g</span> <span class="o">=</span> <span class="n">future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>                  <span class="c1">// value_type = void.
</span><span class="k">auto</span> <span class="n">h</span> <span class="o">=</span> <span class="n">future</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">)</span><span class="p">;</span>           <span class="c1">// value_type = string.
</span><span class="k">auto</span> <span class="n">i</span> <span class="o">=</span> <span class="n">future</span><span class="p">(</span><span class="s">"</span><span class="s">hello</span><span class="s">"</span><span class="p">,</span> <span class="mf">3.14</span><span class="p">,</span> <span class="mi">17</span><span class="p">)</span><span class="p">;</span> <span class="c1">// value_type = tuple&lt;string, double, int>.
</span>
<span class="c1">// Continuations.
</span><span class="k">auto</span> <span class="n">j</span> <span class="o">=</span> <span class="n">g</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>         <span class="c1">// async(F) AKA f().
</span><span class="k">auto</span> <span class="n">k</span> <span class="o">=</span> <span class="n">h</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>         <span class="c1">// async(F, h.get()) AKA f(h.get()).
</span><span class="k">auto</span> <span class="n">l</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">h</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>   <span class="c1">// async(F, h.move()) AKA f(h.move()).
</span><span class="k">auto</span> <span class="n">m</span> <span class="o">=</span> <span class="n">h</span><span class="p">.</span><span class="n">move_then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>    <span class="c1">// async(F, h.move()) AKA f(h.move()).
</span><span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">future</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span> <span class="c1">// async(F, future(3).move()) AKA F(future(3).move()).
</span>
<span class="c1">// Apply-style Continuations.
</span><span class="k">auto</span> <span class="n">o</span> <span class="o">=</span> <span class="n">i</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span> <span class="c1">// F("hello", 3.14, 17).
</span>
<span class="c1">// Continuation chaining.
</span><span class="k">auto</span> <span class="n">p</span> <span class="o">=</span> <span class="n">async</span><span class="p">(</span><span class="n">D</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">E</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span> <span class="c1">// F(E(D())); all values moved.
</span><span class="k">auto</span> <span class="n">q</span> <span class="o">=</span> <span class="n">h</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">E</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>        <span class="c1">// F(E(g)); all values except g moved.
</span></pre>
<pre class="highlight"><span class="n">future</span><span class="o">&lt;</span><span class="n">string</span><span class="o">></span> <span class="n">g</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">></span> <span class="n">h</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>
<span class="n">future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span>    <span class="n">i</span> <span class="o">=</span> <span class="cm">/* ... */</span><span class="p">;</span>

<span class="c1">// Combining.
</span><span class="k">auto</span> <span class="n">j</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">;</span>    <span class="c1">// value_type = tuple&lt;string, double, int>.
</span><span class="k">auto</span> <span class="n">k</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="mf">3.14</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">;</span> <span class="c1">// value_type = tuple&lt;string, double, int>.
</span>
<span class="c1">// Apply-style Continuations.
</span><span class="k">auto</span> <span class="n">l</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>            <span class="c1">// F(g.get(), h.get(), i.get()).
</span><span class="k">auto</span> <span class="n">m</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="mf">3.14</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>         <span class="c1">// F(g.get(), 3.14, i.get()).
</span><span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">)</span><span class="p">.</span><span class="n">then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>      <span class="c1">// F(g.move(), h.move(), i.move()).
</span><span class="k">auto</span> <span class="n">o</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">.</span><span class="n">move_then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span>       <span class="c1">// F(g.move(), h.move(), i.move()).
</span><span class="k">auto</span> <span class="n">p</span> <span class="o">=</span> <span class="n">when_all</span><span class="p">(</span><span class="n">move</span><span class="p">(</span><span class="n">g</span><span class="p">)</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span><span class="p">.</span><span class="n">move_then</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="p">;</span> <span class="c1">// F(g.move(), h.get(), i.get()).
</span></pre>
   <p>Here’s a (rough) synopsis of the interface:</p>
<pre class="highlight"><span class="k">namespace</span> <span class="n">std2</span>
<span class="p">{</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Ts</span><span class="o">></span>
<span class="k">struct</span> <span class="n">future</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="n">value_type</span> <span class="o">=</span> 
        <span class="c1">// void         when sizeof...(Ts) == 0 (e.g. future&lt;>).
</span>        <span class="c1">// Ts...        when sizeof...(Ts) == 1 (e.g. future&lt;T>).
</span>        <span class="c1">// tuple&lt;Ts...> when sizeof...(Ts) > 1  (e.g. future&lt;T, ...>).
</span>
    <span class="k">using</span> <span class="n">reference</span>       <span class="o">=</span> <span class="n">value_type</span><span class="o">&amp;</span><span class="p">;</span>
    <span class="k">using</span> <span class="n">const_reference</span> <span class="o">=</span> <span class="n">value_type</span> <span class="k">const</span><span class="o">&amp;</span><span class="p">;</span>

    <span class="c1">// DefaultConstructible.
</span>    <span class="k">constexpr</span> <span class="nf">future</span><span class="p">(</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="c1">// MoveAssignable.
</span>    <span class="c1">// 
</span>    <span class="c1">// Requires: Each Ts shall be MoveAssignable.
</span>    <span class="n">future</span><span class="p">(</span><span class="n">future</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">future</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">future</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="c1">// CopyAssignable.
</span>    <span class="c1">// 
</span>    <span class="c1">// Requires: Each Ts shall be CopyAssignable.
</span>    <span class="n">future</span><span class="p">(</span><span class="n">future</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">future</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">future</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="c1">///////////////////////////////////////////////////////////////////////////
</span>    <span class="c1">// Composition.
</span>
    <span class="c1">// when_all and make_ready_future constructor.
</span>    <span class="c1">//
</span>    <span class="c1">// Effects: Constructs a future that will be ready when all of us are
</span>    <span class="c1">// ready; if us is not a future, it is ready.
</span>    <span class="c1">//
</span>    <span class="c1">// Requires:
</span>    <span class="c1">// * sizeof...(Us) == sizeof...(Us)
</span>    <span class="c1">// * The result of get&lt;0>(tuple_cat(detail::move_or_get(us)...)) shall be
</span>    <span class="c1">//   assignable to value_type when sizeof...(Ts) == 1.
</span>    <span class="c1">// * The result of tuple_cat(detail::move_or_get(us)...) shall be
</span>    <span class="c1">//   assignable to value_type when sizeof...(Ts) > 1.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Us</span><span class="o">></span>
    <span class="n">future</span><span class="p">(</span><span class="n">Us</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">us</span><span class="p">)</span><span class="p">;</span>

    <span class="c1">///////////////////////////////////////////////////////////////////////////
</span>    <span class="c1">// Continuation Attachment.
</span>
    <span class="c1">// Effects: Equivalent to:
</span>    <span class="c1">// * return async(forward&lt;Continuation>(cont));
</span>    <span class="c1">//   when sizeof...(Ts) == 0.
</span>    <span class="c1">// * return async(forward&lt;Continuation>(cont), get());
</span>    <span class="c1">//   when sizeof...(Ts) == 1.
</span>    <span class="c1">// * return apply(async, tuple_cat(tuple(forward&lt;Continuation>(cont)), get());
</span>    <span class="c1">//   when sizeof...(Ts) > 1.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">move_then</span><span class="p">(</span><span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span><span class="p">;</span>
    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span> <span class="o">&amp;</span><span class="o">&amp;</span><span class="p">;</span>

    <span class="c1">// Effects: Equivalent to:
</span>    <span class="c1">// * move(); return async(forward&lt;Executor>(exec), forward&lt;Continuation>(cont));
</span>    <span class="c1">//   when sizeof...(Ts) == 0.
</span>    <span class="c1">// * return async(forward&lt;Executor>(exec), forward&lt;Continuation>(cont), move());
</span>    <span class="c1">//   when sizeof...(Ts) == 1.
</span>    <span class="c1">// * return apply(async,
</span>    <span class="c1">//                 tuple_cat(tuple(forward&lt;Executor>(exec), forward&lt;Continuation>(cont)),
</span>    <span class="c1">//                 move());
</span>    <span class="c1">//   when sizeof...(Ts) > 1.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Executor</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">move_then</span><span class="p">(</span><span class="n">Executor</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">exec</span><span class="p">,</span> <span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span><span class="p">;</span>
    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Executor</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">Executor</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">exec</span><span class="p">,</span> <span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span> <span class="o">&amp;</span><span class="o">&amp;</span><span class="p">;</span>

    <span class="c1">// Effects: Equivalent to:
</span>    <span class="c1">// * return async(forward&lt;Continuation>(cont));
</span>    <span class="c1">//   when sizeof...(Ts) == 0.
</span>    <span class="c1">// * return async(forward&lt;Continuation>(cont), get());
</span>    <span class="c1">//   when sizeof...(Ts) == 1.
</span>    <span class="c1">// * return apply(async, tuple_cat(tuple(forward&lt;Continuation>(cont)), get());
</span>    <span class="c1">//   when sizeof...(Ts) > 1.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span><span class="p">;</span>

    <span class="c1">// Effects: Equivalent to:
</span>    <span class="c1">// * return async(forward&lt;Executor>(exec), forward&lt;Continuation>(cont));
</span>    <span class="c1">//   when sizeof...(Ts) == 0.
</span>    <span class="c1">// * return async(forward&lt;Executor>(exec), forward&lt;Continuation>(cont), get());
</span>    <span class="c1">//   when sizeof...(Ts) == 1.
</span>    <span class="c1">// * return apply(async,
</span>    <span class="c1">//                 tuple_cat(tuple(forward&lt;Executor>(exec), forward&lt;Continuation>(cont)),
</span>    <span class="c1">//                 get());
</span>    <span class="c1">//   when sizeof...(Ts) > 1.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Executor</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Continuation</span><span class="o">></span>
    <span class="k">auto</span> <span class="n">then</span><span class="p">(</span><span class="n">Executor</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">exec</span><span class="p">,</span> <span class="n">Continuation</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">cont</span><span class="p">)</span><span class="p">;</span>

    <span class="c1">///////////////////////////////////////////////////////////////////////////
</span>    <span class="c1">// Status Observers.
</span>
    <span class="c1">// Returns: true if the future is ready.
</span>    <span class="kt">bool</span> <span class="nf">ready</span><span class="p">(</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>

    <span class="c1">// Returns: true if the future is associated with a shared state.
</span>    <span class="kt">bool</span> <span class="nf">valid</span><span class="p">(</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>

    <span class="c1">///////////////////////////////////////////////////////////////////////////
</span>    <span class="c1">// Consumer Access.
</span>
    <span class="c1">// Effects: Moves the value out of the shared state and invalidates the
</span>    <span class="c1">// shared state.
</span>    <span class="c1">//
</span>    <span class="c1">// Precondition: ready() is true and valid() is true.
</span>    <span class="c1">//
</span>    <span class="c1">// Throws: The stored exception, if an exception was stored in the shared
</span>    <span class="c1">// state.  
</span>    <span class="n">value_type</span> <span class="nf">move</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
    <span class="n">value_type</span> <span class="nf">get</span><span class="p">(</span><span class="p">)</span> <span class="o">&amp;</span><span class="o">&amp;</span><span class="p">;</span>

    <span class="c1">// Effects: Returns a reference to the value of the shared state.
</span>    <span class="c1">//
</span>    <span class="c1">// Precondition: ready() is true and valid() is true.
</span>    <span class="c1">// 
</span>    <span class="c1">// Throws: The stored exception, if an exception was stored in the shared
</span>    <span class="c1">// state.  
</span>    <span class="n">reference</span> <span class="nf">get</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
    <span class="n">const_reference</span> <span class="nf">get</span><span class="p">(</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">struct</span> <span class="n">future_result</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="n">type</span> <span class="o">=</span> <span class="n">T</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Ts</span><span class="o">></span>
<span class="k">struct</span> <span class="n">future_result</span><span class="o">&lt;</span><span class="n">future</span><span class="o">&lt;</span><span class="n">Ts</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span>
<span class="p">{</span>
    <span class="k">using</span> <span class="n">type</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">future</span><span class="o">&lt;</span><span class="n">Ts</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">:</span><span class="o">:</span><span class="n">value_type</span><span class="p">;</span>
<span class="p">}</span><span class="p">;</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">using</span> <span class="n">future_result_t</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">future_result</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">:</span><span class="o">:</span><span class="n">type</span><span class="p">;</span>

<span class="c1">// Deduction guide for implicit unwrapping.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Us</span><span class="o">></span>
<span class="n">future</span><span class="p">(</span><span class="n">Us</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">us</span><span class="p">)</span> <span class="o">-</span><span class="o">></span> <span class="n">future</span><span class="o">&lt;</span><span class="n">future_result_t</span><span class="o">&lt;</span><span class="n">Us</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="p">;</span>

<span class="k">namespace</span> <span class="n">detail</span>
<span class="p">{</span>

<span class="c1">// Effects: Equivalent to return t.get();.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="n">move_or_get</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">&amp;</span> <span class="n">t</span><span class="p">)</span><span class="p">;</span>

<span class="c1">// Effects: Equivalent to return t.get();.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="n">move_or_get</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">)</span><span class="p">;</span>

<span class="c1">// Effects: Equivalent to return t.move();.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="n">move_or_get</span><span class="p">(</span><span class="n">future</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">)</span><span class="p">;</span>

<span class="c1">// Effects: Equivalent to return forward&lt;T>(t);
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="n">move_or_get</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">)</span><span class="p">;</span>

<span class="p">}</span>

<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Ts</span><span class="o">></span>
<span class="k">struct</span> <span class="n">promise</span>
<span class="p">{</span>
    <span class="c1">// DefaultConstructible.
</span>    <span class="k">constexpr</span> <span class="n">promise</span><span class="p">(</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>

    <span class="c1">// MoveAssignable.
</span>    <span class="n">promise</span><span class="p">(</span><span class="n">promise</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">promise</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">promise</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="c1">// Returns: The future attached to this promise’s shared state.
</span>    <span class="c1">//
</span>    <span class="c1">// Precondition: get_future has not been called previously on this
</span>    <span class="c1">// promise..
</span>    <span class="n">future</span><span class="o">&lt;</span><span class="n">Ts</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span> <span class="n">get_future</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>

    <span class="c1">// Effects: Sets the promise’s value and changes its state to ready.
</span>    <span class="c1">//
</span>    <span class="c1">// Requires: 
</span>    <span class="c1">// * sizeof...(Ts) == sizeof...(Us)
</span>    <span class="c1">// * Each Ts shall be constructible from the corresponding element of Us.
</span>    <span class="c1">// 
</span>    <span class="c1">// Precondition: The promise is not ready.
</span>    <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Us</span><span class="o">></span>
    <span class="kt">void</span> <span class="n">set_value</span><span class="p">(</span><span class="n">Us</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">us</span><span class="p">)</span><span class="p">;</span> 

    <span class="c1">// Effects: Sets the promise’s to ready and sets its value to error.
</span>    <span class="c1">//
</span>    <span class="c1">// Precondition: The promise is not ready.
</span>    <span class="kt">void</span> <span class="nf">set_exception</span><span class="p">(</span><span class="n">exception_ptr</span> <span class="n">error</span><span class="p">)</span><span class="p">;</span> 
<span class="p">}</span><span class="p">;</span>

<span class="c1">///////////////////////////////////////////////////////////////////////////////
</span>
<span class="c1">// Effects: Adds a work item to exec (or the default global spawner) which
</span><span class="c1">// calls invoke(f, args...) and returns a future that is ready when the
</span><span class="c1">// work item is completed (e.g. when cont has been executed). The result of
</span><span class="c1">// invoke(f, args...) is the value of the future.
</span><span class="c1">//
</span><span class="c1">// Requires: is_invocable_v&lt;F, Args...> is true.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Args</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">declval</span><span class="o">&lt;</span><span class="n">F</span><span class="o">></span><span class="p">(</span><span class="p">)</span><span class="p">(</span><span class="n">declval</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">></span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">)</span><span class="o">></span>
<span class="n">async</span><span class="p">(</span><span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">f</span><span class="p">,</span> <span class="n">Args</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="p">)</span><span class="p">;</span>

<span class="c1">// Note: This function shall not participate in overload resolution unless
</span><span class="c1">// is_executor_v&lt;Executor> is true.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Executor</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Args</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">declval</span><span class="o">&lt;</span><span class="n">F</span><span class="o">></span><span class="p">(</span><span class="p">)</span><span class="p">(</span><span class="n">declval</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">></span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">)</span><span class="o">></span>
<span class="n">async</span><span class="p">(</span><span class="n">Executor</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">exec</span><span class="p">,</span> <span class="n">F</span><span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">f</span><span class="p">,</span> <span class="n">Args</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="p">)</span><span class="p">;</span>

<span class="c1">///////////////////////////////////////////////////////////////////////////////
</span>
<span class="c1">// Effects: Equivalent to: return future(forward&lt;Us>(us)...);
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">Us</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">future_result_t</span><span class="o">&lt;</span><span class="n">Us</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span>
<span class="n">when_all</span><span class="p">(</span><span class="n">Us</span><span class="o">&amp;</span><span class="o">&amp;</span><span class="p">.</span><span class="p">.</span><span class="p">.</span> <span class="n">us</span><span class="p">)</span><span class="p">;</span>

<span class="c1">// Effects: Constructs a future that is ready when all the elements in
</span><span class="c1">// [first, last) are ready.
</span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">InputIterator</span><span class="o">></span>
<span class="n">future</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">future_result_t</span><span class="o">&lt;</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">InputIterator</span><span class="o">></span><span class="o">:</span><span class="o">:</span><span class="n">value_type</span><span class="o">></span><span class="p">.</span><span class="p">.</span><span class="p">.</span><span class="o">></span><span class="o">></span>
<span class="n">when_all</span><span class="p">(</span><span class="n">InputIterator</span> <span class="n">first</span><span class="p">,</span> <span class="n">InputIterator</span> <span class="n">last</span><span class="p">)</span><span class="p">;</span>

<span class="p">}</span>
</pre>
   <h2 class="heading settled" data-level="4" id="acknowledgements"><span class="secno">4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>A big thanks to David Sankel and Sean Parent, who have provided a lot of useful
insight over the past few weeks.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

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

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

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

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

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

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


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

    tocNav.appendChild(toggle);
  }

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

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

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

})();
</script>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-p0443r1">[P0443r1]
   <dd>Jared Hoberock, Michael Garland, Chris Kohlhoff, Chris Mysen, Carter Edwards, Gordon Brown. <a href="https://wg21.link/p0443r1">A Unified Executors Proposal for C++</a>. 6 January 2017. URL: <a href="https://wg21.link/p0443r1">https://wg21.link/p0443r1</a>
  </dl>