<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>P3367R4: constexpr coroutines</title>
<style>
@media (prefers-color-scheme: dark) {
	:root {
		--text-color: #BBB;
		--found-highlight: blue;
		--found-text-color: white;
		--main-background: 32,32,32;
		--header-color: white;
		--box-shadow-color: rgba(0,0,0,0.5);
    --thin-box-shadow-color: rgba(0,0,0,0.1);
		--nav-background-color: #101010;
		--code-foreground-color: white;
		--code-info-color: rgba(255,255,255,0.1);
		--code-background-color: var(--nav-background-color);
		--link-color: #8ef3ff;
		--visited-link-color: #f0ff89;
		--hover-link-color: #b3f7ff;
		--hover-visited-link-color: #c8ffb3;
		--line-color: 255,255,255;
		--header-background: 0,0,0;
		--quote-left-color: rgba(255,255,255,0.5);
		--highlight: rgba(255,252,0,0.25);
	}
	::selection {
	  color: black;
	  background: lightyellow;
	}
}

@media (prefers-color-scheme: light) {
	:root {
		--text-color: black;
		--found-highlight: yellow;
		--found-text-color: black;
		--main-background: 255,255,255;
		--header-color: black;
		--box-shadow-color: rgba(0,0,0,0.3);
    --thin-box-shadow-color: rgba(0,0,0,0.1);
		--nav-background-color: #F5F5F5;
		--code-foreground-color: black;
		--code-info-color: rgba(0,0,0,0.1);
		--code-background-color: var(--nav-background-color);
		--link-color: #000082;
		--visited-link-color: #508d0f;
		--hover-link-color: #5757c2;
		--hover-visited-link-color: #94c560;
		--line-color: 12,43,75;
		--header-background: 0,0,0;
		--quote-left-color: rgba(0,0,0,0.5);
		--highlight: rgba(255,254,207,0.5);
	}
	/*
	*::selection {
	  color: black;
	  background: #a4c3f6;
	}*/
}

@media (prefers-color-scheme: dark) {
	svg {
		--hana-text: black;
		--hana-outline: black;
		--hana-contrast-text: rgba(255,255,255,0.75);
		--hana-info: rgba(255,255,255,0.6);
		--hana-lines: white;
		--hana-special-boxes: rgba(0,0,0,0.5);
		--hana-special-boxes-outline: rgba(255,255,255,0.5);
		--hana-boxes: rgba(255,255,255,0.6);
		--hana-boxes-background: rgba(255,255,255,0.1);
		--hana-inside-text: white;
		--hana-outside-text: var(--text-color);
		--hana-shadow: white;
		--hana-structures-outline: white;
		--hana-structures-fill: black;
		--hana-structures-fill-meaningless: #444;
		--hana-pink-fill: #a3567e;
		--hana-purple-fill: #4d539d;
		--hana-green-fill: #1e7451;
		--hana-yellow-fill: #727529;
		--hana-orange-fill: #714530;
	}
}

@media (prefers-color-scheme: light) {
	svg {
		--hana-text: black;
		--hana-outline: black;
		--hana-contrast-text: rgba(255,255,255,1);
		--hana-info: rgba(0,0,0,0.6);
		--hana-lines: black;
		--hana-special-boxes: rgba(0,0,0,0.9);
		--hana-special-boxes-outline: rgba(255,255,255,0.5);
		--hana-boxes: rgba(0,0,0,0.6);
		--hana-boxes-background: rgba(0,0,0,0.1);
		--hana-inside-text: var(--text-color);
		--hana-outside-text: var(--text-color);
		--hana-shadow: black;
		--hana-structures-outline: black;
		--hana-structures-fill: white;
		--hana-structures-fill-meaningless: lightgray;
		--hana-pink-fill: #ffacd6;
		--hana-purple-fill: #acacff;
		--hana-green-fill: #acffd5;
		--hana-yellow-fill: #ffffac;
		--hana-orange-fill: #ffc8ad;
	}
}

svg g#boxes * {
	fill: var(--hana-boxes);
	fill-opacity: 0.1;
	stroke: var(--hana-boxes);
}
svg g#special {
	opacity: 0.25;
}
svg g#black-outline * {
	stroke: var(--hana-outline);
}
svg g#text * {
	fill: var(--hana-text);
}
svg g#info * {
	fill: var(--hana-info);
}
svg g#info text {
	fill: var(--hana-info);
}
svg g#contrast-text * {
	fill: var(--hana-contrast-text);
}
svg g#contrast-black-outline * {
	fill: var(--hana-special-boxes);
	stroke: var(--hana-special-boxes-outline);
}
svg g#black-lines * {
	stroke: var(--hana-lines);
}
svg g#black-lines polygon {
	fill: var(--hana-lines);
}

/* inheritance */
svg g#outside-text * {
	fill: var(--hana-outside-text);
}
svg g#inside-text * {
	fill: var(--hana-inside-text);
}
svg g#shadow path {
	fill: var(--hana-shadow);
	opacity: 0.1;
}
svg g#arrows g path, svg g#arrows g line {
	stroke: var(--hana-structures-outline);
}
svg g#arrows g polygon {
	fill: var(--hana-structures-outline);
}
svg g#structures > * {
	stroke: var(--hana-structures-outline);
	fill: var(--hana-structures-fill);
}
svg g#items g#meaningless > * {
	fill: var(--hana-structures-fill-meaningless);
}
svg g#items g#pink > * {
	fill: var(--hana-pink-fill);
}
svg g#items g#orange > * {
	fill: var(--hana-orange-fill);
}
svg g#items g#purple > * {
	fill: var(--hana-purple-fill);
}
svg g#items g#yellow > * {
	fill: var(--hana-yellow-fill);
}
svg g#items g#green > * {
	fill: var(--hana-green-fill);
}
svg g#items * {
	stroke: var(--hana-structures-outline);
}


span:target, p:target, li:target, div:target {
  background: var(--highlight);
}

.name-of-paper {
	font-size: 28px;
	padding-top: 0.5em;
}

span.found {
	text-shadow: 0 0 10px var(--found-highlight),  0 0 10px var(--found-highlight),  0 0 10px var(--found-highlight),  0 0 10px var(--found-highlight);
	color: var(--found-text-color) !important;
}

body {
	font-family: Helvetica;
	padding: 0;
	margin: 0;
	overflow: hidden;
	color: var(--text-color);
	background-color: rgba(var(--main-background), 1);
}

body > div {
	display: flex;
	padding: 0;
	margin: 0;
}

.hide-on-narrow {
	display: inherit;
}

.hide-on-wide {
	display: none;
}

@media only screen and (max-width: 1100px) {
	body {
		overflow: inherit !important;
	}
	.hide-on-narrow {
		display: none;
	}
	.hide-on-wide {
		display: inherit;
	}
	body > div {
		display: block !important;
	}
	article {
		overflow: inherit !important;
		background-image: linear-gradient(to right, transparent,rgba(var(--main-background),0.6), rgba(var(--main-background),0.8), rgba(var(--main-background),0.6), transparent) !important;
	}
	nav, article {
		flex: initial !important;
	}
	nav {
		min-width: initial !important;
		max-width: initial !important;
		min-height: initial !important;
		max-height: initial !important;
		box-shadow: 0 10px 0 var(--box-shadow-color);
	}
	nav > div {
		overflow: inherit !important;
		position: relative !important;
		max-width: initial !important;
		max-height: initial !important;
	}
	div:has(> input[type=search]) {
		display: none;
	}
	div.quote {
		overflow-x: visible;
    overflow-y: visible;
	}
}

nav {
	padding: 0 0.5em;
	margin: 0;
	flex: 1 1 0;
	min-width: 350px;
	max-width: 350px;
	box-shadow: 0 0 10px var(--box-shadow-color);
	background-color: var(--nav-background-color);
}

nav > div {
	position: fixed;
	max-width: 350px;
	max-height: 100%;
	overflow: scroll;
	top: 0;
	left: 0;
	padding: 0 0.5em;
	margin: 0;
}

nav > div > div {
	padding: 0.5em;
	padding-top: 0;
	padding-bottom: 1em;
}

article {
	flex: 3 1 0;
	overflow: scroll;
	height: 100vh;
	text-align: justify;
	background-image: linear-gradient(to bottom, transparent,rgba(var(--main-background),0.6), rgba(var(--main-background),0.8), rgba(var(--main-background),0.6), transparent);
	padding: 0;
	margin: 0;
}

article > div {
	padding-right: 1.5em;
	padding-left: 1.5em;
	padding-bottom: 1em;
}

code {
	
}

div.quote {
	color: var(--code-foreground-color);
	background: var(--code-background-color);
	padding: 1em;
	border-radius: 0px 15px 15px 0px;
	border-left: 5px solid var(--quote-left-color);
	font-style: italic;
	margin: 1em;
}

code:not(pre > code) {
	color: inherit;
	background: var(--code-background-color);
	border-radius: 5px;
	padding: 0 0.2em;
	margin: 0 2px;
	outline: 2px solid var(--code-background-color);
}

pre > code {
	outline: none;
	line-height: 1.4;
	tab-size: 2;
}

pre:has(code) {
	color: var(--code-foreground-color);
	background: var(--code-background-color);
	padding: 1em;
	border-radius: 15px;
	position: relative;
	z-index: 1;
	overflow-x: visible;
	overflow-y: visible;
}

pre:has(code.language-carbon)::before {
	content: "Carbon";
	text-transform: uppercase;
	position: absolute;
	top: 1em;
	right: 1em;
	color: var(--code-info-color);
	font-weight: bold;
}

p, ul > li {
	text-align: justify;
	overflow-wrap: break-word;
	hyphens: auto;
}

article ul > li {
	padding-bottom: 0.25em;
}

div.description ul {
  padding-top: 0.5em;
	padding-bottom: 0.5em;
}

a {
	color: var(--link-color);
	text-decoration-style: dotted;
}

a:hover {
	color: var(--hover-link-color);
	text-decoration-style: solid;
}

a:visited {
	color: var(--visited-link-color);
}

a:visited:hover {
	color: var(--hover-visited-link-color);
	text-decoration-style: solid;
}

h1, h2, h3, h4, h5 {
	text-align: left;
	margin: 0;
	margin-bottom: 10px;
	padding: 0.5em;
	padding-top: 20px;
	padding-bottom: 2px;
	z-index: 2;
	color: var(--header-color) !important;
	a {
		color: var(--header-color) !important;
	}
}

article h1, article h2, article h3, article h4, article h5 {
/*	position: sticky;
	position: -webkit-sticky;
	top: 0;*/
	
}

h1 {
	font-weight: 800;
	border-bottom: rgba(var(--line-color), 1) dotted 2px;
}

h2 {
	font-weight: 800;
	border-bottom: rgba(var(--line-color), 0.75) dotted 2px;
}

h3, h4, h5 {
	font-weight: 600;
	border-bottom: rgba(var(--line-color), 0.33) dotted 2px;
}

h1 > a, h2 > a, h3 > a, h4 > a, h5 > a {
	text-decoration: inherit;
}

h1:target::after, h2:target::after, h3:target::after, h4:target::after, h5:target::after {
	text-decoration: inherit;
	content: " ⚓︎";
  font-size: 14px;
}

h1 > a:hover, h2 > a:hover, h3 > a:hover, h4 > a:hover, h5 > a:hover {
	color: var(--hover-link-color);
}

div:has(> input[type=search]) {
	position: fixed;
	top: 0;
	right: 0;
	z-index: 1000;
	padding: 0.5em;
	background-color: var(--nav-background-color);
	box-shadow: 0 0 10px rgba(0,0,0,0.3);
	border-bottom-left-radius: 10px;
}

div > input[type=search] {
	background-color: var(--nav-background-color);
	border: 2px solid var(--text-color);
	color: var(--text-color);
	width: 300px;
}

div.paper-info {
	padding: 0;
	padding-top: 1em;
	
	.key {
		font-weight: bold;
	}
	
	div {
	}
}

ul {
	padding: 0;
	margin: 0;
	padding-left: 1em;
}

div#toc > ul {
	margin-left: 1em;
}

div#toc ul {
	padding-left: 0.5em;
}

li > ul {
	padding-left: 0.25em;
}

ul > li {
	padding-left: 0.25em;
}

div#toc li {
	text-align: left;
}

code .error, code .before {
	line-height: 1.9;
}

code .error > *, code .before > * {
	background-color: #FF8888 !important;
	color: black !important;
	@media (prefers-color-scheme: dark) {
		color: white;
	}
	border: 3px solid #FF8888;
	font-weight: bold;
}

code .after > * {
	background-color: lightgreen !important;
	color: black !important;
	@media (prefers-color-scheme: dark) {
		color: white;
	}
	border: 3px solid lightgreen;
	font-weight: bold;
}

code .unchanged > * {
	background-color: lightyellow !important;
	color: black !important;
	@media (prefers-color-scheme: dark) {
		color: white;
	}
	border: 3px solid lightyellow;
	font-weight: bold;
}

code .invisible {
	visibility: hidden;
}

.changes {
	display: inline-block;
}

.wording h1, .wording h1 > a, .wording h2, .wording h2 > a {
	font-size: inherit;
	text-decoration: none;
	border: none;
	padding: 0;
	margin: 0;
	@media (prefers-color-scheme: dark) {
		color: white !important;
	}
	@media (prefers-color-scheme: light) {
		color: black !important;
	}
	
	/*color: orange !important;*/
}

.wording p {
	padding: 0;
	padding-top: 0.5em;
	margin: 0;
}

.wording a {
	text-decoration: none;
	color: inherit;
}

.wording a:hover {
	text-decoration: underline;
	color: var(--link-color);
}

.wording a:visited {

}

.wording code {
	background: inherit !important;
	border: none;
	outline: none;
}
	
.wording {
	font-family: "Noto Serif";
	
	padding: 0.5em 1em;
	padding-bottom: 1em;
	color: var(--code-foreground-color);
	background: var(--code-background-color);
	line-height: 1.55;
	
	border-radius: 15px;
	position: relative;
	z-index: 1;
	overflow-x: visible;
	overflow-y: visible;
}
	
.wording .added, pre .added {
	background-color: lightgreen;
	text-decoration: underline;
  text-decoration-color: green;
  text-decoration-thickness: 2px !important;
	z-index: 80;
	padding: 3px;
	@media (prefers-color-scheme: dark) {
		color: black !important;
	}
}

.highlight {
	border-radius: 5px;
	border: 5px solid #fff587;
	background-color: #fff587;
	color: black;
	z-index: -5;
	text-shadow: 0 0 5px white;
	@media (prefers-color-scheme: dark) {
		border: 5px solid #001676;
		background-color: #001676;
		color: white;
		text-shadow: 0 0 10px black;
	}
	
	
}

div.added pre.added *, div.added pre.added {
	text-decoration-color: transparent;
}

.wording .added-item {
	background-color: lightgreen;
  text-decoration: underline;
  text-decoration-color: green;
  text-decoration-thickness: 2px !important;
	@media (prefers-color-scheme: dark) {
		color: black;
	}
}
	
.wording .removed {
	background-color: #FF8888;
	z-index: 50;
	padding: 3px;
  text-decoration: line-through;
  text-decoration-color: rgba(255,0,0,0.75);
  text-decoration-thickness: 2px !important;
	@media (prefers-color-scheme: dark) {
		color: black;
	}
}

.wording li.removed-bullet::before {
	background-color: #FF8888;
	z-index: 50;
	padding: 3px;
  text-decoration: line-through;
  text-decoration-color: rgba(255,0,0,0.75);
  text-decoration-thickness: 2px !important;
	@media (prefers-color-scheme: dark) {
		color: black;
	}
}
	
.wording .note {
	font-size: 0.8em;
}
	
.wording	+ .wording {
	margin-top: 0.5em;
}
	
.wording pre:has(code) {
	border: 1px solid var(--code-info-color);
	border-radius: 0;
	padding: 0em;
	z-index: 1;
	overflow-x: scroll;
}
	
.wording	code .addeded span {
	color: black !important;
}

table.poll {
  border-collapse: collapse;
  margin-top: 20px;
}

table.poll th, table.poll td {
  border: 0;
  padding: 5px 10px;
  text-align: center;
  border: 2px solid rgba(128,128,128,0.2);
}

table.poll td:first-child, table.poll th:first-child {
 border-left: none;
}

table.poll td:last-child, table.poll th:last-child {
 border-right: none;
}

table.poll tr:first-child th, table.poll tr:first-child td {
  border-top: none;
}

table.poll tr:last-child th, table.poll tr:last-child td {
  border-bottom: none;
}

.wording .description {
  padding-bottom: 1em;
}

.wording .caps {
  text-transform: uppercase;
}

table th.table-group {
	max-width: 2em;
}

table th.table-group > span {
	max-width: 2em;
	display: block;
	overflow: visible;
	text-align: center;
	transform: translateX(1em);
}

table th.table-group > span > span {
	display: inline-block;
	transform: translateX(-50%) rotate(-90deg);
	width: auto;
}

table.before-after th, table.before-after td  {
  height: 30px;
}



table.before-after .green {
  color: green;
}

table.before-after .orange {
  color: orange;
}

table.before-after .red-normal {
  color: red;
}

table.before-after .in-progress {
	color: blue;
	background-color: rgba(0,231,255,0.5);
}

table.before-after .proposing {
	color: green;
	background-color: rgba(0,255,0,0.5);
}

table.before-after .not-proposing {
	color: red;
	background-color: rgba(255,0,0,0.25);
}

table.before-after .never-proposing {
	color: red;
	background-color: rgba(255,0,0,0.25);
}

table.before-after .proposed-ready-for-future {
	color: green;
	background-color: rgba(203,229,7,0.5);
}

table.before-after .proposed-ready-for-future2 {
	color: green;
	background-color: rgba(255,198,0,0.5);
}

table.before-after .red {
  color: red;
  font-size: 24px;
  line-height: 16px;
}

td a, td a:visited, td a:hover {
	color: inherit;
}

div.wording-note {
  background: rgb(var(--main-background));
  box-shadow: 5px 0 10px var(--thin-box-shadow-color) inset;
  border-radius: 15px;
  color: var(--text-color);
  padding: 10px;
  margin: 10px 20px;
  font-size: 12px;
}

.parnum {
	font-size: 12px;
	margin-right: 0.25em;
	display: inline-block;
}

li:has(> .parnum) {
	list-style-position: inside;
	position: relative;
}

li > .parnum {
	position: absolute;
	left: -30px;
	bottom: 2px;
}

div.svgimg {
	text-align: left;
}

div.svgimg > div {
	
}

div.svgimg > div > svg {

}

@media (prefers-color-scheme: dark) {
	div.svgimg > div > img {
		border-radius: 10px;
		filter: drop-shadow(0px 0px 5px rgb(255 255 255 / 0.4));
	}
}

table.before-after td.disable-bottom, table.before-after th.disable-bottom {
	border-bottom: none;
}
table.before-after th.left, table.before-after td.left {
	text-align: left;
}

td a.note:after {
	vertical-align: super;
	font-size: 75%;
	margin-left: 0.5em;
}

td a.note.n1:after {
	content: "1";
}

td a.note.n2:after {
	content: "2";
}

td a.note.n3:after {
	content: "3";
}

td a.note.n4:after {
	content: "4";
}

td a.note.n5:after {
	content: "5";
}

blockquote {
	background: rgba(0,0,0,0.10);
	font-style: italic;
	padding: 0.05em 1em;
	margin: 0;
	border-left: rgba(0,0,0,0.5) 5px solid;
}

.wording pre code em, .wording pre code em span {
	color: var(--text-color) !important;
}
</style>
<style>
@media (prefers-color-scheme: light) {

pre code.hljs {

}
code.hljs {

}
/*

XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>

*/
.hljs {
  color: inherit
}
/* Gray DOCTYPE selectors like WebKit */
.xml .hljs-meta {
  color: #c0c0c0
}
.hljs-comment,
.hljs-quote {
  color: #007400
}
.hljs-tag,
.hljs-attribute,
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-name {
  color: #aa0d91
}
.hljs-variable,
.hljs-template-variable {
  color: #3F6E74
}
.hljs-code,
.hljs-string,
.hljs-meta .hljs-string {
  color: #c41a16
}
.hljs-regexp,
.hljs-link {
  color: #0E0EFF
}
.hljs-title,
.hljs-symbol,
.hljs-bullet,
.hljs-number {
  color: #1c00cf
}
.hljs-section,
.hljs-meta {
  color: #643820
}
.hljs-title.class_,
.hljs-class .hljs-title,
.hljs-type,
.hljs-built_in,
.hljs-params {
  color: #5c2699
}
.hljs-attr {
  color: #836C28
}
.hljs-subst {
  color: #000
}
.hljs-formula {
  font-style: italic
}
.hljs-addition {

}
.hljs-deletion {

}
.hljs-selector-id,
.hljs-selector-class {
  color: #9b703f
}
.hljs-doctag,
.hljs-strong {
  font-weight: bold
}
.hljs-emphasis {
  font-style: italic
}

}

@media (prefers-color-scheme: dark) {

pre code.hljs {

}
code.hljs {

}
/*

XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>

*/
.hljs {
  color: inherit
}
/* Gray DOCTYPE selectors like WebKit */
.xml .hljs-meta {
  color: #c0c0c0
}
.hljs-comment,
.hljs-quote {
  color: #007400
}
.hljs-tag,
.hljs-attribute,
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-name {
  color: #aa0d91
}
.hljs-variable,
.hljs-template-variable {
  color: #3F6E74
}
.hljs-code,
.hljs-string,
.hljs-meta .hljs-string {
  color: #c41a16
}
.hljs-regexp,
.hljs-link {
  color: #0E0EFF
}
.hljs-title,
.hljs-symbol,
.hljs-bullet,
.hljs-number {
  color: #9382ff
}
.hljs-section,
.hljs-meta {
  color: #643820
}
.hljs-title.class_,
.hljs-class .hljs-title,
.hljs-type,
.hljs-built_in,
.hljs-params {
  color: #b879ff
}
.hljs-attr {
  color: #836C28
}
.hljs-subst {
  color: #000
}
.hljs-formula {
  font-style: italic
}
.hljs-addition {

}
.hljs-deletion {

}
.hljs-selector-id,
.hljs-selector-class {
  color: #9b703f
}
.hljs-doctag,
.hljs-strong {
  font-weight: bold
}
.hljs-emphasis {
  font-style: italic
}

}



</style>
<style>
.wording  {
    font-family: 'Noto Serif';
    hyphens: auto;
    line-height: 1.5;
    font-size: 10pt;
    padding-left: 3em;
}

.wording div {
    background: inherit;
}

.wording div.wrapper {
    max-width: 20cm;
    margin: auto;
}

.wording div.texpara {
    margin-top: 3pt;
    margin-bottom: 3pt;
}

.wording table div.texpara {
    margin-top: 0;
    margin-bottom: 0;
}

.wording table.enumerate div.texpara {
    margin-top: 3pt;
    margin-bottom: 3pt;
}

.wording ul {
    list-style-type: none;
    padding-left: 9mm;
    margin-top: 0;
    margin-bottom: 0;
}

.wording ol {
    margin-top: 0;
    margin-bottom: 0;
}

.wording a {
    text-decoration: none;
}

.wording a.hidden_link {
    text-decoration: none;
    color: inherit;
}

.wording li {
    margin-top: 3pt;
    margin-bottom: 3pt;
}

.wording h1 {
    line-height: 1;
    margin-top: 10pt;
    margin-bottom: 10pt;
}

.wording h2 {
    line-height: 1;
    font-size: 14pt;
    margin-top: 10pt;
    margin-bottom: 10pt;
}

.wording h2::after {
    content: "";
    clear: both;
    display: table;
}

.wording h3 {
    line-height: 1;
    margin-top: 10pt;
    margin-bottom: 10pt;
}

.wording h3::after {
    content: "";
    clear: both;
    display: table;
}

.wording h4 {
    line-height: 1;
    margin-top: 10pt;
    margin-bottom: 10pt;
}

.wording h4::after {
    content: "";
    clear: both;
    display: table;
}

.wording ul > li:before {
    content: "\2014";
    position: absolute;
    margin-left: -1.5em;
}

.wording .shy:before {
    content: "\00ad";
    /* This is U+00AD SOFT HYPHEN, same as &shy, but we put it in :before
    	to stop it from being included when the text is copied to the clipboard
    	with Firefox, which is especially annoying when copying to a terminal,
    	where the hyphen characters will show up. */
}


.wording .abbr_ref {
    float: right;
}

.wording .folded_abbr_ref {
    float: right;
}

.wording .unfolded_abbr_ref {
    display: none;
}

.wording .secnum {
    display: inline-block;
    min-width: 35pt;
}

.wording .annexnum {
    display: block;
}

.wording div.sourceLinkParent {
    float: right;
}

.wording a.sourceLink {
    position: absolute;
    opacity: 0;
    margin-left: 10pt;
}

.wording a.sourceLink:hover {
    opacity: 1;
}

.wording a.itemDeclLink {
    position: absolute;
    font-size: 75%;
    text-align: right;
    width: 5em;
    opacity: 0;
}

.wording a.itemDeclLink:hover {
    opacity: 1;
}

.wording div.marginalizedparent {
    position: relative;
    left: -18mm;
}

.wording a.marginalized {
    width: 15mm;
    position: absolute;
    font-size: 7pt;
    text-align: right;
}

.wording a.enumerated_item_num {
    display: block;
    margin-top: 3pt;
    margin-bottom: 3pt;
    margin-right: 6pt;
}

.wording div.para {
    margin-bottom: 6pt;
    margin-top: 6pt;
    text-align: justify;
    min-height: 1.2em;
}

.wording div.section {
    text-align: justify;
}

.wording div.sentence {
    display: inline;
}

.wording a.index {
    position: relative;
    float: right;
    right: -1em;
    display: none;
}

.wording a.index:before {
    position: absolute;
    content: "⟵";
    background-color: #C9FBC9;
}


.wording .indexitems {
    margin-left: 2em;
    text-indent: -2em;
}

.wording div.itemdescr {
    margin-left: 12mm;
}

.wording .bnf {
    font-family: 'Noto Sans';
    font-size: 10pt;
    font-style: italic;
    margin-left: 25pt;
    margin-top: 0.5em;
    margin-bottom: 0.5em;
    text-indent: -3em;
    padding-left: 3em;
    line-height: 1.5;
}

.wording div.bnf span.texttt {
    font-family: 'Noto Sans Mono';
    font-style: normal;
}

.wording .rebnf {
    font-family: 'Noto Serif';
    font-style: italic;
    margin-top: 0.5em;
    margin-bottom: 0.5em;
    margin-left: 30pt;
    text-indent: -3em;
    padding-left: 3em;
    line-height: 1.5;
}

.wording .simplebnf {
    font-family: 'Noto Serif';
    font-style: italic;
    font-size: 10pt;
    margin-top: 0.5em;
    margin-bottom: 0.5em;
    margin-left: 30pt;
    line-height: 1.5;
}

.wording span.textnormal {
    font-style: normal;
    font-family: 'Noto Serif';
    font-size: 10pt;
    white-space: normal;
}

.wording .bnf span.textnormal {
    font-style: normal;
    font-family: 'Noto Serif';
    font-size: 10pt;
    white-space: normal;
}

.wording p {
    margin-top: 4pt;
    margin-bottom: 4pt;
}

.wording span.rlap {
    display: inline-block;
    width: 0px;
    text-indent: 0;
}

.wording span.terminal {
    font-family: 'Noto Sans Mono';
    font-style: normal;
    font-size: 9pt;
    white-space: pre-wrap;
}

.wording span.noncxxterminal {
    font-family: 'Noto Sans Mono';
    font-style: normal;
    font-size: 9pt;
}

.wording span.term {
    font-style: italic;
}

.wording span.tcode {
    font-family: 'Noto Sans Mono';
    font-style: normal;
}

.wording span.textbf {
    font-weight: bold;
}

.wording span.textsf {
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording div.footnote span.textsf {
    font-family: 'Noto Sans';
    font-size: 8pt;
}

.wording .bnf span.textsf {
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording .simplebnf span.textsf {
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording .example span.textsf {
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording span.textsc {
    font-variant: small-caps;
}

.wording span.nontermdef {
    font-style: italic;
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording .rebnf a.nontermdef {
    font-style: italic;
    font-family: 'Noto Serif';
}

.wording span.emph {
    font-style: italic;
}

.wording span.techterm {
    font-style: italic;
}

.wording span.mathit {
    font-style: italic;
}

.wording span.mathsf {
    font-family: 'Noto Sans';
}

.wording span.mathrm {
    font-family: 'Noto Serif';
    font-style: normal;
}

.wording span.textrm {
    font-family: 'Noto Serif';
    font-size: 10pt;
}

.wording span.textsl {
    font-style: italic;
}

.wording span.mathtt {
    font-family: 'Noto Sans Mono';
    font-style: normal;
}

.wording span.mbox {
    font-family: 'Noto Serif';
    font-style: normal;
}

.wording span.ungap {
    display: inline-block;
    width: 2pt;
}

.wording span.texttt {
    font-family: 'Noto Sans Mono';
}

.wording span.textit {
    font-style: italic;
}

.wording div.footnote span.texttt {
    font-family: 'Noto Sans Mono';
}

.wording span.tcode_in_codeblock {
    font-family: 'Noto Sans Mono';
    font-style: normal;
    font-size: 9pt;
}

.wording span.phantom {
    color: white;
}
/* Unfortunately, this way the text is still selectable. Another
	option is display:none, but then we lose the nice layout.
	Todo: find proper solution. */

.wording span.math {
    font-style: normal;
    font-family: 'Noto Serif';
    font-size: 10pt;
}

.wording span.mathblock {
    display: block;
    margin-left: auto;
    margin-right: auto;
    margin-top: 1.2em;
    margin-bottom: 1.2em;
    text-align: center;
}

.wording span.mathalpha {
    font-style: italic;
}

.wording span.synopsis {
    font-weight: bold;
    margin-top: 0.5em;
    display: block;
}

.wording span.definition {
    font-weight: bold;
    display: block;
}

.wording .codeblock {
    font-family: 'Noto Sans Mono';
    margin-left: 1.2em;
    line-height: 1.5;
    font-size: 9pt;
    white-space: pre;
    display: block;
    margin-top: 3pt;
    margin-bottom: 3pt;
		overflow-x: visible;
		overflow-y: default;
}

.wording table .codeblock {
    margin-right: 0;
}

.wording .outputblock {
    margin-left: 1.2em;
    line-height: 1.5;
    font-family: 'Noto Sans Mono';
    font-size: 9pt;
}

.wording code {
    font-family: 'Noto Sans Mono';
    font-style: normal;
}

.wording div.itemdecl {
    margin-top: 2ex;
}

.wording code.itemdeclcode {
    white-space: pre;
    font-family: 'Noto Sans Mono';
    font-size: 9pt;
    display: block;
		overflow-x: visible;
		overflow-y: default;
}

.wording .comment {
    color: green;
    font-style: italic;
    font-family: 'Noto Serif';
    font-size: 10pt;
}

.wording .footnote .comment {
    color: green;
    font-style: italic;
    font-family: 'Noto Serif';
    font-size: 8pt;
}

.wording .example .comment {
    color: green;
    font-style: italic;
    font-family: 'Noto Serif';
    font-size: 9pt;
}

.wording .note .comment {
    color: green;
    font-style: italic;
    font-family: 'Noto Serif';
    font-size: 9pt;
}

.wording span.keyword {
    color: #00607c;
    font-style: normal;
}

.wording span.parenthesis {
    color: #af1915;
}

.wording span.curlybracket {
    color: #af1915;
}

.wording span.squarebracket {
    color: #af1915;
}

.wording span.literal {
    color: #9F6807;
}

.wording span.literalterminal {
    color: #9F6807;
    font-family: 'Noto Sans Mono';
    font-style: normal;
}

.wording span.operator {
    color: #570057;
}

.wording span.anglebracket {
    color: #570057;
}

.wording span.preprocessordirective {
    color: #6F4E37;
}

.wording span.textsuperscript {
    vertical-align: super;
    font-size: smaller;
    line-height: 0;
}

.wording .footnoteref {
    vertical-align: super;
    font-size: smaller;
    line-height: 0;
}

.wording .footnote {
    font-size: 8pt;
}

.wording .footnote .math {
    font-size: 8pt;
}

.wording .footnotenum {
    display: inline-block;
    text-align: right;
    margin-right: 1mm;
    width: 4ch;
}

.wording .footnoteBacklink {
    display: none;
}

.wording .footnoteSeparator {
    background: black;
    margin-top: 5mm;
    height: 1px;
    width: 6cm;
}

.wording div.minipage {
    display: inline-block;
    margin-right: 3em;
}

.wording div.numberedTable {
    text-align: center;
    margin-left: 1em;
    margin-right: 1em;
    margin-bottom: 12pt;
    margin-top: 8pt;
}

.wording div.figure {
    text-align: center;
    margin-left: 2em;
    margin-right: 2em;
    margin-bottom: 12pt;
    margin-top: 3pt;
}

.wording table {
    border: 1px solid black;
    border-collapse: collapse;
    margin-left: auto;
    margin-right: auto;
    margin-top: 7pt;
    text-align: left;
}

.wording td, .wording th {
    padding-left: 8pt;
    padding-right: 8pt;
    vertical-align: top;
}

.wording td.empty {
    padding: 0px;
    padding-left: 1px;
}

.wording td.left {
    text-align: left;
}

.wording td.hidden {
    padding: 0;
    width: 0;
}

.wording td.right {
    text-align: right;
}

.wording td.center {
    text-align: center;
}

.wording td.justify {
    text-align: justify;
}

.wording td.border {
    border-left: 1px solid black;
}

.wording tr.rowsep, .wording td.cline {
    border-top: 1px solid black;
}

.wording tr.capsep {
    border-top: 3px solid black;
    border-top-style: double;
}

.wording th {
    border-bottom: 1px solid black;
}

.wording span.centry {
    font-weight: bold;
}

.wording div.table {
    display: block;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    width: 90%;
}

.wording span.indented {
    background: inherit;
    display: block;
    margin-left: 2em;
    margin-bottom: 1em;
    margin-top: 1em;
}

.wording span.uppercase {
    text-transform: uppercase;
}

.wording span.ucode {
    font-variant: small-caps;
    text-transform: uppercase;
    font-size: 90%;
}

.wording span.uname {
    font-variant: small-caps;
    text-transform: uppercase;
    font-size: 90%;
}

.wording table.enumerate {
    border: 0;
    margin: 0;
}

.wording table.enumerate td {
    padding: 0;
}

.wording table.enumerate td:first-child {
    width: 1cm;
    text-align: right;
}

@media (prefers-color-scheme: dark) {
    .wording {
        background-color: #171717;
        color: #d0d0d0;
    }

    .wording span.mjx-mstyle {
        color: #d0d0d0 !important
    }

    .wording a:link {
        color: #64adff;
    }

    .wording a:visited {
        color: #a36ae6;
    }

    .wording a.hidden_link {
        text-decoration: none;
        color: inherit;
    }

    .wording span.phantom {
        color: #171717;
    }

    .wording a.index:before {
        color: #d0d0d0;
        background-color: #4b6353;
    }

    .wording .comment {
        color: #35da00;
    }

    .wording .footnote .comment {
        color: #35da00;
    }

    .wording .example .comment {
        color: #35da00;
    }

    .wording .note .comment {
        color: #35da00;
    }

    .wording span.keyword {
        color: #12cabe;
    }

    .wording span.parenthesis {
        color: #ff1515;
    }

    .wording span.curlybracket {
        color: #ff1515;
    }

    .wording span.squarebracket {
        color: #ff1515;
    }

    .wording span.literal {
        color: #dfa837;
    }

    .wording span.literalterminal {
        color: #dfa837;
    }

    .wording span.operator {
        color: #baa6b9;
    }

    .wording span.anglebracket {
        color: #baa6b9;
    }

    .wording span.preprocessordirective {
        color: #b27c58;
    }

    .wording table {
        border-color: #d0d0d0;
    }

    .wording td.border {
        border-color: #d0d0d0;
    }

    .wording td.border {
        border-left-color: #d0d0d0;
    }

    .wording tr.rowsep, td.cline {
        border-top-color: #d0d0d0;
    }

    .wording tr.capsep {
        border-top-color: #d0d0d0;
    }

    .wording th {
        border-bottom-color: #d0d0d0;
    }

    .wording .footnoteSeparator {
        background-color: #d0d0d0;
    }

    .wording text {
        fill: #d0d0d0;
    }

    .wording path {
        stroke: #d0d0d0;
    }

    .wording polygon {
        stroke: #d0d0d0;
        fill: #d0d0d0;
    }

    .wording ellipse {
        stroke: #d0d0d0;
    }

}

.wording .mjx-chtml {
    display: inline-block;
    line-height: 0;
    text-indent: 0;
    text-align: left;
    text-transform: none;
    font-style: normal;
    font-weight: normal;
    font-size: 100%;
    font-size-adjust: none;
    letter-spacing: normal;
    word-wrap: normal;
    word-spacing: normal;
    white-space: nowrap;
    float: none;
    direction: ltr;
    max-width: none;
    max-height: none;
    min-width: 0;
    min-height: 0;
    border: 0;
    margin: 0;
    padding: 1px 0
}

.wording .MJXc-display {
    display: block;
    background: inherit;
    text-align: center;
    margin: 1em 0;
    padding: 0
}

.wording .mjx-chtml[tabindex]:focus, .wording  :focus .mjx-chtml[tabindex] {
    display: inline-table
}

.wording .mjx-full-width {
    text-align: center;
    display: table-cell !important;
    width: 10000em
}

.wording .mjx-math {
    display: inline-block;
    border-collapse: separate;
    border-spacing: 0
}

.wording .mjx-math * {
    display: inline-block;
    -webkit-box-sizing: content-box !important;
    -moz-box-sizing: content-box !important;
    box-sizing: content-box !important;
    text-align: left
}

.wording .mjx-numerator {
    display: block;
    background: inherit;
    text-align: center
}

.wording .mjx-denominator {
    display: block;
    background: inherit;
    text-align: center
}

.wording .MJXc-stacked {
    height: 0;
    position: relative
}

.wording .MJXc-stacked > * {
    position: absolute
}

.wording .MJXc-bevelled > * {
    display: inline-block
}

.wording .mjx-stack {
    display: inline-block
}

.wording .mjx-op {
    display: block;
    background: inherit
}

.wording .mjx-under {
    display: table-cell
}

.wording .mjx-over {
    display: block;
    background: inherit
}

.wording .mjx-over > * {
    padding-left: 0px !important;
    padding-right: 0px !important
}

.wording .mjx-under > * {
    padding-left: 0px !important;
    padding-right: 0px !important
}

.wording .mjx-stack > .mjx-sup {
    display: block;
    background: inherit
}

.wording .mjx-stack > .mjx-sub {
    display: block;
    background: inherit
}

.wording .mjx-prestack > .mjx-presup {
    display: block;
    background: inherit
}

.wording .mjx-prestack > .mjx-presub {
    display: block;
    background: inherit
}

.wording .mjx-delim-h > .mjx-char {
    display: inline-block
}

.wording .mjx-surd {
    vertical-align: top
}

.wording .mjx-mphantom * {
    visibility: hidden
}

.wording .mjx-merror {
    background-color: #FFFF88;
    color: #CC0000;
    border: 1px solid #CC0000;
    padding: 2px 3px;
    font-style: normal;
    font-size: 90%
}

.wording .mjx-annotation-xml {
    line-height: normal
}

.wording .mjx-menclose > svg {
    fill: none;
    stroke: currentColor
}

.wording .mjx-mtr {
    display: table-row
}

.wording .mjx-mlabeledtr {
    display: table-row
}

.wording .mjx-mtd {
    display: table-cell;
    text-align: center
}

.wording .mjx-label {
    display: table-row
}

.wording .mjx-box {
    display: inline-block
}

.wording .mjx-block {
    display: block;
    background: inherit
}

.wording .mjx-span {
    display: inline
}

.wording .mjx-char {
    display: block;
    background: inherit;
    white-space: pre
}

.wording .mjx-itable {
    display: inline-table;
    width: auto
}

.wording .mjx-row {
    display: table-row
}

.wording .mjx-cell {
    display: table-cell
}

.wording .mjx-table {
    display: table;
    width: 100%
}

.wording .mjx-line {
    display: block;
    background: inherit;
    height: 0
}

.wording .mjx-strut {
    width: 0;
    padding-top: 1em
}

.wording .mjx-vsize {
    width: 0
}

.wording .MJXc-space1 {
    margin-left: .167em
}

.wording .MJXc-space2 {
    margin-left: .222em
}

.wording .MJXc-space3 {
    margin-left: .278em
}

.wording .mjx-ex-box-test {
    position: absolute;
		overflow-x: visible;
		overflow-y: default;
    width: 1px;
    height: 60ex
}

.wording .mjx-line-box-test {
    display: table !important
}

.wording .mjx-line-box-test span {
    display: table-cell !important;
    width: 10000em !important;
    min-width: 0;
    max-width: none;
    padding: 0;
    border: 0;
    margin: 0
}

.wording .MJXc-TeX-unknown-R {
    font-family: monospace;
    font-style: normal;
    font-weight: normal
}

.wording .MJXc-TeX-unknown-I {
    font-family: monospace;
    font-style: italic;
    font-weight: normal
}

.wording .MJXc-TeX-unknown-B {
    font-family: monospace;
    font-style: normal;
    font-weight: bold
}

.wording .MJXc-TeX-unknown-BI {
    font-family: monospace;
    font-style: italic;
    font-weight: bold
}

.wording .MJXc-TeX-ams-R {
    font-family: MJXc-TeX-ams-R, MJXc-TeX-ams-Rw
}

.wording .MJXc-TeX-cal-B {
    font-family: MJXc-TeX-cal-B, MJXc-TeX-cal-Bx, MJXc-TeX-cal-Bw
}

.wording .MJXc-TeX-frak-R {
    font-family: MJXc-TeX-frak-R, MJXc-TeX-frak-Rw
}

.wording .MJXc-TeX-frak-B {
    font-family: MJXc-TeX-frak-B, MJXc-TeX-frak-Bx, MJXc-TeX-frak-Bw
}

.wording .MJXc-TeX-math-BI {
    font-family: MJXc-TeX-math-BI, MJXc-TeX-math-BIx, MJXc-TeX-math-BIw
}

.wording .MJXc-TeX-sans-R {
    font-family: 'Noto Sans';
    font-size: 10pt;
}

.wording .MJXc-TeX-sans-B {
    font-family: MJXc-TeX-sans-B, MJXc-TeX-sans-Bx, MJXc-TeX-sans-Bw
}

.wording .MJXc-TeX-sans-I {
    font-family: MJXc-TeX-sans-I, MJXc-TeX-sans-Ix, MJXc-TeX-sans-Iw
}

.wording .MJXc-TeX-script-R {
    font-family: MJXc-TeX-script-R, MJXc-TeX-script-Rw
}

.wording .MJXc-TeX-type-R {
    font-family: 'Noto Sans Mono';
    font-size: 10pt;
}

.wording .MJXc-TeX-cal-R {
    font-family: MJXc-TeX-cal-R, MJXc-TeX-cal-Rw
}

.wording .MJXc-TeX-main-B {
    font-family: MJXc-TeX-main-B, MJXc-TeX-main-Bx, MJXc-TeX-main-Bw
}

.wording .MJXc-TeX-main-I {
    font-style: italic
}

.wording .MJXc-TeX-main-R {
}

.wording .MJXc-TeX-math-I {
    font-style: italic
}

.wording .MJXc-TeX-size1-R {
    font-family: MJXc-TeX-size1-R, MJXc-TeX-size1-Rw
}

.wording .MJXc-TeX-size2-R {
    font-family: MJXc-TeX-size2-R, MJXc-TeX-size2-Rw
}

.wording .MJXc-TeX-size3-R {
    font-family: MJXc-TeX-size3-R, MJXc-TeX-size3-Rw
}

.wording .MJXc-TeX-size4-R {
    font-family: MJXc-TeX-size4-R, MJXc-TeX-size4-Rw
}

.wording .MJXc-TeX-vec-R {
    font-family: MJXc-TeX-vec-R, MJXc-TeX-vec-Rw
}

.wording .MJXc-TeX-vec-B {
    font-family: MJXc-TeX-vec-B, MJXc-TeX-vec-Bx, MJXc-TeX-vec-Bw
}

@font-face {
    font-family: MJXc-TeX-ams-R;
    src: local('MathJax_AMS'), local('MathJax_AMS-Regular')
}

@font-face {
    font-family: MJXc-TeX-ams-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_AMS-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_AMS-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_AMS-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-cal-B;
    src: local('MathJax_Caligraphic Bold'), local('MathJax_Caligraphic-Bold')
}

@font-face {
    font-family: MJXc-TeX-cal-Bx;
    src: local('MathJax_Caligraphic');
    font-weight: bold
}

@font-face {
    font-family: MJXc-TeX-cal-Bw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Caligraphic-Bold.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Bold.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Caligraphic-Bold.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-frak-R;
    src: local('MathJax_Fraktur'), local('MathJax_Fraktur-Regular')
}

@font-face {
    font-family: MJXc-TeX-frak-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Fraktur-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Fraktur-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-frak-B;
    src: local('MathJax_Fraktur Bold'), local('MathJax_Fraktur-Bold')
}

@font-face {
    font-family: MJXc-TeX-frak-Bx;
    src: local('MathJax_Fraktur');
    font-weight: bold
}

@font-face {
    font-family: MJXc-TeX-frak-Bw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Fraktur-Bold.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Bold.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Fraktur-Bold.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-math-BI;
    src: local('MathJax_Math BoldItalic'), local('MathJax_Math-BoldItalic')
}

@font-face {
    font-family: MJXc-TeX-math-BIx;
    src: local('MathJax_Math');
    font-weight: bold;
    font-style: italic
}

@font-face {
    font-family: MJXc-TeX-math-BIw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Math-BoldItalic.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Math-BoldItalic.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Math-BoldItalic.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-sans-R;
    src: local('MathJax_SansSerif'), local('MathJax_SansSerif-Regular')
}

@font-face {
    font-family: MJXc-TeX-sans-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_SansSerif-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_SansSerif-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-sans-B;
    src: local('MathJax_SansSerif Bold'), local('MathJax_SansSerif-Bold')
}

@font-face {
    font-family: MJXc-TeX-sans-Bx;
    src: local('MathJax_SansSerif');
    font-weight: bold
}

@font-face {
    font-family: MJXc-TeX-sans-Bw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_SansSerif-Bold.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Bold.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_SansSerif-Bold.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-sans-I;
    src: local('MathJax_SansSerif Italic'), local('MathJax_SansSerif-Italic')
}

@font-face {
    font-family: MJXc-TeX-sans-Ix;
    src: local('MathJax_SansSerif');
    font-style: italic
}

@font-face {
    font-family: MJXc-TeX-sans-Iw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_SansSerif-Italic.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Italic.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_SansSerif-Italic.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-script-R;
    src: local('MathJax_Script'), local('MathJax_Script-Regular')
}

@font-face {
    font-family: MJXc-TeX-script-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Script-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Script-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Script-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-type-R;
    src: local('MathJax_Typewriter'), local('MathJax_Typewriter-Regular')
}

@font-face {
    font-family: MJXc-TeX-type-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Typewriter-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Typewriter-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Typewriter-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-cal-R;
    src: local('MathJax_Caligraphic'), local('MathJax_Caligraphic-Regular')
}

@font-face {
    font-family: MJXc-TeX-cal-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Caligraphic-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Caligraphic-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-main-B;
    src: local('MathJax_Main Bold'), local('MathJax_Main-Bold')
}

@font-face {
    font-family: MJXc-TeX-main-Bx;
    src: local('MathJax_Main');
    font-weight: bold
}

@font-face {
    font-family: MJXc-TeX-main-Bw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Main-Bold.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Main-Bold.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Bold.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-main-I;
    src: local('MathJax_Main Italic'), local('MathJax_Main-Italic')
}

@font-face {
    font-family: MJXc-TeX-main-Ix;
    src: local('MathJax_Main');
    font-style: italic
}

@font-face {
    font-family: MJXc-TeX-main-Iw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Main-Italic.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Main-Italic.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Italic.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-main-R;
    src: local('MathJax_Main'), local('MathJax_Main-Regular')
}

@font-face {
    font-family: MJXc-TeX-main-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Main-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-math-I;
    src: local('MathJax_Math Italic'), local('MathJax_Math-Italic')
}

@font-face {
    font-family: MJXc-TeX-math-Ix;
    src: local('MathJax_Math');
    font-style: italic
}

@font-face {
    font-family: MJXc-TeX-math-Iw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Math-Italic.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Math-Italic.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-size1-R;
    src: local('MathJax_Size1'), local('MathJax_Size1-Regular')
}

@font-face {
    font-family: MJXc-TeX-size1-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Size1-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Size1-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Size1-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-size2-R;
    src: local('MathJax_Size2'), local('MathJax_Size2-Regular')
}

@font-face {
    font-family: MJXc-TeX-size2-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Size2-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Size2-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-size3-R;
    src: local('MathJax_Size3'), local('MathJax_Size3-Regular')
}

@font-face {
    font-family: MJXc-TeX-size3-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Size3-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Size3-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-size4-R;
    src: local('MathJax_Size4'), local('MathJax_Size4-Regular')
}

@font-face {
    font-family: MJXc-TeX-size4-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Size4-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Size4-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-vec-R;
    src: local('MathJax_Vector'), local('MathJax_Vector-Regular')
}

@font-face {
    font-family: MJXc-TeX-vec-Rw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Vector-Regular.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Vector-Regular.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Vector-Regular.otf') format('opentype')
}

@font-face {
    font-family: MJXc-TeX-vec-B;
    src: local('MathJax_Vector Bold'), local('MathJax_Vector-Bold')
}

@font-face {
    font-family: MJXc-TeX-vec-Bx;
    src: local('MathJax_Vector');
    font-weight: bold
}

@font-face {
    font-family: MJXc-TeX-vec-Bw;
    src /*1*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/eot/MathJax_Vector-Bold.eot');
    src /*2*/: url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/woff/MathJax_Vector-Bold.woff') format('woff'), url('https://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Vector-Bold.otf') format('opentype')
}

.wording div.example {
	display: block;
	margin-top: 5pt;
	margin-bottom: 5pt;
	font-size: 11pt;
	color: #bb00bb;
}

.wording div.note {
	display: block;
	margin-top: 5pt;
	margin-bottom: 5pt;
	font-size: 11pt;
	color: #bb00bb;
}

.wording div.example {
	display: block;
	margin-top: 5pt;
	margin-bottom: 5pt;
	font-size: 9pt;
}

.wording div.note {
	display: block;
	margin-top: 5pt;
	margin-bottom: 5pt;
	font-size: 9pt;
}

.wording div.note .texttt { font-size: 9pt; }
.wording div.example .texttt { font-size: 9pt; }

.wording div.note .textsf { font-family: 'Noto Sans'; font-size: 9pt; }
.wording div.example .textsf { font-family: 'Noto Sans'; font-size: 9pt; }

.wording div.note .math { font-size: 9pt; }
.wording div.example .math { font-size: 9pt; }

.wording a.footnotenum { display: none; }
.wording div.footnote { display: none; }
.wording div.footnoteSeparator { display: none; }
.wording .footnoteref { display: none; }

.wording div.nonNormativeOnly { display: none; }


</style>
<link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel='stylesheet'>
<link href="https://fonts.googleapis.com/css?family=Noto+Sans" rel='stylesheet'>
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+Mono" rel='stylesheet'>
<script language='javascript'>
/*!
  Highlight.js v11.9.0 (git: b7ec4bfafc)
  (c) 2006-2024 undefined and other contributors
  License: BSD-3-Clause
 */
var hljs=function(){"use strict";function e(t){
return t instanceof Map?t.clear=t.delete=t.set=()=>{
throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{
throw Error("set is read-only")
}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{
const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i)
})),t}class t{constructor(e){
void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}
ignoreMatch(){this.isMatchIgnored=!0}}function n(e){
return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")
}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t]
;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope
;class o{constructor(e,t){
this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){
this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{
if(e.startsWith("language:"))return e.replace("language:","language-")
;if(e.includes(".")){const n=e.split(".")
;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ")
}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)}
closeNode(e){s(e)&&(this.buffer+="</span>")}value(){return this.buffer}span(e){
this.buffer+=`<span class="${e}">`}}const r=(e={})=>{const t={children:[]}
;return Object.assign(t,e),t};class a{constructor(){
this.rootNode=r(),this.stack=[this.rootNode]}get top(){
return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){
this.top.children.push(e)}openNode(e){const t=r({scope:e})
;this.add(t),this.stack.push(t)}closeNode(){
if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){
for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}
walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){
return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t),
t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){
"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{
a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e}
addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){
this.closeNode()}__addSublanguage(e,t){const n=e.root
;t&&(n.scope="language:"+t),this.add(n)}toHTML(){
return new o(this,this.options).value()}finalize(){
return this.closeAllNodes(),!0}}function l(e){
return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")}
function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")}
function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{
const t=e[e.length-1]
;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{}
})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"}
function p(e){return RegExp(e.toString()+"|").exec("").length-1}
const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./
;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n
;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break}
s+=i.substring(0,e.index),
i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0],
"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)}
const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={
begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'",
illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n",
contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t,
contains:[]},n);s.contains.push({scope:"doctag",
begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",
end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0})
;const o=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/)
;return s.contains.push({begin:h(/[ ]+/,"(",o,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s
},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({
__proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{
scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N,
C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number",
begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{
"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{
t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E,
MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0},
NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w,
PHRASAL_WORDS_MODE:{
begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
},QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/,
end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]},
RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",
SHEBANG:(e={})=>{const t=/^#![ ]*\//
;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t,
end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)},
TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x,
UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){
"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){
void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){
t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",
e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,
void 0===e.relevance&&(e.relevance=0))}function L(e,t){
Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){
if(e.match){
if(e.begin||e.end)throw Error("begin & end are not supported with match")
;e.begin=e.match,delete e.match}}function P(e,t){
void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return
;if(e.starts)throw Error("beforeMatch cannot be used with starts")
;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t]
})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={
relevance:0,contains:[Object.assign(n,{endsParent:!0})]
},e.relevance=0,delete n.beforeMatch
},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword"
;function $(e,t,n=C){const i=Object.create(null)
;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{
Object.assign(i,$(e[n],t,n))})),i;function s(e,n){
t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|")
;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){
return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{
console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{
z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0)
},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],o={},r={}
;for(let e=1;e<=t.length;e++)r[e+i]=s[e],o[e+i]=!0,i+=p(t[e-1])
;e[n]=r,e[n]._emit=o,e[n]._multi=!0}function Z(e){(e=>{
e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,
delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={
_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope
}),(e=>{if(Array.isArray(e.begin)){
if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),
K
;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"),
K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{
if(Array.isArray(e.end)){
if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"),
K
;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"),
K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){
function t(t,n){
return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":""))
}class n{constructor(){
this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}
addRule(e,t){
t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]),
this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null)
;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|"
}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex
;const t=this.matcherRe.exec(e);if(!t)return null
;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n]
;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){
this.rules=[],this.multiRegexes=[],
this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){
if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n
;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))),
t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){
return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){
this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){
const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex
;let n=t.exec(e)
;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{
const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)}
return n&&(this.regexIndex+=n.position+1,
this.regexIndex===this.count&&this.considerAll()),n}}
if(e.compilerExtensions||(e.compilerExtensions=[]),
e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language.  See documentation.")
;return e.classNameAliases=i(e.classNameAliases||{}),function n(o,r){const a=o
;if(o.isCompiled)return a
;[I,B,Z,D].forEach((e=>e(o,r))),e.compilerExtensions.forEach((e=>e(o,r))),
o.__beforeBegin=null,[T,L,P].forEach((e=>e(o,r))),o.isCompiled=!0;let c=null
;return"object"==typeof o.keywords&&o.keywords.$pattern&&(o.keywords=Object.assign({},o.keywords),
c=o.keywords.$pattern,
delete o.keywords.$pattern),c=c||/\w+/,o.keywords&&(o.keywords=$(o.keywords,e.case_insensitive)),
a.keywordPatternRe=t(c,!0),
r&&(o.begin||(o.begin=/\B|\b/),a.beginRe=t(a.begin),o.end||o.endsWithParent||(o.end=/\B|\b/),
o.end&&(a.endRe=t(a.end)),
a.terminatorEnd=l(a.end)||"",o.endsWithParent&&r.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+r.terminatorEnd)),
o.illegal&&(a.illegalRe=t(o.illegal)),
o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{
variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{
starts:e.starts?i(e.starts):null
}):Object.isFrozen(e)?i(e):e))("self"===e?o:e)))),o.contains.forEach((e=>{n(e,a)
})),o.starts&&n(o.starts,r),a.matcher=(e=>{const t=new s
;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin"
}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end"
}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){
return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{
constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}}
const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{
const i=Object.create(null),s=Object.create(null),o=[];let r=!0
;const a="Could not find the language '{}', did you forget to load/include a language module?",l={
disableAutodetect:!0,name:"Plain text",contains:[]};let p={
ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,
languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",
cssSelector:"pre code",languages:null,__emitter:c};function b(e){
return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s=""
;"object"==typeof t?(i=e,
n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."),
G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),
s=e,i=t),void 0===n&&(n=!0);const o={code:i,language:s};N("before:highlight",o)
;const r=o.result?o.result:E(o.language,o.code,n)
;return r.code=o.code,N("after:highlight",r),r}function E(e,n,s,o){
const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R)
;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n=""
;for(;t;){n+=R.substring(e,t.index)
;const s=_.case_insensitive?t[0].toLowerCase():t[0],o=(i=s,N.keywords[i]);if(o){
const[e,i]=o
;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{
const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0]
;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i
;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{
if(""===R)return;let e=null;if("string"==typeof N.subLanguage){
if(!i[N.subLanguage])return void M.addText(R)
;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top
}else e=x(R,N.subLanguage.length?N.subLanguage:null)
;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language)
})():l(),R=""}function u(e,t){
""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1
;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue}
const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}}
function h(e,t){
return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope),
e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),
R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{
value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t)
;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e)
;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){
for(;e.endsParent&&e.parent;)e=e.parent;return e}}
if(e.endsWithParent)return f(e.parent,n,i)}function b(e){
return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){
const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const o=N
;N.endScope&&N.endScope._wrap?(g(),
u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(),
d(N.endScope,e)):o.skip?R+=t:(o.returnEnd||o.excludeEnd||(R+=t),
g(),o.excludeEnd&&(R=t));do{
N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent
}while(N!==s.parent);return s.starts&&h(s.starts,e),o.returnEnd?0:t.length}
let w={};function y(i,o){const a=o&&o[0];if(R+=i,null==a)return g(),0
;if("begin"===w.type&&"end"===o.type&&w.index===o.index&&""===a){
if(R+=n.slice(o.index,o.index+1),!r){const t=Error(`0 width match regex (${e})`)
;throw t.languageName=e,t.badRule=w.rule,t}return 1}
if(w=o,"begin"===o.type)return(e=>{
const n=e[0],i=e.rule,s=new t(i),o=[i.__beforeBegin,i["on:begin"]]
;for(const t of o)if(t&&(t(e,s),s.isMatchIgnored))return b(n)
;return i.skip?R+=n:(i.excludeBegin&&(R+=n),
g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(o)
;if("illegal"===o.type&&!s){
const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"<unnamed>")+'"')
;throw e.mode=N,e}if("end"===o.type){const e=m(o);if(e!==ee)return e}
if("illegal"===o.type&&""===a)return 1
;if(I>1e5&&I>3*o.index)throw Error("potential infinite loop, way more iterations than matches")
;return R+=a,a.length}const _=O(e)
;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"')
;const v=V(_);let k="",N=o||v;const S={},M=new p.__emitter(p);(()=>{const e=[]
;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope)
;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{
if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){
I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A
;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(A,e.index),e)
;A=e.index+t}y(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e,
value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){
if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n),
illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A,
context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(r)return{
language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N}
;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{
const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)}
;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1)))
;s.unshift(n);const o=s.sort(((e,t)=>{
if(e.relevance!==t.relevance)return t.relevance-e.relevance
;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1
;if(O(t.language).supersetOf===e.language)return-1}return 0})),[r,a]=o,c=r
;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{
let t=e.className+" ";t+=e.parentNode?e.parentNode.className:""
;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1])
;return t||(X(a.replace("{}",n[1])),
X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"}
return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return
;if(N("before:highlightElement",{el:e,language:n
}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e)
;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),
console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),
console.warn("The element with unescaped HTML:"),
console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML)
;t=e;const i=t.textContent,o=n?m(i,{language:n,ignoreIllegals:!0}):x(i)
;e.innerHTML=o.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n
;e.classList.add("hljs"),e.classList.add("language-"+i)
})(e,n,o.language),e.result={language:o.language,re:o.relevance,
relevance:o.relevance},o.secondBest&&(e.secondBest={
language:o.secondBest.language,relevance:o.secondBest.relevance
}),N("after:highlightElement",{el:e,result:o,text:i})}let y=!1;function _(){
"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0
}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}
function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{
s[e.toLowerCase()]=t}))}function k(e){const t=O(e)
;return t&&!t.disableAutodetect}function N(e,t){const n=e;o.forEach((e=>{
e[n]&&e[n](t)}))}
"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{
y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_,
highlightElement:w,
highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"),
G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)},
initHighlighting:()=>{
_(),G("10.6.0","initHighlighting() deprecated.  Use highlightAll() now.")},
initHighlightingOnLoad:()=>{
_(),G("10.6.0","initHighlightingOnLoad() deprecated.  Use highlightAll() now.")
},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){
if(W("Language definition for '{}' could not be registered.".replace("{}",e)),
!r)throw t;W(t),s=l}
s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{
languageName:e})},unregisterLanguage:e=>{delete i[e]
;for(const t of Object.keys(s))s[t]===e&&delete s[t]},
listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v,
autoDetection:k,inherit:Q,addPlugin:e=>{(e=>{
e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{
e["before:highlightBlock"](Object.assign({block:t.el},t))
}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{
e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),o.push(e)},
removePlugin:e=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}),n.debugMode=()=>{
r=!1},n.safeMode=()=>{r=!0},n.versionString="11.9.0",n.regex={concat:h,
lookahead:g,either:f,optional:d,anyNumberOfTimes:u}
;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n
},ne=te({});return ne.newInstance=()=>te({}),ne}()
;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `cpp` grammar compiled for Highlight.js 11.9.0 */
(()=>{var e=(()=>{"use strict";return e=>{const t=e.regex,a=e.COMMENT("//","$",{
contains:[{begin:/\\\n/}]
}),n="decltype\\(auto\\)",r="[a-zA-Z_]\\w*::",i="(?!struct)("+n+"|"+t.optional(r)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",s={
className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{
begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{
begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",
end:"'",illegal:"."},e.END_SAME_AS_BEGIN({
begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={
className:"number",variants:[{
begin:"[+-]?(?:(?:[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)"
},{
begin:"[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)"
}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{
keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"
},contains:[{begin:/\\\n/,relevance:0},e.inherit(c,{className:"string"}),{
className:"string",begin:/<.*?>/},a,e.C_BLOCK_COMMENT_MODE]},u={
className:"title",begin:t.optional(r)+e.IDENT_RE,relevance:0
},d=t.optional(r)+e.IDENT_RE+"\\s*\\(",p={
type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],
keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],
literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"],
_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]
},_={className:"function.dispatch",relevance:0,keywords:{
_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]
},
begin:t.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,t.lookahead(/(<[^<>]+>|)\s*\(/))
},m=[_,l,s,a,e.C_BLOCK_COMMENT_MODE,o,c],f={variants:[{begin:/=/,end:/;/},{
begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],
keywords:p,contains:m.concat([{begin:/\(/,end:/\)/,keywords:p,
contains:m.concat(["self"]),relevance:0}]),relevance:0},g={className:"function",
begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,
keywords:p,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:n,keywords:p,relevance:0},{
begin:d,returnBegin:!0,contains:[u],relevance:0},{begin:/::/,relevance:0},{
begin:/:/,endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{
className:"params",begin:/\(/,end:/\)/,keywords:p,relevance:0,
contains:[a,e.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p,
relevance:0,contains:["self",a,e.C_BLOCK_COMMENT_MODE,c,o,s]}]
},s,a,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++",
aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"</",
classNameAliases:{"function.dispatch":"built_in"},
contains:[].concat(f,g,_,m,[l,{
begin:"\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array|tuple|optional|variant|function)\\s*<(?!<)",
end:">",keywords:p,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:p},{
match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],
className:{1:"keyword",3:"title.class"}}])}}})();hljs.registerLanguage("cpp",e)
})();
</script>
<script language='javascript'>
var mergeHTMLPlugin = (function () {
  'use strict';

  var originalStream;

  /**
   * @param {string} value
   * @returns {string}
   */
  function escapeHTML(value) {
    return value
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#x27;');
  }

  /* plugin itself */

  /** @type {HLJSPlugin} */
  const mergeHTMLPlugin = {
    // preserve the original HTML token stream
    "before:highlightElement": ({ el }) => {
      originalStream = nodeStream(el);
    },
    // merge it afterwards with the highlighted token stream
    "after:highlightElement": ({ el, result, text }) => {
      if (!originalStream.length) return;

      const resultNode = document.createElement('div');
      resultNode.innerHTML = result.value;
      result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
      el.innerHTML = result.value;
    }
  };

  /* Stream merging support functions */

  /**
   * @typedef Event
   * @property {'start'|'stop'} event
   * @property {number} offset
   * @property {Node} node
   */

  /**
   * @param {Node} node
   */
  function tag(node) {
    return node.nodeName.toLowerCase();
  }

  /**
   * @param {Node} node
   */
  function nodeStream(node) {
    /** @type Event[] */
    const result = [];
    (function _nodeStream(node, offset) {
      for (let child = node.firstChild; child; child = child.nextSibling) {
        if (child.nodeType === 3) {
          offset += child.nodeValue.length;
        } else if (child.nodeType === 1) {
          result.push({
            event: 'start',
            offset: offset,
            node: child
          });
          offset = _nodeStream(child, offset);
          // Prevent void elements from having an end tag that would actually
          // double them in the output. There are more void elements in HTML
          // but we list only those realistically expected in code display.
          if (!tag(child).match(/br|hr|img|input/)) {
            result.push({
              event: 'stop',
              offset: offset,
              node: child
            });
          }
        }
      }
      return offset;
    })(node, 0);
    return result;
  }

  /**
   * @param {any} original - the original stream
   * @param {any} highlighted - stream of the highlighted source
   * @param {string} value - the original source itself
   */
  function mergeStreams(original, highlighted, value) {
    let processed = 0;
    let result = '';
    const nodeStack = [];

    function selectStream() {
      if (!original.length || !highlighted.length) {
        return original.length ? original : highlighted;
      }
      if (original[0].offset !== highlighted[0].offset) {
        return (original[0].offset < highlighted[0].offset) ? original : highlighted;
      }

      /*
      To avoid starting the stream just before it should stop the order is
      ensured that original always starts first and closes last:

      if (event1 == 'start' && event2 == 'start')
        return original;
      if (event1 == 'start' && event2 == 'stop')
        return highlighted;
      if (event1 == 'stop' && event2 == 'start')
        return original;
      if (event1 == 'stop' && event2 == 'stop')
        return highlighted;

      ... which is collapsed to:
      */
      return highlighted[0].event === 'start' ? original : highlighted;
    }

    /**
     * @param {Node} node
     */
    function open(node) {
      /** @param {Attr} attr */
      function attributeString(attr) {
        return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"';
      }
      // @ts-ignore
      result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('') + '>';
    }

    /**
     * @param {Node} node
     */
    function close(node) {
      result += '</' + tag(node) + '>';
    }

    /**
     * @param {Event} event
     */
    function render(event) {
      (event.event === 'start' ? open : close)(event.node);
    }

    while (original.length || highlighted.length) {
      let stream = selectStream();
      result += escapeHTML(value.substring(processed, stream[0].offset));
      processed = stream[0].offset;
      if (stream === original) {
        /*
        On any opening or closing tag of the original markup we first close
        the entire highlighted node stack, then render the original tag along
        with all the following original tags at the same offset and then
        reopen all the tags on the highlighted stack.
        */
        nodeStack.reverse().forEach(close);
        do {
          render(stream.splice(0, 1)[0]);
          stream = selectStream();
        } while (stream === original && stream.length && stream[0].offset === processed);
        nodeStack.reverse().forEach(open);
      } else {
        if (stream[0].event === 'start') {
          nodeStack.push(stream[0].node);
        } else {
          nodeStack.pop();
        }
        render(stream.splice(0, 1)[0]);
      }
    }
    return result + escapeHTML(value.substr(processed));
  }

  return mergeHTMLPlugin;

}());
</script>
</head>
<body><div>
<nav><div><div>

<h1 class="hide-on-wide name-of-paper">constexpr coroutines</h1>
<div class="paper-info">
	<div><span class="key">Number:</span> P3367R4</div>
	<div><span class="key">Date:</span> <time>2025-02-17</time></div>
	<div><span class="key">Audience:</span> CWG, LWG</div>
	<div><span class="key">Reply-to:</span> <a href="mailto:cpp@hanicka.net">Hana Dusíková</a></div>
  <div><span class="key">Target:</span> C++29</div>
</div>

<div id='toc'><h2 id='_toc'><a href='#_toc'>Table of contents</a></h2>
<ul>
<li><a href='#changes'>Changes</a></li><li><a href='#timeline'>Timeline</a></li><li><a href='#quote'>Quote</a></li><li><a href='#motivation'>Motivation</a><ul>
<ul>
<li><a href='#coroutines-are-not-just-for-asynchronous'>Coroutines are not just for asynchronous</a></li><li><a href='#fibonnaci-generator'>Fibonnaci generator</a></li></ul>
</ul>
</li><li><a href='#evaluation-of-constexpr-coroutines'>Evaluation of constexpr coroutines</a></li><li><a href='#implementation-experience'>Implementation experience</a><ul>
<ul>
<li><a href='#alternative-implementation-approaches'>Alternative implementation approaches</a><ul>
<ul>
<li><a href='#byte-code-interpreter'>Byte-code interpreter</a></li><li><a href='#c++-coroutines'>C++ coroutines</a></li><li><a href='#ast-transformation-/-split'>AST transformation / split</a><ul>
<ul>
<li><a href='#standard-transformation'>Standard transformation</a></li><li><a href='#transformation-into-void-style-continuation'>Transformation into void-style continuation</a></li><li><a href='#loops-transformation'>Loops transformation</a></li><li><a href='#tail-recursion'>Tail-recursion</a></li></ul>
</ul>
</li><li><a href='#comparison'>Comparison</a></li></ul>
</ul>
</li></ul>
</ul>
</li><li><a href='#impact-on-existing-code'>Impact on existing code</a></li><li><a href='#intention-for-wording-changes'>Intention for wording changes</a></li><li><a href='#proposed-wording-changes'>Proposed wording changes</a><ul>
<ul>
<li><a href='#feature-test-macros'>Feature test macros</a></li></ul>
</ul>
</li></ul>
</div>
</div></div></nav>
<article>
<div><div>
	<h1 class="hide-on-narrow name-of-paper" id="introduction">constexpr coroutines</h1>
	
	<p>This paper is proposing making coroutines functional during constant evaluation. Even when most of use-cases for coroutines are based on I/O and event based, coroutines are still useful for compile-time based computation, eg. <code>std::generator</code>.</p>
	<h2 id='changes'><a href='#changes'>Changes</a></h2>
	<ul>
    <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3367r3.html">R3</a>&#x2005;→&#x2005;R4: <a href="#5.22">allow <code>co_await</code> and <code>co_yield</code> only within coroutine evaluation</a></li>
		<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3367r2.html">R2</a>&#x2005;→&#x2005;<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3367r3.html">R3</a>: <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3367r3.html">added motivation text</a>, <a href="https://isocpp.org/files/papers/P3367R3.html#standard-transformation">added AST transform approach examples</a></li>
		<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3367r1.html">R1</a>&#x2005;→&#x2005;<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3367r2.html">R2</a>: <a href="#elide-allocation-wording">Updated wording to elide allocator functionality in coroutine promise types.</a> <a href="#alternative-implementation-approaches">Added discussion about alternative implementation strategies.</a> <a href="timeline">Added information about decision by various groups which seen this paper.</a></li>
		<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3372r0.html">R0</a>&#x2005;→&#x2005;<a href="https://wg21.link/p3372r1">R1</a>: Changed wording mentioning lifetime of coroutines after expr.const 5.2</li>
	</ul>
	<h2 id='timeline'><a href='#timeline'>Timeline</a></h2>
	<h4>EWG in Wroclaw</h4>
	<div><strong>Poll:</strong> P3367 constexpr coroutines send to CWG and LEWG for inclusion for C++26</div>
	<table class="poll">
		<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
		<tr><td>4</td><td>12</td><td>3</td><td>0</td><td>0</td></tr>
	</table>
	<p>Result: Consensus</p>

	<h4>LEWG in Wroclaw</h4>
	<div><strong>Poll:</strong> Forward P3367R1 to LWG for C++26</div>
	<table class="poll">
		<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
		<tr><td>12</td><td>5</td><td>0</td><td>0</td><td>0</td></tr>
	</table>
	<p>Result: Unanimous consent</p>
	
	<h4>CWG in Wroclaw</h4>
	<blockquote>
	<p>Multiple implementers expressed concerns about resources needed for the implementation of this feature, where the resources might be better spent implementing C++ features where market demand is higher.</p>

	<p>EWG is requested to reconsider putting this feature into the standard.</p>
	</blockquote>
	<p><strong>Note:</strong> CWG did review of the wording and only question was about what to do with allocation / deallocation functions. Wording was updated to elide these calls during constant evaluation of a coroutine. Concern about resources was reflected by updating the paper to contain informations about alternative implementation strategies.</p>
	<p>Based on anecdotal evidence people don't use coroutines for two reasons: one is missing standard library support (which is partially resolved with <code>std::generator</code>) and second is mutual exclusivity with much more popular constant evaluated code. Having constant evaluation of couroutines will help alleviate this and I do expect seeing libraries implementing lazy coroutine based parsers.</p>
  
	<h4>EWG in Hagenberg</h4>
	<div><strong>Poll:</strong> P3367R3: constexpr coroutines: Forward to CWG for inclusion in C++26</div>
	<table class="poll">
		<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
		<tr><td>2</td><td>2</td><td>15</td><td>23</td><td>5</td></tr>
	</table>
	<p>Result: Consensus against</p>
  
	<div><strong>Poll:</strong> P3367R3: constexpr coroutines: Forward to CWG for inclusion in C++29</div>
	<table class="poll">
		<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
		<tr><td>13</td><td>23</td><td>12</td><td>3</td><td>1</td></tr>
	</table>
	<p>Result: Consensus</p>
  <p><strong>Dissent</strong> <ul>
    <li>Still premature, needs implementation work beyond time horizon</li>
    <li>Competes with unknown workload from other C++29 features</li>
  </ul></p>
  
	<h2 id='quote'><a href='#quote'>Quote</a></h2>
  <p>Well, you just told me coroutines are the best way to solve some problems, so wouldn't I also want to use the Best Way at compile time? (quote from Jason Turner, co-author of <em>"constexpr all the things"</em> talk)</p>
	<h2 id='motivation'><a href='#motivation'>Motivation</a></h2>
	<p>Currently C++'s <a href="https://eel.is/c++draft/dcl.constexpr#3.1">doesn't allow coroutines to be <code>constexpr</code></a>. This limitation forces users to choose between having <code>constexpr</code> compatible library or (maybe) simpler coroutine interface. As a library author I do prefer <code>constexpr</code> but I do not want to make this decision.</p>
	<p>I think this limitation and weak library support for coroutines are main limiting factors for bigger adoption of coroutines. I personally want to be able to write <a href="https://github.com/hanickadot/compile-time-regular-expressions">CTRE</a> coroutine interface which allows partially process input on a regular expression state and continue later when it will be resumed.</p>
	<h3 id='coroutines-are-not-just-for-asynchronous'><a href='#coroutines-are-not-just-for-asynchronous'>Coroutines are not just for asynchronous</a></h3>
	<p>Most people see uses for coroutines for asynchronous and event based programming. Coroutines are useful for parsers, modeling clock-perfect timing in emulators, and generally any state machines.</p>
	<h3 id='fibonnaci-generator'><a href='#fibonnaci-generator'>Fibonnaci generator</a></h3>
	<p>When this paper is merged into the standard, users will be able to use <code>std::generator</code>-like coroutines to generate or calculate data.</p>
  <pre><code class="language-cpp">template &lt;typename T&gt; constexpr auto fib() -> std::generator&lt;T&gt; {
    T a = 0;
    T b = 1;
    co_yield a;
    do {
        co_yield b;
        auto tmp = b;
        b += a;
        a = tmp;
    } while (true);
}

template &lt;typename T, size_t N&gt; constexpr auto calculate_fibonnaci() {
    auto res = std::array&lt;T, N&gt;{};
    std::ranges::copy(fib&lt;T&gt;() | std::views::take(N), res.begin());
    return res;
}

constexpr auto cached_fibonnaci = calculate_fibonnaci&lt;unsigned, 20&gt;();</code></pre>
	<h2 id='evaluation-of-constexpr-coroutines'><a href='#evaluation-of-constexpr-coroutines'>Evaluation of constexpr coroutines</a></h2>
	<p>Implementation must make sure to avoid stack exhaustion and store evaluation state and coroutine's local variables in a way to avoid it. By simply resuming coroutine and evaluating it on system stack (in case of AST walking implementations) will lead to it.</p>
	<div class='svgimg'><div><?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="529.24" height="415.5" viewBox="0 0 529.24 415.5">
  <g id="boxes">
    <path d="M345.93,373.02s-9.32-2.69-30.01-2.69-30.01,2.69-30.01,2.69V37.42h60.02v335.6Z" fill="#fafafa" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="4.45" y="92.56" width="221.47" height="318.13" fill="#fafafa" stroke="#050505" stroke-miterlimit="10"/>
  </g>
  <g id="special">
    <line x1="371.18" y1="37.42" x2="258.61" y2="373.02" fill="none" stroke="red" stroke-miterlimit="10" stroke-width="12"/>
    <line x1="262.39" y1="39.95" x2="374.96" y2="375.55" fill="none" stroke="red" stroke-miterlimit="10" stroke-width="12"/>
  </g>
  <g id="black-outline">
    <rect x="65.93" y="52.18" width="19.14" height="19.14" fill="#c7eafb" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="65.93" y="4.81" width="19.14" height="19.14" fill="#c7eafb" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="152.78" y="354.72" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="65.93" y="117.87" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="85.07" y="165.24" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="65.93" y="212.61" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="85.07" y="307.52" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <g>
      <rect x="104.21" y="212.61" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="152.78 230.75 152.78 231.75 151.78 231.75" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="149.75" y1="231.75" x2="106.22" y2="231.75" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="105.21 231.75 104.21 231.75 104.21 230.75" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="104.21" y1="228.85" x2="104.21" y2="214.56" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="104.21 213.61 104.21 212.61 105.21 212.61" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="107.23" y1="212.61" x2="150.77" y2="212.61" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="151.78 212.61 152.78 212.61 152.78 213.61" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="152.78" y1="215.52" x2="152.78" y2="229.8" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <rect x="118.92" y="259.98" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="41.56" width="19.14" height="19.14" fill="#c7eafb" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="66.02" width="19.14" height="19.14" fill="#c7eafb" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="90.47" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="114.93" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <g>
      <rect x="291.63" y="139.38" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="340.2 157.52 340.2 158.52 339.2 158.52" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="337.18" y1="158.52" x2="293.65" y2="158.52" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="292.63 158.52 291.63 158.52 291.63 157.52" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="291.63" y1="155.62" x2="291.63" y2="141.33" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="291.63 140.38 291.63 139.38 292.63 139.38" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="294.66" y1="139.38" x2="338.19" y2="139.38" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="339.2 139.38 340.2 139.38 340.2 140.38" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="340.2" y1="142.29" x2="340.2" y2="156.57" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <rect x="306.35" y="163.84" width="19.14" height="19.14" fill="#f49ac1" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="188.29" width="19.14" height="19.14" fill="#f49ac1" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="212.75" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <rect x="306.35" y="261.65" width="19.14" height="19.14" fill="#b5dec8" stroke="#050505" stroke-miterlimit="10"/>
    <g>
      <rect x="291.63" y="286.11" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="340.2 304.25 340.2 305.25 339.2 305.25" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="337.18" y1="305.25" x2="293.65" y2="305.25" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="292.63 305.25 291.63 305.25 291.63 304.25" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="291.63" y1="302.35" x2="291.63" y2="288.06" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="291.63 287.11 291.63 286.11 292.63 286.11" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="294.66" y1="286.11" x2="338.19" y2="286.11" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="339.2 286.11 340.2 286.11 340.2 287.11" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="340.2" y1="289.01" x2="340.2" y2="303.3" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="contrast-black-outline">
    <g>
      <rect x="138.06" y="307.69" width="48.57" height="19.14" fill="#b900ff"/>
      <g>
        <polyline points="186.63 325.83 186.63 326.83 185.63 326.83" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="183.61" y1="326.83" x2="140.08" y2="326.83" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="139.06 326.83 138.06 326.83 138.06 325.83" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="138.06" y1="323.92" x2="138.06" y2="309.64" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="138.06 308.69 138.06 307.69 139.06 307.69" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="141.09" y1="307.69" x2="184.62" y2="307.69" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="185.63 307.69 186.63 307.69 186.63 308.69" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="186.63" y1="310.59" x2="186.63" y2="324.87" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="16.12" y="165.24" width="48.57" height="19.14" fill="#b900ff"/>
      <g>
        <polyline points="64.69 183.38 64.69 184.38 63.69 184.38" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="61.67" y1="184.38" x2="18.14" y2="184.38" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="17.12 184.38 16.12 184.38 16.12 183.38" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="16.12" y1="181.48" x2="16.12" y2="167.2" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="16.12 166.24 16.12 165.24 17.12 165.24" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="19.15" y1="165.24" x2="62.68" y2="165.24" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="63.69 165.24 64.69 165.24 64.69 166.24" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="64.69" y1="168.15" x2="64.69" y2="182.43" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <circle cx="40.41" cy="222.18" r="9.57" fill="#b900ff" stroke="#050505" stroke-miterlimit="10"/>
    <circle cx="75.5" cy="269.55" r="9.57" fill="#b900ff" stroke="#050505" stroke-miterlimit="10"/>
    <circle cx="94.64" cy="364.29" r="9.57" fill="#b900ff" stroke="#050505" stroke-miterlimit="10"/>
    <g>
      <rect x="291.63" y="237.2" width="48.57" height="19.14" fill="#b900ff"/>
      <g>
        <polyline points="340.2 255.34 340.2 256.34 339.2 256.34" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="337.18" y1="256.34" x2="293.65" y2="256.34" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="292.63 256.34 291.63 256.34 291.63 255.34" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="291.63" y1="253.44" x2="291.63" y2="239.15" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="291.63 238.2 291.63 237.2 292.63 237.2" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="294.66" y1="237.2" x2="338.19" y2="237.2" fill="none" stroke="#050505" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="339.2 237.2 340.2 237.2 340.2 238.2" fill="none" stroke="#050505" stroke-miterlimit="10"/>
        <line x1="340.2" y1="240.1" x2="340.2" y2="254.39" fill="none" stroke="#050505" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="black-lines">
    <path d="M328.31,41.56c20.44,0,20.88,21.8,40.2,21.8-19.75,0-20.1,21.8-40.2,21.8" fill="none" stroke="#050505" stroke-miterlimit="10"/>
    <path d="M328.31,90.47c35.09,0,20.88,21.8,40.2,21.8-19.75,0-5.04,46.25-25.14,46.25" fill="none" stroke="#050505" stroke-miterlimit="10"/>
    <path d="M328.31,163.84c20.44,0,20.88,21.8,40.2,21.8-19.75,0-20.1,21.8-40.2,21.8" fill="none" stroke="#050505" stroke-miterlimit="10"/>
    <path d="M328.79,212.75c34.17,0,18.99,46.25,38.31,46.25-19.75,0-3.22,46.25-23.32,46.25" fill="none" stroke="#050505" stroke-miterlimit="10"/>
    <g>
      <line x1="75.5" y1="231.75" x2="75.5" y2="253.34" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="73.32 251.85 75.5 259.98 77.68 251.85 73.32 251.85" fill="#050505"/>
    </g>
    <g>
      <line x1="94.64" y1="326.49" x2="94.64" y2="348.08" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="92.46 346.59 94.64 354.72 96.82 346.59 92.46 346.59" fill="#050505"/>
    </g>
    <g>
      <line x1="75.5" y1="111.23" x2="75.5" y2="71.32" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="77.68 109.74 75.5 117.87 73.32 109.74 77.68 109.74" fill="#050505"/>
    </g>
    <g>
      <line x1="75.5" y1="23.95" x2="75.5" y2="45.53" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="73.32 44.05 75.5 52.18 77.68 44.05 73.32 44.05" fill="#050505"/>
    </g>
    <g>
      <line x1="162.35" y1="326.99" x2="162.35" y2="348.58" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="160.17 347.09 162.35 355.22 164.53 347.09 160.17 347.09" fill="#050505"/>
    </g>
    <g>
      <path d="M129.02,205.98c3.18-19.95,20.46-35.19,41.3-35.19,23.1,0,41.82,18.72,41.82,41.82v161.66c0,13.75-11.14,24.89-24.89,24.89s-24.89-11.14-24.89-24.89" fill="none" stroke="#050505" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="131.41 204.72 128.49 212.61 127.07 204.32 131.41 204.72" fill="#050505"/>
    </g>
    <g>
      <path d="M75.5,137.01c0,16.94-26.05,11.44-33.26,21.83" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="40.84 156.84 40.41 165.24 44.99 158.18 40.84 156.84" fill="#050505"/>
    </g>
    <g>
      <path d="M75.5,137.01c0,16.5,14.08,11.38,18.09,21.66" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="91.02 157.64 94.64 165.24 95.3 156.85 91.02 157.64" fill="#050505"/>
    </g>
    <g>
      <path d="M94.64,184.38c0,15.9-14.11,11.2-18.1,21.66" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="74.81 204.22 75.5 212.61 79.09 205 74.81 204.22" fill="#050505"/>
    </g>
    <g>
      <path d="M128.49,279.29c0,16.08-25.18,11.19-32.11,21.81" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="94.95 299.11 94.64 307.52 99.12 300.39 94.95 299.11" fill="#050505"/>
    </g>
    <g>
      <path d="M123.79,206.16c-6.34-10.51-29.15-5.46-29.15-21.78" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="125.28 204.2 125.41 212.61 121.09 205.39 125.28 204.2" fill="#050505"/>
    </g>
    <g>
      <path d="M128.49,279.29c0,16.44,25.15,11.29,32.1,21.81" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="157.85 300.4 162.35 307.52 162.01 299.11 157.85 300.4" fill="#050505"/>
    </g>
    <g>
      <line x1="128.49" y1="231.75" x2="128.49" y2="253.34" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="126.31 251.85 128.49 259.98 130.67 251.85 126.31 251.85" fill="#050505"/>
    </g>
    <g>
      <line x1="40.41" y1="184.38" x2="40.41" y2="205.97" fill="none" stroke="#050505" stroke-miterlimit="10"/>
      <polygon points="38.23 204.48 40.41 212.61 42.59 204.48 38.23 204.48" fill="#050505"/>
    </g>
  </g>
  <g id="text">
    <text transform="translate(71.82 131.15)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(90.63 178.52)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
    <text transform="translate(71.16 225.89)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">C</tspan></text>
    <text transform="translate(90.63 320.8)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">E</tspan></text>
    <text transform="translate(105.81 225.89)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(124.16 273.26)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
    <text transform="translate(71.6 65.46)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.02em"><tspan x="0" y="0">Y</tspan></text>
    <text transform="translate(71.49 18.09)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">X</tspan></text>
    <text transform="translate(158.68 368)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(311.92 54.84)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">X</tspan></text>
    <text transform="translate(312.02 79.3)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.02em"><tspan x="0" y="0">Y</tspan></text>
    <text transform="translate(312.24 103.75)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(311.92 128.21)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
    <text transform="translate(293.23 152.66)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(311.58 226.03)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
    <text transform="translate(312.58 177.12)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(312.58 201.57)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(312.25 274.94)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(293.23 299.39)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
  <g id="info">
    <text transform="translate(373.36 66.25)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">non-coroutine code</tspan></text>
    <text transform="translate(372.98 114.93)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspended coroutine code</tspan></text>
    <text transform="translate(371.32 188.29)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">non-coroutine code</tspan></text>
    <text transform="translate(372.98 261.65)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">coroutine code</tspan></text>
    <text transform="translate(171.52 106.7)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">coroutine</tspan></text>
    <text transform="translate(296.92 333.8)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">system</tspan><tspan x="5" y="14.4">stack</tspan></text>
    <text transform="translate(372.09 173.41)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">(unrelated)</tspan></text>
  </g>
  <g id="contrast-text">
    <text transform="translate(17.72 178.52)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(33.41 225.89)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(68.49 273.26)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(87.64 368)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(139.66 320.97)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(293.23 250.48)" fill="#050505" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
</svg></div></div>	<p>This is because coroutines can be interlieved and their state must be maintained to be resumed. The stack then contains mixed coroutines and normal code together. To avoid this situation the easiest way to model a coroutine is to use coroutine (or coroutine-like functionality) to store the state (represented with values on stack) somewhere else. Because AST walk is unbounded, obvious first choice is a stackfull coroutine (fiber, not a thread!).</p>
	<p>Lifetime of coroutine is bounded to be only within constant evaluation similary as memory allocation. Any coroutine leaking outside boundaries of constant evaluation means whole constant evalution failed.</p>
	<div class='svgimg'><div><?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="420.31" height="226.56" viewBox="0 0 420.31 226.56">
  <g id="boxes">
    <path d="M412.41,218.89s-9.32-2.69-30.01-2.69-30.01,2.69-30.01,2.69V7.67h60.02v211.21Z" fill="#fff" opacity=".5" stroke="#231f20" stroke-miterlimit="10"/>
    <path d="M208.8,219.53s-9.32-2.69-30.01-2.69-30.01,2.69-30.01,2.69V8.32h60.02v211.21Z" fill="#fff" opacity=".5" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="black-outline">
    <rect x="169.21" y="12.89" width="19.14" height="19.14" fill="#c7eafb" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="169.21" y="37.34" width="19.14" height="19.14" fill="#c7eafb" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="169.21" y="60.74" width="19.14" height="19.14" fill="#f49ac1" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="169.21" y="85.19" width="19.14" height="19.14" fill="#f49ac1" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="373.99" y="86.68" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="373.99" y="135.59" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="373.39" y="12.89" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="373.39" y="37.34" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <g>
      <rect x="359.28" y="160.04" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="407.85 178.18 407.85 179.18 406.85 179.18" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="404.82" y1="179.18" x2="361.29" y2="179.18" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="360.28 179.18 359.28 179.18 359.28 178.18" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="359.28" y1="176.28" x2="359.28" y2="161.99" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="359.28 161.04 359.28 160.04 360.28 160.04" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="362.3" y1="160.04" x2="405.84" y2="160.04" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="406.85 160.04 407.85 160.04 407.85 161.04" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="407.85" y1="162.94" x2="407.85" y2="177.23" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="358.68" y="61.8" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="407.25 79.94 407.25 80.94 406.25 80.94" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="404.22" y1="80.94" x2="360.69" y2="80.94" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="359.68 80.94 358.68 80.94 358.68 79.94" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="358.68" y1="78.04" x2="358.68" y2="63.75" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="358.68 62.8 358.68 61.8 359.68 61.8" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="361.7" y1="61.8" x2="405.24" y2="61.8" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="406.25 61.8 407.25 61.8 407.25 62.8" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="407.25" y1="64.7" x2="407.25" y2="78.99" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="contrast-black-outline">
    <g>
      <rect x="359.28" y="111.13" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="407.85 129.27 407.85 130.27 406.85 130.27" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="404.82" y1="130.27" x2="361.29" y2="130.27" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="360.28 130.27 359.28 130.27 359.28 129.27" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="359.28" y1="127.37" x2="359.28" y2="113.08" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="359.28 112.13 359.28 111.13 360.28 111.13" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="362.3" y1="111.13" x2="405.84" y2="111.13" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="406.85 111.13 407.85 111.13 407.85 112.13" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="407.85" y1="114.04" x2="407.85" y2="128.32" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="contrast-text">
    <text transform="translate(360.88 124.41)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
  <g id="black-lines">
    <g>
      <path d="M356.41,70.94c-59.08-14.34-79.62,6.02-142.48-8.15" fill="none" stroke="#231f20" stroke-miterlimit="10" stroke-width="2"/>
      <polygon points="219.32 58.28 215.75 63.14 216.77 69.09 205.23 60.66 219.32 58.28" fill="#231f20"/>
    </g>
    <g>
      <path d="M197.68,58.08c70.33-9.04,95.63-58.8,161.56-39.05" fill="none" stroke="#231f20" stroke-miterlimit="10" stroke-width="2"/>
      <polygon points="369.27 22.46 353.18 23.53 358.47 18.86 357.04 11.96 369.27 22.46" fill="#231f20"/>
    </g>
    <g>
      <path d="M197.68,105.82c85.54,7.96,104.71-26.54,148.14-30.42" fill="none" stroke="#231f20" stroke-miterlimit="10" stroke-width="2"/>
      <polygon points="356.41 75.08 341.74 81.76 345.04 75.53 341.26 69.57 356.41 75.08" fill="#231f20"/>
    </g>
    <g>
      <path d="M355.19,169.61c-86.72,10.84-89.13-40.3-148.78-56.46" fill="none" stroke="#231f20" stroke-miterlimit="10" stroke-width="2"/>
      <polygon points="211.79 108.82 208.19 113.67 209.18 119.62 197.68 111.13 211.79 108.82" fill="#231f20"/>
    </g>
    <path d="M165.68,12.36c-20.44,0-20.88,21.8-40.2,21.8,19.75,0,20.1,21.8,40.2,21.8" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
    <path d="M165.68,60.21c-20.44,0-20.88,21.8-40.2,21.8,19.75,0,20.1,21.8,40.2,21.8" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="text">
    <text transform="translate(174.78 26.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">X</tspan></text>
    <text transform="translate(174.89 50.63)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.02em"><tspan x="0" y="0">Y</tspan></text>
    <text transform="translate(175.45 74.02)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(175.45 98.47)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(379.23 99.96)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
    <text transform="translate(379.9 148.87)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(360.88 173.32)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(379.29 26.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(378.96 50.63)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
    <text transform="translate(360.28 75.08)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
  <g id="info">
    <text transform="translate(17.83 37.8)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">non-coroutine code</tspan></text>
    <text transform="translate(16.84 85.19)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">non-coroutine code</tspan></text>
    <text transform="translate(231.43 45.83) rotate(-25.4)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">switch stack</tspan></text>
    <text transform="translate(159.78 196.8)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">system</tspan><tspan x="5" y="14.4">stack</tspan></text>
    <text transform="translate(360.72 196.8)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">stackfull</tspan><tspan x="-3.01" y="14.4">coroutine</tspan></text>
    <text transform="translate(61 70.94)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">(unrelated)</tspan></text>
  </g>
</svg></div></div>	<h2 id='implementation-experience'><a href='#implementation-experience'>Implementation experience</a></h2>
  <p>Partially implemented in clang available on my <a href="https://github.com/hanickadot/llvm-project/tree/P3367-constexpr-coroutines">github</a>, implementation should be ready for its presentation at Wroclaw meeting, and also will be soon available on compiler explorer (thanks Matt!).</p>
  <p>Most of functionality needed was already present in Clang, it was mostly about removing checks in the parser.</p>
  <p>Another part was implementing the functionality in Clang's interpreter and there I needed to add fibers (stackfull coroutines) as the interpreter recursive walks over AST. Ability to save interpreter's stack content did minimize impact of the change to only resuming, suspending, and variable storage and life-time management.</p>
  <p>At the end of evaluation the interpret needs to check objects holding fibers if there is still any coroutine not released, if there is it report similar error as when there is an unreleased memory allocation.</p>
  <p>Hardest problem was implementing local "stack", as <code>createLocal</code> function was designed around idea of having only one branch of evaluation. This I solved by providing context of currently evaluated coroutine in <code>EvalInfo</code> and switching it on every suspension / resume of a coroutine.</p>
	<h3 id='alternative-implementation-approaches'><a href='#alternative-implementation-approaches'>Alternative implementation approaches</a></h3>
	<p>The implementation is using fibers (not threads!) to create a storage for execution of coroutines outside of main stack. Main requirement here is to make sure jumping between coroutines won't run out of the system stack.</p>
	<p>Following subpart of paper shows alternative approaches which can model coroutines. All of them have same expressive ability and model coroutines well. These implementation has various advantages and costs. For every model of constant evaluation should be possible found good and usable match.</p>
	<h4 id='byte-code-interpreter'><a href='#byte-code-interpreter'>Byte-code interpreter</a></h4>
	<p><a href="https://clang.llvm.org/docs/ConstantInterpreter.html">Clang implementation</a> is starting to use a byte-code virtual machine based interpreter. In such implementation the implementation approach is identical for actually compiling coroutines to a native code. Only thing you need is ability to change current stack / or reference coroutine variables based on offset to coroutine frame.</p>
	<p>Such interpret has many advantages over AST walking one mostly in speed and security. I was told initial measurements in the byte-code interpreter in clang are three orders of magnitude faster over recursive AST walking. Security is inherit to fact of not using system stack for the evaluation at all.</p>
	<h4 id='c++-coroutines'><a href='#c++-coroutines'>C++ coroutines</a></h4>
	<p>For compilers which are using C++20 code itself another implementation strategy is to not use the system stack for walking AST, but change all necessory functions into coroutines which would model ordinary functions with only one return point to its callee. But these functions can be suspended and evaluation can switch to evaluation of a constexpr coroutine. Because all coroutines will be allocated on heap, this also hardens implementation's constexpr evaluator.</p>
	<div class='svgimg'><div><?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="537.4" height="156.6" viewBox="0 0 537.4 156.6">
  <g id="black-outline">
    <rect x="270.62" y="15.39" width="19.14" height="19.14" fill="#c7eafb" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="270.62" y="48.88" width="19.14" height="19.14" fill="#c7eafb" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="270.62" y="82.38" width="19.14" height="19.14" fill="#f49ac1" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="271.08" y="115.87" width="19.14" height="19.14" fill="#f49ac1" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="378.5" y="82.47" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="378.5" y="115.87" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="378.5" y="15.39" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="378.5" y="48.88" width="19.14" height="19.14" fill="#b5dec8" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="contrast-black-outline">
    <g>
      <rect x="320.7" y="115.87" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="369.27 134.01 369.27 135.01 368.27 135.01" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="366.24" y1="135.01" x2="322.71" y2="135.01" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="321.7 135.01 320.7 135.01 320.7 134.01" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="320.7" y1="132.11" x2="320.7" y2="117.82" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="320.7 116.87 320.7 115.87 321.7 115.87" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="323.72" y1="115.87" x2="367.26" y2="115.87" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="368.27 115.87 369.27 115.87 369.27 116.87" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="369.27" y1="118.78" x2="369.27" y2="133.06" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="320.7" y="48.88" width="48.57" height="19.14" fill="#fbb040"/>
      <g>
        <polyline points="369.27 67.02 369.27 68.02 368.27 68.02" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="366.24" y1="68.02" x2="322.71" y2="68.02" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="321.7 68.02 320.7 68.02 320.7 67.02" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="320.7" y1="65.12" x2="320.7" y2="50.84" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="320.7 49.88 320.7 48.88 321.7 48.88" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="323.72" y1="48.88" x2="367.26" y2="48.88" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="368.27 48.88 369.27 48.88 369.27 49.88" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="369.27" y1="51.79" x2="369.27" y2="66.07" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="black-lines">
    <g>
      <line x1="280.19" y1="48.88" x2="280.19" y2="36.2" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="281.89 38.2 280.19 36.5 278.5 38.2 278.5 36.76 280.19 35.06 281.89 36.76 281.89 38.2" fill="#231f20"/>
    </g>
    <g>
      <line x1="280.19" y1="82.38" x2="280.05" y2="69.44" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="281.77 71.42 280.06 69.74 278.38 71.45 278.37 70.01 280.04 68.3 281.76 69.98 281.77 71.42" fill="#231f20"/>
    </g>
    <g>
      <line x1="388.07" y1="48.88" x2="388.07" y2="36.2" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="389.77 38.2 388.07 36.5 386.38 38.2 386.38 36.76 388.07 35.06 389.77 36.76 389.77 38.2" fill="#231f20"/>
    </g>
    <g>
      <line x1="388.07" y1="81.85" x2="388.07" y2="69.17" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="389.77 71.16 388.07 69.46 386.38 71.16 386.38 69.72 388.07 68.02 389.77 69.72 389.77 71.16" fill="#231f20"/>
    </g>
    <g>
      <line x1="388.07" y1="115.87" x2="388.07" y2="102.75" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="389.77 104.75 388.07 103.05 386.38 104.75 386.38 103.31 388.07 101.61 389.77 103.31 389.77 104.75" fill="#231f20"/>
    </g>
    <g>
      <path d="M289.76,55.4c.16.02.33.05.49.07" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <path d="M291.24,55.58c23.34,2.23,15.15-29.96,85.1-30.61" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <path d="M376.86,24.97c.17,0,.33,0,.5,0" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="375.42 26.75 377.07 25 375.32 23.36 376.76 23.32 378.5 24.96 376.86 26.7 375.42 26.75" fill="#231f20"/>
    </g>
    <g>
      <path d="M378.5,58.45c-2.89-1.51-6.41-.84-8.15-.35" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="371.77 55.91 370.64 58.03 372.76 59.15 371.39 59.58 369.27 58.45 370.39 56.33 371.77 55.91" fill="#231f20"/>
    </g>
    <g>
      <path d="M320.7,58.45c-11.45-2.06-11.79,9.25-29.86,3.08" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="293.27 60.51 291.13 61.6 292.22 63.73 290.85 63.29 289.76 61.15 291.9 60.07 293.27 60.51" fill="#231f20"/>
    </g>
    <g>
      <line x1="280.27" y1="115.78" x2="280.13" y2="102.85" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="281.85 104.82 280.13 103.14 278.46 104.86 278.44 103.42 280.12 101.7 281.83 103.38 281.85 104.82" fill="#231f20"/>
    </g>
    <g>
      <path d="M290.22,125.44c10.62,3.05,10.37-29.89,26.75-43.6,9.23-7.72,23.9-9.73,41.32-6.51,16.73,3.1,10.4-11.83,19.07-12" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="375.31 64.98 377.07 63.35 375.43 61.59 376.87 61.64 378.5 63.4 376.75 65.03 375.31 64.98" fill="#231f20"/>
    </g>
    <g>
      <path d="M378.5,124.98c-2.89-1.51-6.41-.84-8.15-.35" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="371.77 122.43 370.64 124.55 372.76 125.67 371.39 126.1 369.27 124.98 370.39 122.86 371.77 122.43" fill="#231f20"/>
    </g>
    <g>
      <path d="M320.7,125.7c-11.47-2.06-8.82,5.83-29.8,2.86" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="293.09 127.12 291.19 128.58 292.65 130.48 291.22 130.29 289.76 128.39 291.67 126.93 293.09 127.12" fill="#231f20"/>
    </g>
    <path d="M408.44,16.19c20.44,0,18.76,59.15,38.08,59.15-19.75,0-17.98,59.28-38.08,59.28" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
    <path d="M254.41,15.45c-20.44,0-20.88,26.13-40.2,26.13,19.75,0,20.1,26.05,40.2,26.05" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
    <path d="M253.98,83.05c-20.44,0-18.76,24.17-38.08,24.17,19.75,0,17.64,27.39,37.73,27.39" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
    <g>
      <line x1="265.77" y1="7.44" x2="265.77" y2="142.51" fill="none" stroke="#00aeef" stroke-miterlimit="10"/>
      <polygon points="260.78 141.05 265.77 149.69 270.75 141.05 260.78 141.05" fill="#00aeef"/>
    </g>
    <g>
      <line x1="403.04" y1="7.44" x2="403.04" y2="142.51" fill="none" stroke="#00aeef" stroke-miterlimit="10"/>
      <polygon points="398.06 141.05 403.04 149.69 408.03 141.05 398.06 141.05" fill="#00aeef"/>
    </g>
  </g>
  <g id="boxes">
    <path d="M74.38,146.33s-9.32-2.69-30.01-2.69-30.01,2.69-30.01,2.69V9.39h60.02v136.94Z" fill="#fff" opacity=".5" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="info">
    <text transform="translate(20.68 108.74)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">(unused)</tspan><tspan x="4.68" y="14.4">system</tspan><tspan x="9.68" y="28.8">stack</tspan></text>
    <text transform="translate(107.06 44.36)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">non-coroutine code</tspan></text>
    <g>
      <path d="M154.88,86.65c-.61,1.19-1.01,2.07-1.2,2.63-.28.86-.42,1.84-.42,2.96s.16,2.17.47,3.11c.2.58.58,1.41,1.15,2.5h-.71c-.57-.89-.92-1.46-1.06-1.71s-.29-.58-.45-1c-.22-.58-.37-1.2-.46-1.85-.04-.34-.06-.66-.06-.97,0-1.16.18-2.19.54-3.09.23-.57.71-1.43,1.44-2.58h.73Z" fill="#231f20"/>
      <path d="M157.16,89.12v4.17c0,.32.05.58.15.79.18.38.52.56,1.02.56.71,0,1.2-.33,1.46-.98.14-.35.21-.83.21-1.45v-3.08h1.05v6.28h-1v-.93c-.12.24-.29.44-.49.6-.39.33-.87.49-1.44.49-.88,0-1.48-.3-1.79-.9-.17-.32-.26-.75-.26-1.28v-4.27h1.08Z" fill="#231f20"/>
      <path d="M162.78,89.12h1v.89c.3-.37.61-.63.94-.79s.7-.24,1.11-.24c.89,0,1.49.31,1.8.93.17.34.26.83.26,1.46v4.03h-1.07v-3.96c0-.38-.06-.69-.17-.93-.19-.39-.53-.59-1.02-.59-.25,0-.46.03-.62.08-.29.09-.54.26-.76.52-.18.21-.29.42-.34.64s-.08.54-.08.95v3.29h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M169.48,89.12h1v1.08c.08-.21.28-.47.6-.77s.69-.45,1.11-.45c.02,0,.05,0,.1,0s.13.01.24.02v1.11c-.06-.01-.12-.02-.17-.02s-.11,0-.17,0c-.53,0-.94.17-1.22.51s-.43.74-.43,1.18v3.61h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M177.32,89.29c.42.21.73.48.95.81.21.32.35.69.42,1.11.06.29.09.75.09,1.38h-4.56c.02.64.17,1.15.45,1.54.28.39.71.58,1.3.58.55,0,.98-.18,1.31-.55.18-.21.31-.46.39-.74h1.04c-.03.23-.12.49-.27.77s-.33.51-.52.69c-.32.31-.71.52-1.18.63-.25.06-.54.09-.85.09-.78,0-1.43-.28-1.97-.85-.54-.57-.81-1.36-.81-2.39s.27-1.83.82-2.46c.54-.63,1.25-.94,2.13-.94.44,0,.87.1,1.29.31ZM177.7,91.76c-.04-.46-.14-.82-.3-1.1-.29-.51-.77-.76-1.44-.76-.48,0-.88.17-1.21.52s-.5.79-.52,1.33h3.46Z" fill="#231f20"/>
      <path d="M180.15,86.79h1.05v8.61h-1.05v-8.61Z" fill="#231f20"/>
      <path d="M186.15,91.6c.24-.03.4-.13.49-.3.05-.09.07-.23.07-.41,0-.36-.13-.62-.38-.79-.26-.16-.62-.24-1.1-.24-.55,0-.94.15-1.17.45-.13.17-.21.41-.25.74h-.98c.02-.78.27-1.32.75-1.62.48-.3,1.04-.46,1.68-.46.74,0,1.34.14,1.8.42.46.28.68.72.68,1.31v3.62c0,.11.02.2.07.26.04.07.14.1.28.1.05,0,.1,0,.16,0s.12-.01.19-.03v.78c-.16.05-.29.08-.38.09s-.2.02-.35.02c-.36,0-.63-.13-.79-.39-.09-.14-.15-.33-.18-.58-.21.28-.52.53-.93.73s-.85.31-1.33.31c-.58,0-1.06-.18-1.43-.53s-.55-.79-.55-1.33c0-.58.18-1.03.54-1.35s.84-.52,1.43-.59l1.68-.21ZM183.93,94.45c.22.18.49.26.79.26.37,0,.73-.09,1.08-.26.59-.28.88-.75.88-1.4v-.85c-.13.08-.29.15-.5.21-.2.05-.4.09-.6.12l-.64.08c-.38.05-.67.13-.86.24-.33.18-.49.48-.49.88,0,.3.11.54.33.72Z" fill="#231f20"/>
      <path d="M189.67,87.37h1.07v1.75h1v.86h-1v4.1c0,.22.07.37.22.44.08.04.22.06.41.06.05,0,.11,0,.16,0s.13,0,.21-.02v.84c-.12.04-.25.06-.38.08s-.27.02-.42.02c-.49,0-.83-.13-1-.38s-.26-.58-.26-.98v-4.15h-.85v-.86h.85v-1.75Z" fill="#231f20"/>
      <path d="M196.67,89.29c.42.21.73.48.95.81.21.32.35.69.42,1.11.06.29.09.75.09,1.38h-4.56c.02.64.17,1.15.45,1.54.28.39.71.58,1.3.58.55,0,.98-.18,1.31-.55.18-.21.31-.46.39-.74h1.04c-.03.23-.12.49-.27.77s-.33.51-.52.69c-.32.31-.71.52-1.18.63-.25.06-.54.09-.85.09-.78,0-1.43-.28-1.97-.85-.54-.57-.81-1.36-.81-2.39s.27-1.83.82-2.46c.54-.63,1.25-.94,2.13-.94.44,0,.87.1,1.29.31ZM197.05,91.76c-.04-.46-.14-.82-.3-1.1-.29-.51-.77-.76-1.44-.76-.48,0-.88.17-1.21.52s-.5.79-.52,1.33h3.46Z" fill="#231f20"/>
      <path d="M202.91,89.31c.19.12.4.32.64.62v-3.17h1.01v8.64h-.95v-.87c-.25.39-.54.67-.87.84-.33.17-.72.26-1.15.26-.7,0-1.3-.29-1.81-.88s-.76-1.37-.76-2.35c0-.91.23-1.71.7-2.38.47-.67,1.13-1,1.99-1,.48,0,.88.1,1.2.3ZM200.56,94.02c.28.45.74.68,1.36.68.49,0,.89-.21,1.2-.63s.47-1.02.47-1.81-.16-1.38-.48-1.76-.72-.57-1.2-.57c-.53,0-.96.2-1.29.61-.33.41-.49,1-.49,1.79,0,.67.14,1.23.43,1.69Z" fill="#231f20"/>
      <path d="M205.78,97.84c.62-1.21,1.02-2.09,1.2-2.65.27-.84.41-1.82.41-2.95s-.16-2.16-.47-3.1c-.2-.58-.58-1.41-1.15-2.5h.71c.6.96.97,1.55,1.09,1.78s.26.53.41.93c.19.49.32.97.4,1.45s.12.94.12,1.38c0,1.16-.18,2.19-.55,3.09-.23.58-.71,1.44-1.44,2.57h-.73Z" fill="#231f20"/>
      <path d="M107.4,103.52h1v.89c.3-.37.61-.63.94-.79s.7-.24,1.11-.24c.89,0,1.49.31,1.8.93.17.34.26.83.26,1.46v4.03h-1.07v-3.96c0-.38-.06-.69-.17-.93-.19-.39-.53-.59-1.02-.59-.25,0-.46.03-.62.08-.29.09-.54.26-.76.52-.18.21-.29.42-.34.64s-.08.54-.08.95v3.29h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M118.62,104.15c.55.54.83,1.33.83,2.38s-.24,1.85-.73,2.51c-.49.66-1.25.99-2.27.99-.86,0-1.54-.29-2.04-.88s-.76-1.37-.76-2.35c0-1.05.27-1.89.8-2.52.53-.62,1.25-.94,2.14-.94.8,0,1.48.27,2.04.81ZM117.96,108.32c.26-.53.39-1.12.39-1.76,0-.58-.09-1.06-.28-1.43-.29-.58-.8-.87-1.52-.87-.64,0-1.1.25-1.39.74s-.43,1.08-.43,1.78.15,1.22.43,1.67.75.67,1.38.67c.69,0,1.17-.26,1.42-.79Z" fill="#231f20"/>
      <path d="M120.75,103.52h1v.89c.3-.37.61-.63.94-.79s.7-.24,1.11-.24c.89,0,1.49.31,1.8.93.17.34.26.83.26,1.46v4.03h-1.07v-3.96c0-.38-.06-.69-.17-.93-.19-.39-.53-.59-1.02-.59-.25,0-.46.03-.62.08-.29.09-.54.26-.76.52-.18.21-.29.42-.34.64s-.08.54-.08.95v3.29h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M127.14,105.91h2.94v1.08h-2.94v-1.08Z" fill="#231f20"/>
      <path d="M135.56,103.85c.44.34.71.94.8,1.78h-1.03c-.06-.39-.21-.71-.43-.96s-.58-.38-1.07-.38c-.67,0-1.15.33-1.44.98-.19.42-.28.95-.28,1.57s.13,1.16.4,1.59.68.64,1.25.64c.44,0,.78-.13,1.04-.4s.43-.63.53-1.09h1.03c-.12.83-.41,1.44-.88,1.83s-1.07.58-1.8.58c-.82,0-1.47-.3-1.96-.9s-.73-1.35-.73-2.25c0-1.1.27-1.96.8-2.57s1.22-.92,2.04-.92c.71,0,1.28.17,1.73.52Z" fill="#231f20"/>
      <path d="M141.96,104.15c.55.54.83,1.33.83,2.38s-.24,1.85-.73,2.51c-.49.66-1.25.99-2.27.99-.86,0-1.54-.29-2.04-.88s-.76-1.37-.76-2.35c0-1.05.27-1.89.8-2.52.53-.62,1.25-.94,2.14-.94.8,0,1.48.27,2.04.81ZM141.31,108.32c.26-.53.39-1.12.39-1.76,0-.58-.09-1.06-.28-1.43-.29-.58-.8-.87-1.52-.87-.64,0-1.1.25-1.39.74s-.43,1.08-.43,1.78.15,1.22.43,1.67.75.67,1.38.67c.69,0,1.17-.26,1.42-.79Z" fill="#231f20"/>
      <path d="M144.12,103.52h1v1.08c.08-.21.28-.47.6-.77s.69-.45,1.11-.45c.02,0,.05,0,.1,0s.13.01.24.02v1.11c-.06-.01-.12-.02-.17-.02s-.11,0-.17,0c-.53,0-.94.17-1.22.51s-.43.74-.43,1.18v3.61h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M152.63,104.15c.55.54.83,1.33.83,2.38s-.24,1.85-.73,2.51c-.49.66-1.25.99-2.27.99-.86,0-1.54-.29-2.04-.88s-.76-1.37-.76-2.35c0-1.05.27-1.89.8-2.52.53-.62,1.25-.94,2.14-.94.8,0,1.48.27,2.04.81ZM151.98,108.32c.26-.53.39-1.12.39-1.76,0-.58-.09-1.06-.28-1.43-.29-.58-.8-.87-1.52-.87-.64,0-1.1.25-1.39.74s-.43,1.08-.43,1.78.15,1.22.43,1.67.75.67,1.38.67c.69,0,1.17-.26,1.42-.79Z" fill="#231f20"/>
      <path d="M155.81,103.52v4.17c0,.32.05.58.15.79.18.38.52.56,1.02.56.71,0,1.2-.33,1.46-.98.14-.35.21-.83.21-1.45v-3.08h1.05v6.28h-1v-.93c-.12.24-.29.44-.49.6-.39.33-.87.49-1.44.49-.88,0-1.48-.3-1.79-.9-.17-.32-.26-.75-.26-1.28v-4.27h1.08Z" fill="#231f20"/>
      <path d="M161.64,101.77h1.07v1.75h1v.86h-1v4.1c0,.22.07.37.22.44.08.04.22.06.41.06.05,0,.11,0,.16,0s.13,0,.21-.02v.84c-.12.04-.25.06-.38.08s-.27.02-.42.02c-.49,0-.83-.13-1-.38s-.26-.58-.26-.98v-4.15h-.85v-.86h.85v-1.75Z" fill="#231f20"/>
      <path d="M164.77,101.19h1.07v1.2h-1.07v-1.2ZM164.77,103.55h1.07v6.25h-1.07v-6.25Z" fill="#231f20"/>
      <path d="M167.43,103.52h1v.89c.3-.37.61-.63.94-.79s.7-.24,1.11-.24c.89,0,1.49.31,1.8.93.17.34.26.83.26,1.46v4.03h-1.07v-3.96c0-.38-.06-.69-.17-.93-.19-.39-.53-.59-1.02-.59-.25,0-.46.03-.62.08-.29.09-.54.26-.76.52-.18.21-.29.42-.34.64s-.08.54-.08.95v3.29h-1.05v-6.28Z" fill="#231f20"/>
      <path d="M177.98,103.69c.42.21.73.48.95.81.21.32.35.69.42,1.11.06.29.09.75.09,1.38h-4.56c.02.64.17,1.15.45,1.54.28.39.71.58,1.3.58.55,0,.98-.18,1.31-.55.18-.21.31-.46.39-.74h1.04c-.03.23-.12.49-.27.77s-.33.51-.52.69c-.32.31-.71.52-1.18.63-.25.06-.54.09-.85.09-.78,0-1.43-.28-1.97-.85-.54-.57-.81-1.36-.81-2.39s.27-1.83.82-2.46c.54-.63,1.25-.94,2.13-.94.44,0,.87.1,1.29.31ZM178.36,106.16c-.04-.46-.14-.82-.3-1.1-.29-.51-.77-.76-1.44-.76-.48,0-.88.17-1.21.52s-.5.79-.52,1.33h3.46Z" fill="#231f20"/>
      <path d="M188.26,103.85c.44.34.71.94.8,1.78h-1.03c-.06-.39-.21-.71-.43-.96s-.58-.38-1.07-.38c-.67,0-1.15.33-1.44.98-.19.42-.28.95-.28,1.57s.13,1.16.4,1.59.68.64,1.25.64c.44,0,.78-.13,1.04-.4s.43-.63.53-1.09h1.03c-.12.83-.41,1.44-.88,1.83s-1.07.58-1.8.58c-.82,0-1.47-.3-1.96-.9s-.73-1.35-.73-2.25c0-1.1.27-1.96.8-2.57s1.22-.92,2.04-.92c.71,0,1.28.17,1.73.52Z" fill="#231f20"/>
      <path d="M194.66,104.15c.55.54.83,1.33.83,2.38s-.24,1.85-.73,2.51c-.49.66-1.25.99-2.27.99-.86,0-1.54-.29-2.04-.88s-.76-1.37-.76-2.35c0-1.05.27-1.89.8-2.52.53-.62,1.25-.94,2.14-.94.8,0,1.48.27,2.04.81ZM194.01,108.32c.26-.53.39-1.12.39-1.76,0-.58-.09-1.06-.28-1.43-.29-.58-.8-.87-1.52-.87-.64,0-1.1.25-1.39.74s-.43,1.08-.43,1.78.15,1.22.43,1.67.75.67,1.38.67c.69,0,1.17-.26,1.42-.79Z" fill="#231f20"/>
      <path d="M200.24,103.71c.19.12.4.32.64.62v-3.17h1.01v8.64h-.95v-.87c-.25.39-.54.67-.87.84-.33.17-.72.26-1.15.26-.7,0-1.3-.29-1.81-.88s-.76-1.37-.76-2.35c0-.91.23-1.71.7-2.38.47-.67,1.13-1,1.99-1,.48,0,.88.1,1.2.3ZM197.88,108.42c.28.45.74.68,1.36.68.49,0,.89-.21,1.2-.63s.47-1.02.47-1.81-.16-1.38-.48-1.76-.72-.57-1.2-.57c-.53,0-.96.2-1.29.61-.33.41-.49,1-.49,1.79,0,.67.14,1.23.43,1.69Z" fill="#231f20"/>
      <path d="M207.34,103.69c.42.21.73.48.95.81.21.32.35.69.42,1.11.06.29.09.75.09,1.38h-4.56c.02.64.17,1.15.45,1.54.28.39.71.58,1.3.58.55,0,.98-.18,1.31-.55.18-.21.31-.46.39-.74h1.04c-.03.23-.12.49-.27.77s-.33.51-.52.69c-.32.31-.71.52-1.18.63-.25.06-.54.09-.85.09-.78,0-1.43-.28-1.97-.85-.54-.57-.81-1.36-.81-2.39s.27-1.83.82-2.46c.54-.63,1.25-.94,2.13-.94.44,0,.87.1,1.29.31ZM207.72,106.16c-.04-.46-.14-.82-.3-1.1-.29-.51-.77-.76-1.44-.76-.48,0-.88.17-1.21.52s-.5.79-.52,1.33h3.46Z" fill="#231f20"/>
    </g>
    <text transform="translate(292.36 53.25) rotate(-6.84)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0"> </tspan></text>
    <text transform="translate(295.17 52.86) rotate(-16.6)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0"> </tspan></text>
    <text transform="translate(297.86 52) rotate(-26.42)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0"> </tspan></text>
    <text transform="translate(300.27 50.76) rotate(-34.15)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0"> </tspan></text>
    <text transform="translate(302.46 49.29) rotate(-40.8)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">a</tspan></text>
    <text transform="translate(305.92 46.25) rotate(-43.41)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">s</tspan></text>
    <text transform="translate(308.79 43.52) rotate(-42.61)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">y</tspan></text>
    <text transform="translate(311.63 40.82) rotate(-38.99)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">m</tspan></text>
    <text transform="translate(316.7 36.7) rotate(-32.79)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">m</tspan></text>
    <text transform="translate(322.22 33.2) rotate(-27.48)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">e</tspan></text>
    <text transform="translate(326.11 31.21) rotate(-24.47)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">t</tspan></text>
    <text transform="translate(328.09 30.3) rotate(-22.39)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">r</tspan></text>
    <text transform="translate(330.52 29.31) rotate(-20.6)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">i</tspan></text>
    <text transform="translate(332.12 28.69) rotate(-18.42)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">c</tspan></text>
    <text transform="translate(335.87 27.46) rotate(-16.26)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0"> </tspan></text>
    <text transform="translate(337.95 26.85) rotate(-14.84)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">t</tspan></text>
    <text transform="translate(340.09 26.28) rotate(-13.35)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">r</tspan></text>
    <text transform="translate(342.62 25.66) rotate(-11.38)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">a</tspan></text>
    <text transform="translate(346.93 24.8) rotate(-9.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">n</tspan></text>
    <text transform="translate(351.27 24.1) rotate(-7.32)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">s</tspan></text>
    <text transform="translate(355.22 23.6) rotate(-6.07)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">f</tspan></text>
    <text transform="translate(357.41 23.36) rotate(-4.84)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">e</tspan></text>
    <text transform="translate(361.8 22.99) rotate(-3.65)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">r</tspan></text>
    <text transform="translate(261.91 101.18) rotate(-90)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">evalation order</tspan></text>
    <text transform="translate(448.19 78.56)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">coroutine code</tspan></text>
    <text transform="translate(320.15 44.36)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="8"><tspan x="0" y="0">symmetric transfer</tspan></text>
  </g>
  <g id="text">
    <text transform="translate(276.19 28.67)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">X</tspan></text>
    <text transform="translate(276.3 62.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.02em"><tspan x="0" y="0">Y</tspan></text>
    <text transform="translate(276.86 95.66)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(277.32 129.15)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">?</tspan></text>
    <text transform="translate(383.74 95.75)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
    <text transform="translate(384.41 129.15)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(384.4 28.67)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(384.07 62.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
  </g>
  <g id="contrast-text">
    <text transform="translate(322.3 129.15)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(322.3 62.17)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
</svg></div></div>	<h4 id='ast-transformation-/-split'><a href='#ast-transformation-/-split'>AST transformation / split</a></h4>
	<p>Last feasible approach is to implement a transformation of coroutine function, into multiple trees, representing all possible paths which can be taken from each suspension point. Everytime such splitted coroutine is suspended, constexpr evaluator can unroll all its recursive functions. Implementation then needs to implement a storage for coroutine local variables which survive suspension. Hardest part is to implement special AST nodes to represent expressions split for suspension in middle.</p>
	<div class='svgimg'><div><?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="812.15" height="355.32" viewBox="0 0 812.15 355.32">
  <g id="areas">
    <path d="M141.22,296.15c-13.13,24.32,87.35,100.07,79.27-9.01s21.76-145.82-16.61-178.18-107.15,27.33-103.33,47.97,48.89-2.06,74.52-.6,36.65,101.24,14.72,113.52-35.44,1.99-48.57,26.31Z" fill="#ede15f" opacity=".5"/>
    <path d="M141.22,180.86c-36.2,1.5-53.89,35.89-64.99,67.82s.56,80.48,19.52,81.68,16.47-29.95,26.33-55.36,68.52-3.59,72.9-26.05-17.56-69.58-53.76-68.09Z" fill="#a3d49d" opacity=".5"/>
    <path d="M19.28,156.32c0-16.8,13.62-30.11,26.8-27.89s15.58,13.53,13.18,29.99-6.73,27.24-19.99,27.24-19.99-12.53-19.99-29.33Z" fill="#9cbde4" opacity=".5"/>
    <path d="M9.23,99c3.73,23.16,65.51-13.58,62.68,18.13s-25.08,95.57,3.69,102.71,7.61-50.46,24.09-60.19,67.21,15.5,61.42-36.69S123.24,32.36,78.06,32.36,5.5,75.84,9.23,99Z" fill="#f498c0" opacity=".5"/>
    <path d="M331.03,155.63c3.73,23.16,65.51-13.58,62.68,18.13s-25.08,95.57,3.69,102.71,7.61-50.46,24.09-60.19c16.48-9.73,67.21,15.5,61.42-36.69s-37.89-90.6-83.07-90.6-72.55,43.48-68.82,66.64Z" fill="#f498c0" opacity=".5"/>
    <path d="M716.32,276.48c-13.13,24.32,87.35,100.07,79.27-9.01-8.08-109.09,21.76-145.82-16.61-178.18-38.37-32.36-107.15,27.33-103.33,47.97s48.89-2.06,74.52-.6,36.65,101.24,14.72,113.52-35.44,1.99-48.57,26.31Z" fill="#ede15f" opacity=".5"/>
    <path d="M482.6,100c0-16.8,13.62-30.11,26.8-27.89s15.58,13.53,13.18,29.99-6.73,27.24-19.99,27.24-19.99-12.53-19.99-29.33Z" fill="#9cbde4" opacity=".5"/>
    <path d="M608.49,77.17c-36.2,1.5-53.89,35.89-64.99,67.82s.56,80.48,19.52,81.68c18.97,1.2,16.47-29.95,26.33-55.36s68.52-3.59,72.9-26.05-17.56-69.58-53.76-68.09Z" fill="#a3d49d" opacity=".5"/>
  </g>
  <g id="black-outline">
    <rect x="69.09" y="54.11" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="88.23" y="101.47" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="69.09" y="148.84" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="88.23" y="243.75" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="122.08" y="196.21" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="155.94" y="290.95" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="390.88" y="110.73" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="410.02" y="158.1" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="731.04" y="271.29" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="555.49" y="140.06" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="589.34" y="92.52" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
    <rect x="390.88" y="205.47" width="19.14" height="19.14" fill="#fff" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="boxes">
    <rect x="7.61" y="28.79" width="221.47" height="318.13" fill="none" opacity=".5" stroke="#231f20" stroke-miterlimit="10"/>
  </g>
  <g id="black-lines">
    <g>
      <path d="M78.66,73.25c0,16.94-26.05,11.44-33.26,21.83" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="44.01 93.07 43.57 101.47 48.15 94.41 44.01 93.07" fill="#231f20"/>
    </g>
    <g>
      <path d="M78.66,73.25c0,16.5,14.08,11.38,18.09,21.66" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="94.18 93.88 97.8 101.47 98.46 93.08 94.18 93.88" fill="#231f20"/>
    </g>
    <g>
      <path d="M97.8,120.62c0,15.9-14.11,11.2-18.1,21.66" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="77.97 140.46 78.66 148.84 82.25 141.23 77.97 140.46" fill="#231f20"/>
    </g>
    <g>
      <path d="M131.65,215.52c0,16.08-25.18,11.19-32.11,21.81" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="98.11 235.34 97.8 243.75 102.28 236.62 98.11 235.34" fill="#231f20"/>
    </g>
    <g>
      <path d="M126.95,142.39c-6.34-10.51-29.15-5.46-29.15-21.78" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="128.44 140.43 128.57 148.84 124.25 141.62 128.44 140.43" fill="#231f20"/>
    </g>
    <g>
      <path d="M131.65,215.52c0,16.44,25.15,11.29,32.1,21.81" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="161.01 236.63 165.51 243.75 165.18 235.34 161.01 236.63" fill="#231f20"/>
    </g>
    <g>
      <line x1="131.65" y1="167.98" x2="131.65" y2="189.57" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="129.47 188.08 131.65 196.21 133.83 188.08 129.47 188.08" fill="#231f20"/>
    </g>
    <g>
      <line x1="43.57" y1="120.62" x2="43.57" y2="142.2" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="41.39 140.71 43.57 148.84 45.75 140.71 41.39 140.71" fill="#231f20"/>
    </g>
    <g>
      <line x1="78.66" y1="167.98" x2="78.66" y2="189.57" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="76.48 188.08 78.66 196.21 80.84 188.08 76.48 188.08" fill="#231f20"/>
    </g>
    <g>
      <line x1="97.8" y1="262.72" x2="97.8" y2="284.31" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="95.62 282.82 97.8 290.95 99.98 282.82 95.62 282.82" fill="#231f20"/>
    </g>
    <g>
      <line x1="78.66" y1="45.25" x2="78.66" y2="7.55" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="81.56 43.26 78.66 54.11 75.75 43.26 81.56 43.26" fill="#231f20"/>
    </g>
    <g>
      <line x1="165.51" y1="263.23" x2="165.51" y2="284.81" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="163.33 283.32 165.51 291.45 167.69 283.32 163.33 283.32" fill="#231f20"/>
    </g>
    <g>
      <path d="M132.18,142.21c3.18-19.95,20.46-35.19,41.3-35.19,23.1,0,41.82,18.72,41.82,41.82v161.66c0,13.75-11.14,24.89-24.89,24.89s-24.89-11.14-24.89-24.89" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="134.57 140.95 131.65 148.84 130.23 140.55 134.57 140.95" fill="#231f20"/>
    </g>
    <g>
      <path d="M400.45,129.87c0,16.94-26.05,11.44-33.26,21.83" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="365.8 149.69 365.37 158.1 369.95 151.03 365.8 149.69" fill="#231f20"/>
    </g>
    <g>
      <path d="M400.45,129.87c0,16.5,14.08,11.38,18.09,21.66" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="415.97 150.5 419.59 158.1 420.26 149.71 415.97 150.5" fill="#231f20"/>
    </g>
    <g>
      <path d="M419.59,177.24c0,15.9-14.11,11.2-18.1,21.66" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="399.76 197.08 400.45 205.47 404.05 197.86 399.76 197.08" fill="#231f20"/>
    </g>
    <g>
      <path d="M448.75,199.01c-6.34-10.51-29.15-5.46-29.15-21.78" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="450.24 197.05 450.37 205.47 446.05 198.24 450.24 197.05" fill="#231f20"/>
    </g>
    <g>
      <line x1="400.45" y1="224.61" x2="400.45" y2="246.19" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="398.28 244.7 400.45 252.84 402.63 244.7 398.28 244.7" fill="#231f20"/>
    </g>
    <g>
      <line x1="400.45" y1="101.87" x2="400.45" y2="64.17" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="403.36 99.89 400.45 110.73 397.55 99.89 403.36 99.89" fill="#231f20"/>
    </g>
    <g>
      <line x1="740.61" y1="243.56" x2="740.61" y2="265.14" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="738.43 263.66 740.61 271.79 742.79 263.66 738.43 263.66" fill="#231f20"/>
    </g>
    <g>
      <path d="M707.27,122.55c3.18-19.95,20.46-35.19,41.3-35.19,23.1,0,41.82,18.72,41.82,41.82v161.66c0,13.75-11.14,24.89-24.89,24.89s-24.89-11.14-24.89-24.89" fill="none" stroke="#231f20" stroke-dasharray="1 1" stroke-miterlimit="10"/>
      <polygon points="709.67 121.28 706.75 129.18 705.33 120.88 709.67 121.28" fill="#231f20"/>
    </g>
    <g>
      <line x1="506.88" y1="64.29" x2="506.88" y2="85.88" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="504.7 84.39 506.88 92.52 509.06 84.39 504.7 84.39" fill="#231f20"/>
    </g>
    <g>
      <path d="M598.91,111.83c0,16.08-25.18,11.19-32.11,21.81" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="565.38 131.65 565.06 140.06 569.54 132.93 565.38 131.65" fill="#231f20"/>
    </g>
    <g>
      <path d="M598.91,111.83c0,16.44,25.15,11.29,32.1,21.81" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="628.28 132.94 632.77 140.06 632.44 131.65 628.28 132.94" fill="#231f20"/>
    </g>
    <g>
      <line x1="598.91" y1="64.29" x2="598.91" y2="85.88" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="596.74 84.39 598.91 92.52 601.09 84.39 596.74 84.39" fill="#231f20"/>
    </g>
    <g>
      <line x1="565.06" y1="159.03" x2="565.06" y2="180.62" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
      <polygon points="562.88 179.13 565.06 187.26 567.24 179.13 562.88 179.13" fill="#231f20"/>
    </g>
    <g>
      <line x1="248.34" y1="187.77" x2="327.19" y2="187.77" fill="none" stroke="#231f20" stroke-miterlimit="10" stroke-width="2"/>
      <polygon points="315.36 194.13 314.68 192.25 326.99 187.77 314.68 183.29 315.36 181.41 332.84 187.77 315.36 194.13" fill="#231f20"/>
    </g>
  </g>
  <g id="contrast-black-outline">
    <circle cx="43.57" cy="158.41" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <circle cx="78.66" cy="205.78" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <circle cx="97.8" cy="300.52" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <circle cx="400.45" cy="262.41" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <circle cx="506.88" cy="102.09" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <circle cx="565.06" cy="196.83" r="9.57" fill="#414042" stroke="#231f20" stroke-miterlimit="10"/>
    <g>
      <rect x="107.37" y="148.84" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="155.94 166.98 155.94 167.98 154.94 167.98" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="152.91" y1="167.98" x2="109.38" y2="167.98" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="108.37 167.98 107.37 167.98 107.37 166.98" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="107.37" y1="165.08" x2="107.37" y2="150.8" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="107.37 149.84 107.37 148.84 108.37 148.84" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="110.39" y1="148.84" x2="153.93" y2="148.84" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="154.94 148.84 155.94 148.84 155.94 149.84" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="155.94" y1="151.75" x2="155.94" y2="166.03" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="141.22" y="243.92" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="189.79 262.06 189.79 263.06 188.79 263.06" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="186.77" y1="263.06" x2="143.24" y2="263.06" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="142.22 263.06 141.22 263.06 141.22 262.06" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="141.22" y1="260.15" x2="141.22" y2="245.87" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="141.22 244.92 141.22 243.92 142.22 243.92" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="144.25" y1="243.92" x2="187.78" y2="243.92" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="188.79 243.92 189.79 243.92 189.79 244.92" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="189.79" y1="246.82" x2="189.79" y2="261.11" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="341.08" y="158.1" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="389.65 176.24 389.65 177.24 388.65 177.24" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="386.63" y1="177.24" x2="343.09" y2="177.24" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="342.08 177.24 341.08 177.24 341.08 176.24" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="341.08" y1="174.33" x2="341.08" y2="160.05" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="341.08 159.1 341.08 158.1 342.08 158.1" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="344.11" y1="158.1" x2="387.64" y2="158.1" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="388.65 158.1 389.65 158.1 389.65 159.1" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="389.65" y1="161" x2="389.65" y2="175.28" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="682.47" y="129.18" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="731.04 147.32 731.04 148.32 730.04 148.32" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="728.01" y1="148.32" x2="684.48" y2="148.32" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="683.47 148.32 682.47 148.32 682.47 147.32" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="682.47" y1="145.41" x2="682.47" y2="131.13" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="682.47 130.18 682.47 129.18 683.47 129.18" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="685.49" y1="129.18" x2="729.02" y2="129.18" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="730.04 129.18 731.04 129.18 731.04 130.18" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="731.04" y1="132.08" x2="731.04" y2="146.37" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="608.49" y="140.23" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="657.06 158.37 657.06 159.37 656.06 159.37" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="654.03" y1="159.37" x2="610.5" y2="159.37" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="609.49 159.37 608.49 159.37 608.49 158.37" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="608.49" y1="156.46" x2="608.49" y2="142.18" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="608.49 141.23 608.49 140.23 609.49 140.23" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="611.51" y1="140.23" x2="655.04" y2="140.23" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="656.06 140.23 657.06 140.23 657.06 141.23" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="657.06" y1="143.13" x2="657.06" y2="157.41" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="19.28" y="101.47" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="67.86 119.62 67.86 120.62 66.86 120.62" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="64.83" y1="120.62" x2="21.3" y2="120.62" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="20.28 120.62 19.28 120.62 19.28 119.62" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="19.28" y1="117.71" x2="19.28" y2="103.43" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="19.28 102.47 19.28 101.47 20.28 101.47" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="22.31" y1="101.47" x2="65.84" y2="101.47" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="66.86 101.47 67.86 101.47 67.86 102.47" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="67.86" y1="104.38" x2="67.86" y2="118.66" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
    <g>
      <rect x="413.85" y="205.83" width="48.57" height="19.14" fill="#e6e7e8"/>
      <g>
        <polyline points="462.42 223.97 462.42 224.97 461.42 224.97" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="459.39" y1="224.97" x2="415.86" y2="224.97" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="414.85 224.97 413.85 224.97 413.85 223.97" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="413.85" y1="222.07" x2="413.85" y2="207.78" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
        <polyline points="413.85 206.83 413.85 205.83 414.85 205.83" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="416.87" y1="205.83" x2="460.41" y2="205.83" fill="none" stroke="#231f20" stroke-dasharray="2.02 2.02" stroke-miterlimit="10"/>
        <polyline points="461.42 205.83 462.42 205.83 462.42 206.83" fill="none" stroke="#231f20" stroke-miterlimit="10"/>
        <line x1="462.42" y1="208.74" x2="462.42" y2="223.02" fill="none" stroke="#231f20" stroke-dasharray="1.9 1.9" stroke-miterlimit="10"/>
      </g>
    </g>
  </g>
  <g id="text">
    <text transform="translate(74.98 67.39)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(93.8 114.76)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
    <text transform="translate(74.32 162.13)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">C</tspan></text>
    <text transform="translate(93.8 257.03)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">E</tspan></text>
    <text transform="translate(127.32 209.49)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
    <text transform="translate(161.84 304.23)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(396.78 124.01)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12" letter-spacing="-.05em"><tspan x="0" y="0">A</tspan></text>
    <text transform="translate(415.59 171.38)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">B</tspan></text>
    <text transform="translate(396.12 218.75)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">C</tspan></text>
    <text transform="translate(736.94 284.57)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">F</tspan></text>
    <text transform="translate(561.06 153.34)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">E</tspan></text>
    <text transform="translate(594.58 105.8)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">D</tspan></text>
  </g>
  <g id="contrast-text">
    <text transform="translate(36.57 162.13)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(71.66 209.49)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(90.8 304.23)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(393.45 265.42)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(499.88 105.8)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(558.06 200.54)" fill="#fff" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">ret</tspan></text>
    <text transform="translate(20.89 114.76)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(108.97 162.13)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(142.82 257.2)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(342.68 171.38)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(415.45 219.11)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(684.07 142.46)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
    <text transform="translate(610.09 153.51)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">suspend</tspan></text>
  </g>
  <g id="info">
    <text transform="translate(174.68 42.93)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">coroutine</tspan></text>
    <text transform="translate(257.57 183.54)" fill="#231f20" font-family="Helvetica, Helvetica" font-size="12"><tspan x="0" y="0">transform</tspan></text>
  </g>
</svg></div></div>	<p><strong>Note:</strong> similar split is already done in compiler (for Clang at LLVM level, GCC just before leaving frontend, <a href="https://llvm.org/docs/Coroutines.html#async-lowering">for Swift in its frontend</a>)</p>
	<p>C++ coroutines are already defined as a set of transformations over a function based on detection of <code>co_await</code>, <code>co_yield</code>, and <code>co_return</code> keywords. This approach is going a bit further but it can still be done manually.</p>
	<h5 id='standard-transformation'><a href='#standard-transformation'>Standard transformation</a></h5>
	<p>Simple generator which take a value, yield it and later yield value<sup>2</sup>.</p>
	<pre><code class="language-cpp">auto simple(T start) -> std::generator&lt;T&gt; {
	co_yield start;
	auto quad = start * start;
	co_yield quad;
}</code></pre>
	<p>This code is <a href="https://eel.is/c++draft/dcl.fct.def.coroutine#5">current transformed</a> into:</p>
	<pre><code class="language-cpp">auto simple(T start) -> std::generator&lt;T&gt; {
	return std::generator&lt;T&gt;{ <i>coroutine-frame</i> {
		std::generator&lt;T&gt;::promise_type _promise{};
		auto start = start; // copy arguments
		try {
			co_await _promise.initial_suspend();
			co_await _promise.yield_value(start);
			auto quad = start * start;
			co_await _promise.yield_value(quad);
			// body
		} catch (...) {
			if (!<i>initial-await-resume-called</i>) {
				throw;
			}
			_promise.promise.unhandled_exception();
		}
		// final-suspend:
		 co_await promise.final_suspend() ;
	}};
}</code></pre>
	<p>As you can see, it's all just transformation. A function into a coroutine body explicitly managing life-time of a promise type, and <code>co_yield</code> into <code>co_await</code>. Compiler is already doing a lot of transformation in frontend. This proposed implementation strategy is just making a bit more transformations.</p>
	<h5 id='transformation-into-void-style-continuation'><a href='#transformation-into-void-style-continuation'>Transformation into void-style continuation</a></h5>
	<p>Any coroutine can be transformed into a set of <code>void</code> returning functions:</p>
	<pre><code class="language-cpp"><i>coroutine</i> simple(T argument) {
	auto result = co_await normal_function(argument);
	co_return result;
}</code></pre>
	<p>With resulting code looking somehow like this:</p>
	<pre><code class="language-cpp">struct coroutine_state_base {
	// where to jump
	void (*resume_point)(coroutine_state_base *) = nullptr;
};	

// unique type per each coroutine function
struct <i>__coroutine_state</i>: coroutine_state_base {
	// all arguments here...
	T argument;
	
	// promise type
	<i>coroutine</i>::promise_type promise;

	// all variables / temporaries which can survive suspension
	initial_awaiter initial_suspend_result;
	final_awaiter final_suspend_result;
	decltype(normal_function(argument)) tmp;
};

constexpr <i>coroutine</i> simple(T argument) { // &lt;------------- starting point
	// create state
	auto * state = new <i>__coroutine_state</i>{};
	
	// copy arguments
	state->argument = argument;
	
	// construct promise
	new (&state->promise) <i>coroutine</i>::promise_type{...};
	
	// construct result
	auto result = state->promise.get_return_object();
	
	// call (jump-into) coroutine body
	<i>simple_start</i>(state);
	
	// return result object with coroutine handle (usually)
	return result;
}

constexpr void <i>simple_start</i>(coroutine_state_base * vstate) {
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	
	// INITIAL SUSPEND
	state->initial_suspend_result = state->promise.initial_suspend()
	if (!state->initial_suspend_result.await_ready()) {
		state->resume_point = &amp;<i>simple_after_init_suspend</i>;
		
		// tail-recursion jump to next coroutine or continue
		<i>NEXT-COROUTINE</i>(state->initial_suspend_result.await_suspend(std::coroutine_handle{state}));
	}
	return <i>simple_after_init_suspend</i>(state); // tail-recursion
}

constexpr void <i>simple_after_init_suspend</i>(coroutine_state_base * vstate) {
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	
	// BEFORE CUSTOM CO_AWAIT
	try {
		(void)state->initial_suspend.await_resume();
		std::destroy_at(&amp;state->initial_suspend_result); // lifetime of temporary must be destroyed
		
		// normal body
		state->tmp = normal_function(state->argument);
		
		if (!state->tmp.await_ready()) {
			state->resume_point = &amp;<i>simple_after_first_await</i>;
			
			// tail-recursion jump to next coroutine or continue
			<i>NEXT-COROUTINE</i>(state->tmp.await_suspend(std::coroutine_handle{state}));
		}
		
		return <i>simple_after_first_await</i>(state);
	} catch (...) {
		std::destroy_at(&amp;state->tmp);
		state->promise.unhandled_exception();
		return <i>simple_final_suspend</i>(state);
	}
}

constexpr void <i>simple_after_first_await</i>(coroutine_state_base * vstate) {
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	
	// RESUMED or just jumped after CUSTOM CO_AWAIT
	try {
		// get result (which doesn't survive suspension, so it can be put here on stack)
		auto result = state->tmp.await_resume();
		
		// co_return result
		state->promise.return_value(result); 
		
		// end of scope for state->tmp
		std::destroy_at(&amp;state->tmp);
		
	} catch (...) {
		std::destroy_at(&amp;state->tmp);
		state->promise.unhandled_exception();
	}
	
	// jump to final suspend
	return <i>simple_final_suspend</i>(state);
}

constexpr void <i>simple_final_suspend</i>(coroutine_state_base * vstate) {
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	
	// FINAL SUSPEND
	state->final_suspend_result = state->promise.final_suspend();
	if (!state->final_suspend_result.await_ready()) {
		state->resume_point = nullptr;
		
		// tail-recursion jump to next coroutine or continue
		<i>NEXT-COROUTINE</i>(state->final_suspend_result.await_suspend(std::coroutine_handle{state}));
	}
	// destruction of state after final-suspend
	delete &amp;state;
	// no-return ... which will return us to our resumer
}
</pre></code>
<p>Whole transformation is just changing all edges to standalone <code>void</code> returning function between which can be jumped with a tail recursion. Each <code>.await_suspend(coroutine_handle)</code> can return handle to next coroutine, boolean with information if it should be a suspend or not, or just void, which means simple suspend.</p>
<pre><code class="language-cpp">// <i>NEXT-COROUTINE</i>(EXPR) is:
using type = decltype(EXPR);                                                        
if constexpr (std::is_void_v&lt;type&gt;) {                                         
	EXPR;                                                                             
	return; // return to caller                                                       
} else if constexpr (std::same_as&lt;type, bool&gt;) {                              
	if (EXPR) {                                                                       
		return; // return to caller                                                     
	}                                                                                 
	// continue in coroutine                                                          
} else if constexpr (std::convertible_to&lt;std::coroutine_handle&lt;void&gt;&gt;) {
	auto * next_state = static_cast&lt;coroutine_state_base *&gt;(E(XPR).address());                                                          
	return next_state->resume_point(next_state); // tail-recursion
}                                                                                   
</code></pre>
<p>Most of the transformation is lifetime handling and splitting at each <code>co_await</code>. The suspend transformation is already part of compilers so <code>await_ready()</code>, <code>await_suspend(std::coroutine_handle)</code>, <code>await_resume()</code> is already part of each compiler.</p> 
	<h5 id='loops-transformation'><a href='#loops-transformation'>Loops transformation</a></h5>
	<pre><code class="language-cpp">constexpr <i>coroutine</i> loops() noexcept {
		while (co_await check()) {
			another_function();
		}
	}</code></pre>
	<p>Code above is transformed into:</p>
	<pre><code class="language-cpp">constexpr void loops_main(coroutine_state_base * vstate) noexcept {
	// initial suspend skipped for readability
		
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	state->tmp = check();
	if (!state->tmp.await_ready()) {
		state->resume_point = &amp;<i>loops_main_body</i>;
		<i>NEXT-COROUTINE</i>(state->tmp.await_suspend(std::coroutine_handle{state}));
	}
	return <i>loops_main_body</i>(state); // tail-recursion
}

constexpr void <i>loops_main_body</i>(coroutine_handle_base * vstate) noexcept {
	auto * state = static_cast&lt;__coroutine_state *&gt;(vstate);
	if (state->tmp.await_resume()) {
		another_function();
		return <i>loops_main</i>(state); // tail-recursion
	}
	std::destroy_at(&state->tmp);
	return <i>loops_final_suspend</i>(state);
}</code></pre>
	<h5 id='tail-recursion'><a href='#tail-recursion'>Tail-recursion</a></h5>
	<p>To implement constexpr coroutines with the AST transformation a tail recursion is needed to be supported in constant evaluator.</p>
	<h4 id='comparison'><a href='#comparison'>Comparison</a></h4>
	<table class="before-after poll">
		<tr><th rowspan="2">Implementation</th><th colspan="2" style="border-bottom: none">Storage for</th><th rowspan="2" class="left">Area needed to be changed</th></tr>
		<tr><th style="border-top: none">Variables</th><th style="border-top: none">State</th></tr>
		<tr><th>Stackfull<br/>coroutines</th><td>overlay over local variables</td><td>fiber (alternative stack on a heap)</td><td class="left">builtins to control coroutine flow, execution state to keep track of allocations</td></tr>
		<tr><th>Byte-code</th><td>coroutine frame</td><td>instruction pointer</td><td class="left">control of instruction pointer</td></tr>
		<tr><th>Stackless<br/>coroutines</th><td>overlay over local variables</td><td>suspended coroutines</td><td class="left">convert all AST walking functions into coroutines</td></tr>
		<tr><th>AST transformation</th><td>instance of<br/>coroutine state</td><td>function pointer</td><td class="left">custom lifetime handling needs to be added for temporaries / variables across suspend points</td></tr>
	</table>
	<h2 id='impact-on-existing-code'><a href='#impact-on-existing-code'>Impact on existing code</a></h2>
  <p>None, this is a pure extension, it allows code to be constexpr which wasn't case before.</p>
	<h2 id='intention-for-wording-changes'><a href='#intention-for-wording-changes'>Intention for wording changes</a></h2>
  <p>Remove all obstacles blocking coroutines from being constant evaluatable. Make sure all coroutines are destroyed at end of constant evaluation.</p>
	<h2 id='proposed-wording-changes'><a href='#proposed-wording-changes'>Proposed wording changes</a></h2>
	<div class='wording'>
<h2 ><a class='secnum' style='min-width:65pt'>7.7</a> Constant expressions <a class='abbr_ref'>[expr.const]</a></h2>


<div class='para' id='5'><div class='marginalizedparent'><a class='marginalized' href='#5'>5</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/expressions.tex#L7464'>#</a></div><div class='texpara'><div id='5.sentence-1' class='sentence'>An expression <span class='math'><span class='mathalpha'>E</span></span> is a <a class='hidden_link' href='#def:expression,core_constant' title='7.7&emsp;Constant expressions&emsp;[expr.const]'><span id='def:expression,core_constant'><i >core constant expression</i></span></a>
unless the evaluation of <span class='math'><span class='mathalpha'>E</span></span>, following the rules of the abstract
machine (<a href='intro.execution' title='6.9.1&emsp;Sequential execution'>[intro.<span class='shy'></span>execution]</a>), would evaluate one of the following:
<ul class='itemize'><li id='5.1'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.1'>(5.1)</a></div><span id=':this'><span class='texttt'><span class='keyword'>this</span></span></span> (<a href='expr.prim.this' title='7.5.3&emsp;This'>[expr.<span class='shy'></span>prim.<span class='shy'></span>this]</a>), except
<ul class='itemize'><li id='5.1.1'><div class='marginalizedparent' style='left:-36mm'><a class='marginalized' href='#5.1.1'>(5.1.1)</a></div>in a constexpr function (<a href='dcl.constexpr' title='9.2.6&emsp;The constexpr and consteval specifiers'>[dcl.<span class='shy'></span>constexpr]</a>)
that is being evaluated as part of <span class='math'><span class='mathalpha'>E</span></span> or</li><li id='5.1.2'><div class='marginalizedparent' style='left:-36mm'><a class='marginalized' href='#5.1.2'>(5.1.2)</a></div>when appearing as the <a href='expr.post.general#nt:postfix-expression' title='7.6.1.1&emsp;General&emsp;[expr.post.general]'><span id='ntref:postfix-expression'><span class='textsf'><i >postfix-expression</i></span></span></a> of
an implicit or explicit class member access expression (<a href='expr.ref' title='7.6.1.5&emsp;Class member access'>[expr.<span class='shy'></span>ref]</a>);</li></ul></li><li id='5.2'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.2'>(5.2)</a></div>a control flow that passes through
a declaration of a block variable (<a href='basic.scope.block' title='6.4.3&emsp;Block scope'>[basic.<span class='shy'></span>scope.<span class='shy'></span>block]</a>) with
static (<a href='basic.stc.static' title='6.7.5.2&emsp;Static storage duration'>[basic.<span class='shy'></span>stc.<span class='shy'></span>static]</a>) or
thread (<a href='basic.stc.thread' title='6.7.5.3&emsp;Thread storage duration'>[basic.<span class='shy'></span>stc.<span class='shy'></span>thread]</a>) storage duration,
unless that variable is usable in constant expressions;
<div id='example-1' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-1'>1</a></i>:&ensp;<span class='codeblock'><span class='keyword'>constexpr</span> <span class='keyword'>char</span> test<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
  <span class='keyword'>static</span> <span class='keyword'>const</span> <span class='keyword'>int</span> x <span class='operator'>=</span> <span class='literal'>5</span>;
  <span class='keyword'>static</span> <span class='keyword'>constexpr</span> <span class='keyword'>char</span> c<span class='squarebracket'>[</span><span class='squarebracket'>]</span> <span class='operator'>=</span> <span class='literal'>"Hello World"</span>;
  <span class='keyword'>return</span> <span class='operator'>*</span><span class='parenthesis'>(</span>c <span class='operator'>+</span> x<span class='parenthesis'>)</span>;
<span class='curlybracket'>}</span>
<span class='keyword'>static_assert</span><span class='parenthesis'>(</span><span class='literal'>' '</span> <span class='operator'>=</span><span class='operator'>=</span> test<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span>;
</span> —&nbsp;<i>end example</i>]</div></div></li>

<li id='5.??' class="added-item"><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.??'>(5.??)</a></div>a construction of a coroutine promise object ([<a href="https://eel.is/c++draft/dcl.fct.def.coroutine#def:promise_object">dcl.fct.def.coroutine</a>]), unless the coroutine promise object is destroyed within the evaluation of <em>E</em>;</li>

<li id='5.3'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.3'>(5.3)</a></div>an invocation of a non-constexpr function;<a class='footnoteref' href='#footnote-68' id='footnoteref-68' title='Overload resolution ([over.match]) is applied as usual.'>68</a></li><li id='5.4'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.4'>(5.4)</a></div>an invocation of an undefined constexpr function;</li><li id='5.5'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.5'>(5.5)</a></div>an invocation of an instantiated constexpr function
that is not constexpr-suitable;</li><li id='5.6'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.6'>(5.6)</a></div>an invocation of a virtual function (<a href='class.virtual' title='11.7.3&emsp;Virtual functions'>[class.<span class='shy'></span>virtual]</a>)
for an object whose dynamic type is constexpr-unknown;</li>

<div style="height: 50px"></div>

<li id='5.20'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.20'>(5.20)</a></div>a call to an instance of
<span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>allocator<span class='anglebracket'>&lt;</span>T<span class='anglebracket'>&gt;</span><span class='operator'>&#x200b;::&#x200b;</span>allocate</span> (<a href='allocator.members' title='20.2.10.2&emsp;Members'>[allocator.<span class='shy'></span>members]</a>),
unless the allocated storage is deallocated within the evaluation of <span class='math'><span class='mathalpha'>E</span></span>;</li><li id='5.21'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.21'>(5.21)</a></div>a call to an instance of
<span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>allocator<span class='anglebracket'>&lt;</span>T<span class='anglebracket'>&gt;</span><span class='operator'>&#x200b;::&#x200b;</span>deallocate</span> (<a href='allocator.members' title='20.2.10.2&emsp;Members'>[allocator.<span class='shy'></span>members]</a>),
unless it deallocates a region of storage
allocated within the evaluation of <span class='math'><span class='mathalpha'>E</span></span>;</li>

<li id='5.22'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.22'><span class="">(5.22)</span></a></div>an <a href='expr.await#nt:await-expression' title='7.6.2.4&emsp;Await&emsp;[expr.await]'><span id='ntref:await-expression'><span class='textsf'><i >await-expression</i></span></span></a> (<a href='expr.await' title='7.6.2.4&emsp;Await'>[expr.<span class='shy'></span>await]</a>)<span class="added">, unless the evaluation of <span class='mathalpha'>E</span> happens within evaluation of a coroutine</span>;</li>

<li id='5.23'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.23'><span class="">(5.23)</span></a></div>a <a href='expr.yield#nt:yield-expression' title='7.6.17&emsp;Yielding a value&emsp;[expr.yield]'><span id='ntref:yield-expression'><span class='textsf'><i >yield-expression</i></span></span></a> (<a href='expr.yield' title='7.6.17&emsp;Yielding a value'>[expr.<span class='shy'></span>yield]</a>)<span class="added">,  unless the evaluation of <span class='mathalpha'>E</span> happens within evaluation of a coroutine</span>;</li>

<li id='5.24'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.24'>(5.24)</a></div>a three-way comparison (<a href='expr.spaceship' title='7.6.8&emsp;Three-way comparison operator'>[expr.<span class='shy'></span>spaceship]</a>),
relational (<a href='expr.rel' title='7.6.9&emsp;Relational operators'>[expr.<span class='shy'></span>rel]</a>), or equality (<a href='expr.eq' title='7.6.10&emsp;Equality operators'>[expr.<span class='shy'></span>eq]</a>)
operator where the result is unspecified;</li><li id='5.25'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#5.25'>(5.25)</a></div>a <a href='expr.throw#nt:throw-expression' title='7.6.18&emsp;Throwing an exception&emsp;[expr.throw]'><span id='ntref:throw-expression'><span class='textsf'><i >throw-expression</i></span></span></a> (<a href='expr.throw' title='7.6.18&emsp;Throwing an exception'>[expr.<span class='shy'></span>throw]</a>);</li>

</div></div></div>
</div>	<div class='wording'>
<h3 ><a class='secnum' style='min-width:80pt'>9.2.6</a> The <span class='texttt'>constexpr</span> and <span class='texttt'>consteval</span> specifiers <a class='abbr_ref'>[dcl.constexpr]</a></h3><div class='texpara'><a class='index' id=':specifier,constexpr'></a>
<a class='index' id=':specifier,consteval'></a></div><div class='para' id='1'><div class='marginalizedparent'><a class='marginalized' href='#1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L851'>#</a></div><div class='texpara'><div id='1.sentence-1' class='sentence'>The <span id=':constexpr'><span class='texttt'><span class='keyword'>constexpr</span></span></span> specifier shall be applied only to
the definition of a variable or variable template or
the declaration of a function or function template<a class='hidden_link' href='#1.sentence-1'>.</a></div> <div id='1.sentence-2' class='sentence'>The <span id=':consteval'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier shall be applied only to
the declaration of a function or function template<a class='hidden_link' href='#1.sentence-2'>.</a></div> <div id='1.sentence-3' class='sentence'>A function or static data member
declared with the <span id=':constexpr_'><span class='texttt'><span class='keyword'>constexpr</span></span></span> or <span id=':consteval_'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier
on its first declaration
is implicitly an inline function or variable (<a href='dcl.inline' title='9.2.8&emsp;The inline specifier'>[dcl.<span class='shy'></span>inline]</a>)<a class='hidden_link' href='#1.sentence-3'>.</a></div> <div id='1.sentence-4' class='sentence'>If any declaration of a function or function template has
a <span id=':constexpr__'><span class='texttt'><span class='keyword'>constexpr</span></span></span> or <span id=':consteval__'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier,
then all its declarations shall contain the same specifier<a class='hidden_link' href='#1.sentence-4'>.</a></div> <div id='note-1' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#note-1'>1</a></i>:&ensp;<div id='1.sentence-5' class='sentence'>An explicit specialization can differ from the template declaration
with respect to the <span id=':constexpr___'><span class='texttt'><span class='keyword'>constexpr</span></span></span> or <span id=':consteval___'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier<a class='hidden_link' href='#1.sentence-5'>.</a></div> —&nbsp;<i>end note</i>]</div></div> <div id='note-2' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#note-2'>2</a></i>:&ensp;<div id='1.sentence-6' class='sentence'>Function parameters cannot be declared <span id=':constexpr____'><span class='texttt'><span class='keyword'>constexpr</span></span></span><a class='hidden_link' href='#1.sentence-6'>.</a></div> —&nbsp;<i>end note</i>]</div></div> <div id='example-1' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-1'>1</a></i>:&ensp;<span class='codeblock'><span class='keyword'>constexpr</span> <span class='keyword'>void</span> square<span class='parenthesis'>(</span><span class='keyword'>int</span> <span class='operator'>&amp;</span>x<span class='parenthesis'>)</span>;  <span class='comment'>// OK, declaration</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> bufsz <span class='operator'>=</span> <span class='literal'>1024</span>;     <span class='comment'>// OK, definition</span>
<span class='keyword'>constexpr</span> <span class='keyword'>struct</span> pixel <span class='curlybracket'>{</span>        <span class='comment'>// error: <span class='tcode_in_codeblock'>pixel</span> is a type</span>
  <span class='keyword'>int</span> x;
  <span class='keyword'>int</span> y;
  <span class='keyword'>constexpr</span> pixel<span class='parenthesis'>(</span><span class='keyword'>int</span><span class='parenthesis'>)</span>;         <span class='comment'>// OK, declaration</span>
<span class='curlybracket'>}</span>;
<span class='keyword'>constexpr</span> pixel<span class='operator'>::</span>pixel<span class='parenthesis'>(</span><span class='keyword'>int</span> a<span class='parenthesis'>)</span>
  <span class='operator'>:</span> x<span class='parenthesis'>(</span>a<span class='parenthesis'>)</span>, y<span class='parenthesis'>(</span>x<span class='parenthesis'>)</span>                  <span class='comment'>// OK, definition</span>
  <span class='curlybracket'>{</span> square<span class='parenthesis'>(</span>x<span class='parenthesis'>)</span>; <span class='curlybracket'>}</span>
<span class='keyword'>constexpr</span> pixel small<span class='parenthesis'>(</span><span class='literal'>2</span><span class='parenthesis'>)</span>;       <span class='comment'>// error: <span class='tcode_in_codeblock'>square</span> not defined, so <span class='tcode_in_codeblock'>small(2)</span></span>
                                <span class='comment'>// not constant (<a href='expr.const' title='7.7&emsp;Constant expressions'>[expr.<span class='shy'></span>const]</a>) so <span id=':constexpr_____'><span class='tcode_in_codeblock'>constexpr</span></span> not satisfied</span>

<span class='keyword'>constexpr</span> <span class='keyword'>void</span> square<span class='parenthesis'>(</span><span class='keyword'>int</span> <span class='operator'>&amp;</span>x<span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='comment'>// OK, definition</span>
  x <span class='operator'>*</span><span class='operator'>=</span> x;
<span class='curlybracket'>}</span>
<span class='keyword'>constexpr</span> pixel large<span class='parenthesis'>(</span><span class='literal'>4</span><span class='parenthesis'>)</span>;       <span class='comment'>// OK, <span class='tcode_in_codeblock'>square</span> defined</span>
<span class='keyword'>int</span> next<span class='parenthesis'>(</span><span class='keyword'>constexpr</span> <span class='keyword'>int</span> x<span class='parenthesis'>)</span> <span class='curlybracket'>{</span>     <span class='comment'>// error: not for parameters</span>
     <span class='keyword'>return</span> x <span class='operator'>+</span> <span class='literal'>1</span>;
<span class='curlybracket'>}</span>
<span class='keyword'>extern</span> <span class='keyword'>constexpr</span> <span class='keyword'>int</span> memsz;     <span class='comment'>// error: not a definition</span>
</span> —&nbsp;<i>end example</i>]</div></div></div></div><div class='para' id='2'><div class='marginalizedparent'><a class='marginalized' href='#2'>2</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L897'>#</a></div><div class='texpara'><div id='2.sentence-1' class='sentence'>A <span id=':constexpr______'><span class='texttt'><span class='keyword'>constexpr</span></span></span> or <span id=':consteval____'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier
used in the declaration of a function
declares that function to be
a <a class='hidden_link' href='#def:specifier,constexpr,function' title='9.2.6&emsp;The constexpr and consteval specifiers&emsp;[dcl.constexpr]'><span id='def:specifier,constexpr,function'><i >constexpr function</i></span></a><a class='hidden_link' href='#2.sentence-1'>.</a></div> <div id='note-3' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#note-3'>3</a></i>:&ensp;<div id='2.sentence-2' class='sentence'>A function or constructor declared with the <span id=':consteval_____'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier
is an immediate function (<a href='expr.const' title='7.7&emsp;Constant expressions'>[expr.<span class='shy'></span>const]</a>)<a class='hidden_link' href='#2.sentence-2'>.</a></div> —&nbsp;<i>end note</i>]</div></div> <div id='2.sentence-3' class='sentence'>
A destructor, an allocation function, or a deallocation function
shall not be declared with the <span id=':consteval______'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifier<a class='hidden_link' href='#2.sentence-3'>.</a></div></div></div><div class='para' id='3'><div class='marginalizedparent'><a class='marginalized' href='#3'>3</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L909'>#</a></div><div class='texpara'><div id='3.sentence-1' class='sentence'><a class='index' id=':specifier,constexpr,function'></a><a class='index' id=':constexpr_function'></a>A function is <a class='hidden_link' href='#def:constexpr-suitable' title='9.2.6&emsp;The constexpr and consteval specifiers&emsp;[dcl.constexpr]'><span id='def:constexpr-suitable'><i >constexpr-suitable</i></span></a> <span class="added">unless</span> <span class="removed">if</span>
<ul class='itemize'><li id='3.1'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#3.1'><span class="removed">(3.1)</span></a></div><span class='removed'>it is not a coroutine (<a href='dcl.fct.def.coroutine' title='9.5.4&emsp;Coroutine definitions'>[dcl.<span class='shy'></span>fct.<span class='shy'></span>def.<span class='shy'></span>coroutine]</a>), and</span></li><li id='3.2'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#3.2'><span class="removed">(3.2)</span></a></div><span class="removed">if the function </span> <span class="added">it</span> is a constructor or destructor <span class="added">whose class has</span>
<span class="removed">its class does not have </span> any virtual base classes<a class='hidden_link' href='#3.sentence-1'>.</a></li></ul></div> <div id='3.sentence-2' class='sentence'>
Except for instantiated constexpr functions,
non-templated constexpr functions shall be constexpr-suitable<a class='hidden_link' href='#3.sentence-2'>.</a></div></div><div class='texpara'><div id='example-2' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-2'>2</a></i>:&ensp;<span class='codeblock'><span class='keyword'>constexpr</span> <span class='keyword'>int</span> square<span class='parenthesis'>(</span><span class='keyword'>int</span> x<span class='parenthesis'>)</span>
  <span class='curlybracket'>{</span> <span class='keyword'>return</span> x <span class='operator'>*</span> x; <span class='curlybracket'>}</span>             <span class='comment'>// OK</span>
<span class='keyword'>constexpr</span> <span class='keyword'>long</span> long_max<span class='parenthesis'>(</span><span class='parenthesis'>)</span>
  <span class='curlybracket'>{</span> <span class='keyword'>return</span> <span class='literal'>2147483647</span>; <span class='curlybracket'>}</span>        <span class='comment'>// OK</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> abs<span class='parenthesis'>(</span><span class='keyword'>int</span> x<span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
  <span class='keyword'>if</span> <span class='parenthesis'>(</span>x <span class='anglebracket'>&lt;</span> <span class='literal'>0</span><span class='parenthesis'>)</span>
    x <span class='operator'>=</span> <span class='operator'>-</span>x;
  <span class='keyword'>return</span> x;                     <span class='comment'>// OK</span>
<span class='curlybracket'>}</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> constant_non_42<span class='parenthesis'>(</span><span class='keyword'>int</span> n<span class='parenthesis'>)</span> <span class='curlybracket'>{</span>  <span class='comment'>// OK</span>
  <span class='keyword'>if</span> <span class='parenthesis'>(</span>n <span class='operator'>=</span><span class='operator'>=</span> <span class='literal'>42</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
    <span class='keyword'>static</span> <span class='keyword'>int</span> value <span class='operator'>=</span> n;
    <span class='keyword'>return</span> value;
  <span class='curlybracket'>}</span>
  <span class='keyword'>return</span> n;
<span class='curlybracket'>}</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> uninit<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
  <span class='keyword'>struct</span> <span class='curlybracket'>{</span> <span class='keyword'>int</span> a; <span class='curlybracket'>}</span> s;
  <span class='keyword'>return</span> s<span class='operator'>.</span>a;                   <span class='comment'>// error: uninitialized read of <span class='tcode_in_codeblock'>s.a</span></span>
<span class='curlybracket'>}</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> prev<span class='parenthesis'>(</span><span class='keyword'>int</span> x<span class='parenthesis'>)</span>
  <span class='curlybracket'>{</span> <span class='keyword'>return</span> <span class='operator'>-</span><span class='operator'>-</span>x; <span class='curlybracket'>}</span>               <span class='comment'>// OK</span>
<span class='keyword'>constexpr</span> <span class='keyword'>int</span> g<span class='parenthesis'>(</span><span class='keyword'>int</span> x, <span class='keyword'>int</span> n<span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='comment'>// OK</span>
  <span class='keyword'>int</span> r <span class='operator'>=</span> <span class='literal'>1</span>;
  <span class='keyword'>while</span> <span class='parenthesis'>(</span><span class='operator'>-</span><span class='operator'>-</span>n <span class='anglebracket'>&gt;</span> <span class='literal'>0</span><span class='parenthesis'>)</span> r <span class='operator'>*</span><span class='operator'>=</span> x;
  <span class='keyword'>return</span> r;
<span class='curlybracket'>}</span>
</span> —&nbsp;<i>end example</i>]</div></div></div></div><div class='para' id='4'><div class='marginalizedparent'><a class='marginalized' href='#4'>4</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L956'>#</a></div><div class='texpara'><div id='4.sentence-1' class='sentence'>An invocation of a constexpr function in a given context
produces the same result as
an invocation of an equivalent non-constexpr function in the same context
in all respects except that
<ul class='itemize'><li id='4.1'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#4.1'>(4.1)</a></div>an invocation of a constexpr function
can appear in a constant expression (<a href='expr.const' title='7.7&emsp;Constant expressions'>[expr.<span class='shy'></span>const]</a>) and</li><li id='4.2'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#4.2'>(4.2)</a></div>copy elision is not performed in a constant expression (<a href='class.copy.elision' title='11.9.6&emsp;Copy/move elision'>[class.<span class='shy'></span>copy.<span class='shy'></span>elision]</a>)<a class='hidden_link' href='#4.sentence-1'>.</a></li></ul></div> <div id='note-4' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#note-4'>4</a></i>:&ensp;<div id='4.sentence-2' class='sentence'>Declaring a function constexpr can change whether an expression
is a constant expression<a class='hidden_link' href='#4.sentence-2'>.</a></div> <div id='4.sentence-3' class='sentence'>This can indirectly cause calls to <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>is_<span class='shy'></span>constant_<span class='shy'></span>evaluated</span>
within an invocation of the function to produce a different value<a class='hidden_link' href='#4.sentence-3'>.</a></div> —&nbsp;<i>end note</i>]</div></div> <div id='note-5' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#note-5'>5</a></i>:&ensp;<div id='4.sentence-4' class='sentence'>It is possible to write a constexpr function for which
no invocation satisfies the requirements of a core constant expression<a class='hidden_link' href='#4.sentence-4'>.</a></div> —&nbsp;<i>end note</i>]</div></div></div></div><div class='para' id='5'><div class='marginalizedparent'><a class='marginalized' href='#5'>5</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L979'>#</a></div><div class='texpara'><div id='5.sentence-1' class='sentence'>The <span id=':constexpr_______'><span class='texttt'><span class='keyword'>constexpr</span></span></span> and <span id=':consteval_______'><span class='texttt'><span class='keyword'>consteval</span></span></span> specifiers have no
effect on the type of a constexpr function<a class='hidden_link' href='#5.sentence-1'>.</a></div> <div id='example-3' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-3'>3</a></i>:&ensp;<span class='codeblock'><span class='keyword'>constexpr</span> <span class='keyword'>int</span> bar<span class='parenthesis'>(</span><span class='keyword'>int</span> x, <span class='keyword'>int</span> y<span class='parenthesis'>)</span>         <span class='comment'>// OK</span>
    <span class='curlybracket'>{</span> <span class='keyword'>return</span> x <span class='operator'>+</span> y <span class='operator'>+</span> x<span class='operator'>*</span>y; <span class='curlybracket'>}</span>
<span class='comment'>// ...</span>
<span class='keyword'>int</span> bar<span class='parenthesis'>(</span><span class='keyword'>int</span> x, <span class='keyword'>int</span> y<span class='parenthesis'>)</span>                   <span class='comment'>// error: redefinition of <span class='tcode_in_codeblock'>bar</span></span>
    <span class='curlybracket'>{</span> <span class='keyword'>return</span> x <span class='operator'>*</span> <span class='literal'>2</span> <span class='operator'>+</span> <span class='literal'>3</span> <span class='operator'>*</span> y; <span class='curlybracket'>}</span>
</span> —&nbsp;<i>end example</i>]</div></div></div></div><div class='para' id='6'><div class='marginalizedparent'><a class='marginalized' href='#6'>6</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/declarations.tex#L992'>#</a></div><div class='texpara'><div id='6.sentence-1' class='sentence'>A <span id=':constexpr________'><span class='texttt'><span class='keyword'>constexpr</span></span></span> specifier used in an object declaration
declares the object as const<a class='hidden_link' href='#6.sentence-1'>.</a></div> <div id='6.sentence-2' class='sentence'>Such an object
shall have literal type and
shall be initialized<a class='hidden_link' href='#6.sentence-2'>.</a></div> <div id='6.sentence-3' class='sentence'>In any <span id=':constexpr_________'><span class='texttt'><span class='keyword'>constexpr</span></span></span> variable declaration,
the full-expression of the initialization
shall be a constant expression (<a href='expr.const' title='7.7&emsp;Constant expressions'>[expr.<span class='shy'></span>const]</a>)<a class='hidden_link' href='#6.sentence-3'>.</a></div> <div id='6.sentence-4' class='sentence'>A <span id=':constexpr__________'><span class='texttt'><span class='keyword'>constexpr</span></span></span> variable that is an object,
as well as any temporary to which a <span id=':constexpr___________'><span class='texttt'><span class='keyword'>constexpr</span></span></span> reference is bound,
shall have constant destruction<a class='hidden_link' href='#6.sentence-4'>.</a></div> <div id='example-4' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-4'>4</a></i>:&ensp;<span class='codeblock'><span class='keyword'>struct</span> pixel <span class='curlybracket'>{</span>
  <span class='keyword'>int</span> x, y;
<span class='curlybracket'>}</span>;
<span class='keyword'>constexpr</span> pixel ur <span class='operator'>=</span> <span class='curlybracket'>{</span> <span class='literal'>1294</span>, <span class='literal'>1024</span> <span class='curlybracket'>}</span>;    <span class='comment'>// OK</span>
<span class='keyword'>constexpr</span> pixel origin;                 <span class='comment'>// error: initializer missing</span>
</span> —&nbsp;<i>end example</i>]</div></div></div></div>
</div>	<div class='wording'>
<h3 ><a class='secnum' style='min-width:80pt'>9.5.4</a> Coroutine definitions <a class='abbr_ref'>[dcl.fct.def.coroutine]</a></h3>

<div class='para' id='9'><div class='marginalizedparent'><a class='marginalized' href='#9'>9</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/6fe84caba29605d8445c039f585bd9951a0f3e03/source/declarations.tex#L6868'>#</a></div><div class='texpara'><div id='9.sentence-1' class='sentence'>An implementation may need to allocate additional storage for a coroutine<a class='hidden_link' href='#9.sentence-1'>.</a></div> <div id='9.sentence-2' class='sentence'>This storage is known as the <a class='hidden_link' href='#def:coroutine_state' title='9.5.4&emsp;Coroutine definitions&emsp;[dcl.fct.def.coroutine]'><span id='def:coroutine_state'><i >coroutine state</i></span></a> and is obtained by calling
a non-array allocation function (<a href='basic.stc.dynamic.allocation' title='6.7.5.5.2&emsp;Allocation functions'>[basic.<span class='shy'></span>stc.<span class='shy'></span>dynamic.<span class='shy'></span>allocation]</a>)<a class='hidden_link' href='#9.sentence-2'>.</a></div> <div id='9.sentence-3' class='sentence'>The allocation function's name is looked up by searching for it in the scope of the promise type<a class='hidden_link' href='#9.sentence-3'>.</a></div> <ul class='itemize'><li id='9.1'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#9.1'>(9.1)</a></div><div class='texpara'><div id='9.1.sentence-1' class='sentence'>If the search finds any declarations,
overload resolution is performed on a function call created by assembling an
argument list<a class='hidden_link' href='#9.1.sentence-1'>.</a></div> <div id='9.1.sentence-2' class='sentence'>The first argument is the amount of space requested, and
is a prvalue of type <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>size_<span class='shy'></span>t</span><a class='hidden_link' href='#9.1.sentence-2'>.</a></div> <div id='9.1.sentence-3' class='sentence'>The lvalues <span class='math'><span class="mjx-chtml"><span class="mjx-math"><span class="mjx-mrow" aria-hidden="true"><span class="mjx-msubsup"><span class="mjx-base"><span class="mjx-texatom"><span class="mjx-mrow"><span class="mjx-mtext"><span class="mjx-char MJXc-TeX-type-R" style="padding-top: 0.225em; padding-bottom: 0.519em;">p</span></span></span></span></span><span class="mjx-sub" style="font-size: 70.7%; vertical-align: -0.398em; padding-right: 0.071em;"><span class="mjx-mn"><span class="mjx-char MJXc-TeX-main-R" style="padding-top: 0.372em; padding-bottom: 0.372em;">1</span></span></span></span><span class="mjx-mo MJXc-space1"><span class="mjx-char MJXc-TeX-main-R" style="margin-top: -0.144em; padding-bottom: 0.372em;">…</span></span><span class="mjx-texatom MJXc-space1"><span class="mjx-mrow"></span></span><span class="mjx-msubsup"><span class="mjx-base"><span class="mjx-texatom"><span class="mjx-mrow"><span class="mjx-mtext"><span class="mjx-char MJXc-TeX-type-R" style="padding-top: 0.225em; padding-bottom: 0.519em;">p</span></span></span></span></span><span class="mjx-sub" style="font-size: 70.7%; vertical-align: -0.398em; padding-right: 0.071em;"><span class="mjx-mi"><span class="mjx-char MJXc-TeX-math-I" style="padding-top: 0.225em; padding-bottom: 0.298em;">n</span></span></span></span></span></span></span></span> are the successive arguments<a class='hidden_link' href='#9.1.sentence-3'>.</a></div> <div id='9.1.sentence-4' class='sentence'>If no viable function is found (<a href='over.match.viable' title='12.2.3&emsp;Viable functions'>[over.<span class='shy'></span>match.<span class='shy'></span>viable]</a>),
overload resolution is performed again
on a function call created by passing just
the amount of space required as a prvalue of type <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>size_<span class='shy'></span>t</span><a class='hidden_link' href='#9.1.sentence-4'>.</a></div></div></li><li id='9.2'><div class='marginalizedparent' style='left:-27mm'><a class='marginalized' href='#9.2'>(9.2)</a></div><div class='texpara'><div id='9.2.sentence-1' class='sentence'>If the search finds no declarations, a search is performed in the global scope<a class='hidden_link' href='#9.2.sentence-1'>.</a></div> <div id='9.2.sentence-2' class='sentence'>Overload resolution is performed on a function call created by
passing the amount of space required as a prvalue of type <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>size_<span class='shy'></span>t</span><a class='hidden_link' href='#9.2.sentence-2'>.</a></div></div></li></ul></div></div><div class='para' id='10'><div class='marginalizedparent'><a class='marginalized' href='#10'>10</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/6fe84caba29605d8445c039f585bd9951a0f3e03/source/declarations.tex#L6890'>#</a></div><div class='texpara'><div id='10.sentence-1' class='sentence'>If a search for the name <span class='texttt'>get_<span class='shy'></span>return_<span class='shy'></span>object_<span class='shy'></span>on_<span class='shy'></span>allocation_<span class='shy'></span>failure</span>
in the scope of the promise type (<a href='class.member.lookup' title='6.5.2&emsp;Member name lookup'>[class.<span class='shy'></span>member.<span class='shy'></span>lookup]</a>) finds
any declarations, then the result
of a call to an allocation function used to obtain storage for the coroutine
state is assumed to return <span id=':nullptr'><span class='texttt'><span class='literal'>nullptr</span></span></span> if it fails to obtain storage,
and if a global allocation function is selected,
the <span class='texttt'><span class='operator'>&#x200b;::&#x200b;</span><span class='keyword'>operator</span> <span class='keyword'>new</span><span class='parenthesis'>(</span>size_<span class='shy'></span>t, nothrow_<span class='shy'></span>t<span class='parenthesis'>)</span></span> form is used<a class='hidden_link' href='#10.sentence-1'>.</a></div> <div id='10.sentence-2' class='sentence'>The allocation function used in this case shall have a non-throwing
<a href='except.spec#nt:noexcept-specifier' title='14.5&emsp;Exception specifications&emsp;[except.spec]'><span id='ntref:noexcept-specifier'><span class='textsf'><i >noexcept-specifier</i></span></span></a><a class='hidden_link' href='#10.sentence-2'>.</a></div> <div id='10.sentence-3' class='sentence'>If the allocation function returns <span id=':nullptr_'><span class='texttt'><span class='literal'>nullptr</span></span></span>, the coroutine transfers
control to the caller of the coroutine and the return value is obtained by a
call to <span class='texttt'>T<span class='operator'>&#x200b;::&#x200b;</span>get_<span class='shy'></span>return_<span class='shy'></span>object_<span class='shy'></span>on_<span class='shy'></span>allocation_<span class='shy'></span>failure<span class='parenthesis'>(</span><span class='parenthesis'>)</span></span>, where <span class='texttt'>T</span>
is the promise type<a class='hidden_link' href='#10.sentence-3'>.</a></div></div><div class='texpara'><div id='example-2' class='example'><div class='texpara'>[<i>Example&nbsp;<a href='#example-2'>2</a></i>:&ensp;<span class='codeblock'><span class='preprocessordirective'>#include</span> <span class='anglebracket'>&lt;</span>iostream<span class='anglebracket'>&gt;</span>
<span class='preprocessordirective'>#include</span> <span class='anglebracket'>&lt;</span>coroutine<span class='anglebracket'>&gt;</span>

<span class='comment'>// <span class='tcode_in_codeblock'>&#x200b;::&#x200b;operator new(size_<span class='shy'></span>t, nothrow_<span class='shy'></span>t)</span> will be used if allocation is needed</span>
<span class='keyword'>struct</span> generator <span class='curlybracket'>{</span>
  <span class='keyword'>struct</span> promise_type;
  <span class='keyword'>using</span> handle <span class='operator'>=</span> std<span class='operator'>::</span>coroutine_handle<span class='anglebracket'>&lt;</span>promise_type<span class='anglebracket'>&gt;</span>;
  <span class='keyword'>struct</span> promise_type <span class='curlybracket'>{</span>
    <span class='keyword'>int</span> current_value;
    <span class='keyword'>static</span> <span class='keyword'>auto</span> get_return_object_on_allocation_failure<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> generator<span class='curlybracket'>{</span><span class='literal'>nullptr</span><span class='curlybracket'>}</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>auto</span> get_return_object<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> generator<span class='curlybracket'>{</span>handle<span class='operator'>::</span>from_promise<span class='parenthesis'>(</span><span class='operator'>*</span><span class='keyword'>this</span><span class='parenthesis'>)</span><span class='curlybracket'>}</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>auto</span> initial_suspend<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> std<span class='operator'>::</span>suspend_always<span class='curlybracket'>{</span><span class='curlybracket'>}</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>auto</span> final_suspend<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> std<span class='operator'>::</span>suspend_always<span class='curlybracket'>{</span><span class='curlybracket'>}</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>void</span> unhandled_exception<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> std<span class='operator'>::</span>terminate<span class='parenthesis'>(</span><span class='parenthesis'>)</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>void</span> return_void<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
    <span class='keyword'>auto</span> yield_value<span class='parenthesis'>(</span><span class='keyword'>int</span> value<span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
      current_value <span class='operator'>=</span> value;
      <span class='keyword'>return</span> std<span class='operator'>::</span>suspend_always<span class='curlybracket'>{</span><span class='curlybracket'>}</span>;
    <span class='curlybracket'>}</span>
  <span class='curlybracket'>}</span>;
  <span class='keyword'>bool</span> move_next<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> coro <span class='operator'>?</span> <span class='parenthesis'>(</span>coro<span class='operator'>.</span>resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span>, <span class='operator'>!</span>coro<span class='operator'>.</span>done<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span> <span class='operator'>:</span> <span class='literal'>false</span>; <span class='curlybracket'>}</span>
  <span class='keyword'>int</span> current_value<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> coro<span class='operator'>.</span>promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='operator'>.</span>current_value; <span class='curlybracket'>}</span>
  generator<span class='parenthesis'>(</span>generator <span class='keyword'>const</span><span class='operator'>&amp;</span><span class='parenthesis'>)</span> <span class='operator'>=</span> <span class='keyword'>delete</span>;
  generator<span class='parenthesis'>(</span>generator <span class='operator'>&amp;</span><span class='operator'>&amp;</span> rhs<span class='parenthesis'>)</span> <span class='operator'>:</span> coro<span class='parenthesis'>(</span>rhs<span class='operator'>.</span>coro<span class='parenthesis'>)</span> <span class='curlybracket'>{</span> rhs<span class='operator'>.</span>coro <span class='operator'>=</span> <span class='literal'>nullptr</span>; <span class='curlybracket'>}</span>
  <span class='operator'>~</span>generator<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>if</span> <span class='parenthesis'>(</span>coro<span class='parenthesis'>)</span> coro<span class='operator'>.</span>destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span>; <span class='curlybracket'>}</span>
<span class='keyword'>private</span><span class='operator'>:</span>
  generator<span class='parenthesis'>(</span>handle h<span class='parenthesis'>)</span> <span class='operator'>:</span> coro<span class='parenthesis'>(</span>h<span class='parenthesis'>)</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
  handle coro;
<span class='curlybracket'>}</span>;
generator f<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span> <span class='keyword'>co_yield</span> <span class='literal'>1</span>; <span class='keyword'>co_yield</span> <span class='literal'>2</span>; <span class='curlybracket'>}</span>
<span class='keyword'>int</span> main<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='curlybracket'>{</span>
  <span class='keyword'>auto</span> g <span class='operator'>=</span> f<span class='parenthesis'>(</span><span class='parenthesis'>)</span>;
  <span class='keyword'>while</span> <span class='parenthesis'>(</span>g<span class='operator'>.</span>move_next<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span> std<span class='operator'>::</span>cout <span class='anglebracket'>&lt;</span><span class='anglebracket'>&lt;</span> g<span class='operator'>.</span>current_value<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='anglebracket'>&lt;</span><span class='anglebracket'>&lt;</span> std<span class='operator'>::</span>endl;
<span class='curlybracket'>}</span>
</span> —&nbsp;<i>end example</i>]</div></div></div></div><div class='para' id='11'><div class='marginalizedparent'><a class='marginalized' href='#11'>11</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/6fe84caba29605d8445c039f585bd9951a0f3e03/source/declarations.tex#L6944'>#</a></div><div class='texpara'><div id='11.sentence-1' class='sentence'>The coroutine state is destroyed when control flows off the end of the
coroutine or the <span class='texttt'>destroy</span> member
function (<a href='coroutine.handle.resumption' title='17.12.4.6&emsp;Resumption'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>resumption]</a>)
of a coroutine handle (<a href='coroutine.handle' title='17.12.4&emsp;Class template coroutine_&shy;handle'>[coroutine.<span class='shy'></span>handle]</a>)
that refers to the coroutine
is invoked<a class='hidden_link' href='#11.sentence-1'>.</a></div> <div id='11.sentence-2' class='sentence'>In the latter case,
control in the coroutine is considered
to be transferred out of the function (<a href='stmt.dcl' title='8.8&emsp;Declaration statement'>[stmt.<span class='shy'></span>dcl]</a>)<a class='hidden_link' href='#11.sentence-2'>.</a></div> <div id='11.sentence-3' class='sentence'>The storage for the coroutine state is released by calling a
non-array deallocation function (<a href='basic.stc.dynamic.deallocation' title='6.7.5.5.3&emsp;Deallocation functions'>[basic.<span class='shy'></span>stc.<span class='shy'></span>dynamic.<span class='shy'></span>deallocation]</a>)<a class='hidden_link' href='#11.sentence-3'>.</a></div> <div id='11.sentence-4' class='sentence'>If <span class='texttt'>destroy</span> is called for a coroutine that is not suspended, the
program has undefined behavior<a class='hidden_link' href='#11.sentence-4'>.</a></div></div></div><div class='para' id='12'><div class='marginalizedparent'><a class='marginalized' href='#12'>12</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/6fe84caba29605d8445c039f585bd9951a0f3e03/source/declarations.tex#L6959'>#</a></div><div class='texpara'><div id='12.sentence-1' class='sentence'>The deallocation function's name is looked up by searching for it in the scope of the promise type<a class='hidden_link' href='#12.sentence-1'>.</a></div> <div id='12.sentence-2' class='sentence'>If nothing is found, a search is performed in the
global scope<a class='hidden_link' href='#12.sentence-2'>.</a></div> <div id='12.sentence-3' class='sentence'>If both a usual deallocation
function with only a pointer parameter and a usual deallocation function with
both a pointer parameter and a size parameter are found, then the selected deallocation
function shall be the one with two parameters<a class='hidden_link' href='#12.sentence-3'>.</a></div> <div id='12.sentence-4' class='sentence'>Otherwise, the selected
deallocation function shall be the function with one parameter<a class='hidden_link' href='#12.sentence-4'>.</a></div> <div id='12.sentence-5' class='sentence'>If no usual
deallocation function is found, the program is ill-formed<a class='hidden_link' href='#12.sentence-5'>.</a></div> <div id='12.sentence-6' class='sentence'>The selected deallocation function shall be called with the address of the
block of storage to be reclaimed as its first argument<a class='hidden_link' href='#12.sentence-6'>.</a></div> <div id='12.sentence-7' class='sentence'>If a deallocation
function with a parameter of type <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>size_<span class='shy'></span>t</span> is used, the size of
the block is passed as the corresponding argument<a class='hidden_link' href='#12.sentence-7'>.</a></div></div></div>

<div class='para added' id='elide-allocation-wording'><div class='marginalizedparent'><a class='marginalized' href='#elide-allocation-wording'>??</a></div><div class='sourceLinkParent'><a class='sourceLink' href=''>#</a></div><div class='texpara'><div id='??.sentence-1' class='sentence'>During constant evaluation all calls to allocation and deallocation functions found to provide the coroutine state are elided<a class='hidden_link' href='#??.sentence-1'>.</a></div></div></div>

</div>	<div class='wording'>
<h2 ><a class='secnum' style='min-width:65pt'>17.12</a> Coroutines <a class='abbr_ref'>[support.coroutine]</a></h2><div id='general' class='section'><h3 ><a class='secnum' href='#general' style='min-width:80pt'>17.12.1</a> General <a class='abbr_ref' href='support.coroutine.general'>[support.coroutine.general]</a></h3><div class='para' id='general-1'><div class='marginalizedparent'><a class='marginalized' href='#general-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5146'>#</a></div><div class='texpara'><div id='general-1.sentence-1' class='sentence'>The header <span id='header:<coroutine>'><span class='texttt'><span class='anglebracket'>&lt;</span>coroutine<span class='anglebracket'>&gt;</span></span></span>
defines several types providing
compile and run-time support for
coroutines in a C++ program<a class='hidden_link' href='#general-1.sentence-1'>.</a></div></div></div></div><div id='coroutine.syn' class='section'><h3 ><a class='secnum' href='#coroutine.syn' style='min-width:80pt'>17.12.2</a> Header <span class='texttt'>&lt;coroutine&gt;</span> synopsis <a class='abbr_ref' href='coroutine.syn'>[coroutine.syn]</a></h3><div class='texpara'><span id='lib:noop_coroutine_handle'><span id='header:<coroutine>_'><div class='marginalizedparent'><a class='itemDeclLink' href='#header:%3ccoroutine%3e_'>🔗</a></div><span class='codeblock'><span class='comment'>// all freestanding</span>
<span class='preprocessordirective'>#include</span> <span class='anglebracket'>&lt;</span>compare<span class='anglebracket'>&gt;</span>              <span class='comment'>// see <a href='compare.syn' title='17.11.1&emsp;Header &lt;compare&gt; synopsis'>[compare.<span class='shy'></span>syn]</a></span>

<span class='keyword'>namespace</span> std <span class='curlybracket'>{</span>
  <span class='comment'>// <a href='#coroutine.traits' title='17.12.3&emsp;Coroutine traits'>[coroutine.<span class='shy'></span>traits]</a>, coroutine traits</span>
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> R, <span class='keyword'>class</span><span class='operator'>.</span><span class='operator'>.</span><span class='operator'>.</span> ArgTypes<span class='anglebracket'>&gt;</span>
    <span class='keyword'>struct</span> coroutine_traits;

  <span class='comment'>// <a href='#coroutine.handle' title='17.12.4&emsp;Class template coroutine_&shy;handle'>[coroutine.<span class='shy'></span>handle]</a>, coroutine handle</span>
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> Promise <span class='operator'>=</span> <span class='keyword'>void</span><span class='anglebracket'>&gt;</span>
    <span class='keyword'>struct</span> coroutine_handle;

  <span class='comment'>// <a href='#coroutine.handle.compare' title='17.12.4.8&emsp;Comparison operators'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>compare]</a>, comparison operators</span>
  <span class='keyword'>constexpr</span> <span class='keyword'>bool</span> <span class='keyword'>operator</span><span class='operator'>=</span><span class='operator'>=</span><span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> x, coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> y<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
  <span class='keyword'>constexpr</span> strong_ordering <span class='keyword'>operator</span><span class='anglebracket'>&lt;</span><span class='operator'>=</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> x, coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> y<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;

  <span class='comment'>// <a href='#coroutine.handle.hash' title='17.12.4.9&emsp;Hash support'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>hash]</a>, hash support</span>
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> T<span class='anglebracket'>&gt;</span> <span class='keyword'>struct</span> hash;
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> P<span class='anglebracket'>&gt;</span> <span class='keyword'>struct</span> hash<span class='anglebracket'>&lt;</span>coroutine_handle<span class='anglebracket'>&lt;</span>P<span class='anglebracket'>&gt;</span><span class='anglebracket'>&gt;</span>;

  <span class='comment'>// <a href='#coroutine.noop' title='17.12.5&emsp;No-op coroutines'>[coroutine.<span class='shy'></span>noop]</a>, no-op coroutines</span>
  <span class='keyword'>struct</span> noop_coroutine_promise;

  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> <span class='keyword'>struct</span> coroutine_handle<span class='anglebracket'>&lt;</span>noop_coroutine_promise<span class='anglebracket'>&gt;</span>;
  <span class='keyword'>using</span> noop_coroutine_handle <span class='operator'>=</span> coroutine_handle<span class='anglebracket'>&lt;</span>noop_coroutine_promise<span class='anglebracket'>&gt;</span>;

  <span class="added keyword">constexpr </span>noop_coroutine_handle noop_coroutine<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;

  <span class='comment'>// <a href='#coroutine.trivial.awaitables' title='17.12.6&emsp;Trivial awaitables'>[coroutine.<span class='shy'></span>trivial.<span class='shy'></span>awaitables]</a>, trivial awaitables</span>
  <span class='keyword'>struct</span> suspend_never;
  <span class='keyword'>struct</span> suspend_always;
<span class='curlybracket'>}</span>
</span></span></span></div></div><div id='coroutine.traits' class='section'><h3 ><a class='secnum' href='#coroutine.traits' style='min-width:80pt'>17.12.3</a> Coroutine traits <a class='abbr_ref' href='coroutine.traits'>[coroutine.traits]</a></h3><div id='coroutine.traits.general' class='section'><h4 ><a class='secnum' href='#coroutine.traits.general' style='min-width:95pt'>17.12.3.1</a> General <a class='abbr_ref' href='coroutine.traits.general'>[coroutine.traits.general]</a></h4><div class='para' id='coroutine.traits.general-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.traits.general-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5195'>#</a></div><div class='texpara'><div id='coroutine.traits.general-1.sentence-1' class='sentence'>Subclause <a href='#coroutine.traits' title='17.12.3&emsp;Coroutine traits'>[coroutine.<span class='shy'></span>traits]</a> defines requirements on classes representing
<a class='hidden_link' href='#def:coroutine_traits' id='def:coroutine_traits'><i>coroutine traits</i></a>,
and defines the class template
<span class='texttt'>coroutine_<span class='shy'></span>traits</span>
that meets those requirements<a class='hidden_link' href='#coroutine.traits.general-1.sentence-1'>.</a></div></div></div></div><div id='coroutine.traits.primary' class='section'><h4 ><a class='secnum' href='#coroutine.traits.primary' style='min-width:95pt'>17.12.3.2</a> Class template <span class='texttt'>coroutine_<span class='shy'></span>traits</span> <a class='abbr_ref' href='coroutine.traits.primary'>[coroutine.traits.primary]</a></h4><div class='texpara'><a class='index' id='lib:coroutine_traits'></a></div><div class='para' id='coroutine.traits.primary-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.traits.primary-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5205'>#</a></div><div class='texpara'><div id='coroutine.traits.primary-1.sentence-1' class='sentence'>The header <a href='#header:%3ccoroutine%3e' title='17.12.2&emsp;Header &lt;coroutine&gt; synopsis&emsp;[coroutine.syn]'><span id='headerref:<coroutine>'><span class='texttt'>&lt;coroutine&gt;</span></span></a> defines the primary template
<span class='texttt'>coroutine_<span class='shy'></span>traits</span> such that
if <span class='texttt'>ArgTypes</span> is a parameter pack of types and
if the <a href='expr.prim.id.qual#nt:qualified-id' title='7.5.5.3&emsp;Qualified names&emsp;[expr.prim.id.qual]'><span id='ntref:qualified-id'><span class='textsf'><i >qualified-id</i></span></span></a> <span class='texttt'>R<span class='operator'>&#x200b;::&#x200b;</span>promise_<span class='shy'></span>type</span> is valid and
denotes a type (<a href='temp.deduct' title='13.10.3&emsp;Template argument deduction'>[temp.<span class='shy'></span>deduct]</a>),
then <span class='texttt'>coroutine_<span class='shy'></span>traits<span class='anglebracket'>&lt;</span>R, ArgTypes<span class='operator'>.</span><span class='operator'>.</span><span class='operator'>.</span><span class='anglebracket'>&gt;</span></span> has the following publicly
accessible member:
<span class='codeblock'><span class='keyword'>using</span> promise_type <span class='operator'>=</span> <span class='keyword'>typename</span> R<span class='operator'>::</span>promise_type;
</span></div></div><div class='texpara'><div id='coroutine.traits.primary-1.sentence-2' class='sentence'>Otherwise, <span class='texttt'>coroutine_<span class='shy'></span>traits<span class='anglebracket'>&lt;</span>R, ArgTypes<span class='operator'>.</span><span class='operator'>.</span><span class='operator'>.</span><span class='anglebracket'>&gt;</span></span> has no members<a class='hidden_link' href='#coroutine.traits.primary-1.sentence-2'>.</a></div></div></div><div class='para' id='coroutine.traits.primary-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.traits.primary-2'>2</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5219'>#</a></div><div class='texpara'><div id='coroutine.traits.primary-2.sentence-1' class='sentence'>Program-defined specializations of this template shall define a publicly
accessible nested type named <span class='texttt'>promise_<span class='shy'></span>type</span><a class='hidden_link' href='#coroutine.traits.primary-2.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle' class='section'><h3 ><a class='secnum' href='#coroutine.handle' style='min-width:80pt'>17.12.4</a> Class template <span class='texttt'>coroutine_<span class='shy'></span>handle</span> <a class='abbr_ref' href='coroutine.handle'>[coroutine.handle]</a></h3><div id='coroutine.handle.general' class='section'><h4 ><a class='secnum' href='#coroutine.handle.general' style='min-width:95pt'>17.12.4.1</a> General <a class='abbr_ref' href='coroutine.handle.general'>[coroutine.handle.general]</a></h4><div class='texpara'><span id='lib:coroutine_handle'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:coroutine_handle'>🔗</a></div><span class='codeblock'><span class='keyword'>namespace</span> std <span class='curlybracket'>{</span>
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span>
  <span class='keyword'>struct</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='keyword'>void</span><span class='anglebracket'>&gt;</span>
  <span class='curlybracket'>{</span>
    <span class='comment'>// <a href='#coroutine.handle.con' title='17.12.4.2&emsp;Construct/reset'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>con]</a>, construct/reset</span>
    <span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
    <span class='keyword added'>constexpr</span> coroutine_handle<span class='operator'>&amp;</span> <span class='keyword'>operator</span><span class='operator'>=</span><span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.export.import' title='17.12.4.4&emsp;Export/import'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>export.<span class='shy'></span>import]</a>, export/import</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span><span class='operator'>*</span> address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>static</span> <span class='keyword'>constexpr</span> coroutine_handle from_address<span class='parenthesis'>(</span><span class='keyword'>void</span><span class='operator'>*</span> addr<span class='parenthesis'>)</span>;

    <span class='comment'>// <a href='#coroutine.handle.observers' title='17.12.4.5&emsp;Observers'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>observers]</a>, observers</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>explicit</span> <span class='keyword'>operator</span> <span class='keyword'>bool</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>bool</span> done<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;

    <span class='comment'>// <a href='#coroutine.handle.resumption' title='17.12.4.6&emsp;Resumption'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>resumption]</a>, resumption</span>
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> <span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;

  <span class='keyword'>private</span><span class='operator'>:</span>
    <span class='keyword'>void</span><span class='operator'>*</span> ptr;  <span class='comment'>// <i >exposition only</i></span>
  <span class='curlybracket'>}</span>;

  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> Promise<span class='anglebracket'>&gt;</span>
  <span class='keyword'>struct</span> coroutine_handle
  <span class='curlybracket'>{</span>
    <span class='comment'>// <a href='#coroutine.handle.con' title='17.12.4.2&emsp;Construct/reset'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>con]</a>, construct/reset</span>
    <span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>static</span> <span class='keyword added'>constexpr</span> coroutine_handle from_promise<span class='parenthesis'>(</span>Promise<span class='operator'>&amp;</span><span class='parenthesis'>)</span>;
    <span class='keyword added'>constexpr</span> coroutine_handle<span class='operator'>&amp;</span> <span class='keyword'>operator</span><span class='operator'>=</span><span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.export.import' title='17.12.4.4&emsp;Export/import'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>export.<span class='shy'></span>import]</a>, export/import</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span><span class='operator'>*</span> address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>static</span> <span class='keyword'>constexpr</span> coroutine_handle from_address<span class='parenthesis'>(</span><span class='keyword'>void</span><span class='operator'>*</span> addr<span class='parenthesis'>)</span>;

    <span class='comment'>// <a href='#coroutine.handle.conv' title='17.12.4.3&emsp;Conversion'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>conv]</a>, conversion</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>operator</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.observers' title='17.12.4.5&emsp;Observers'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>observers]</a>, observers</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>explicit</span> <span class='keyword'>operator</span> <span class='keyword'>bool</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>bool</span> done<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;

    <span class='comment'>// <a href='#coroutine.handle.resumption' title='17.12.4.6&emsp;Resumption'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>resumption]</a>, resumption</span>
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> <span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
    <span class='keyword added'>constexpr</span> <span class='keyword'>void</span> destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;

    <span class='comment'>// <a href='#coroutine.handle.promise' title='17.12.4.7&emsp;Promise access'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>promise]</a>, promise access</span>
    <span class='keyword added'>constexpr</span> Promise<span class='operator'>&amp;</span> promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;

  <span class='keyword'>private</span><span class='operator'>:</span>
    <span class='keyword'>void</span><span class='operator'>*</span> ptr;  <span class='comment'>// <i >exposition only</i></span>
  <span class='curlybracket'>}</span>;
<span class='curlybracket'>}</span>
</span></span></div><div class='para' id='coroutine.handle.general-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.general-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5289'>#</a></div><div class='texpara'><div id='coroutine.handle.general-1.sentence-1' class='sentence'>An object of type
<span class='texttt'>coroutine_<span class='shy'></span>handle<span class='anglebracket'>&lt;</span>T<span class='anglebracket'>&gt;</span></span> is called a <a class='hidden_link' href='#def:coroutine_handle' id='def:coroutine_handle'><i>coroutine handle</i></a>
and can be used to refer to a suspended or executing coroutine<a class='hidden_link' href='#coroutine.handle.general-1.sentence-1'>.</a></div> <div id='coroutine.handle.general-1.sentence-2' class='sentence'>A <span class='texttt'>coroutine_<span class='shy'></span>handle</span> object whose
member <span class='texttt'>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span></span> returns a null pointer value
does not refer to any
coroutine<a class='hidden_link' href='#coroutine.handle.general-1.sentence-2'>.</a></div> <div id='coroutine.handle.general-1.sentence-3' class='sentence'>Two <span class='texttt'>coroutine_<span class='shy'></span>handle</span> objects refer to the same coroutine
if and only if their member <span class='texttt'>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span></span> returns the same non-null value<a class='hidden_link' href='#coroutine.handle.general-1.sentence-3'>.</a></div></div></div><div class='para' id='coroutine.handle.general-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.general-2'>2</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5300'>#</a></div><div class='texpara'><div id='coroutine.handle.general-2.sentence-1' class='sentence'>If a program declares an explicit or partial specialization of
<span class='texttt'>coroutine_<span class='shy'></span>handle</span>, the behavior is undefined<a class='hidden_link' href='#coroutine.handle.general-2.sentence-1'>.</a></div></div></div></div><div id='coroutine.handle.con' class='section'><h4 ><a class='secnum' href='#coroutine.handle.con' style='min-width:95pt'>17.12.4.2</a> Construct/reset <a class='abbr_ref' href='coroutine.handle.con'>[coroutine.handle.con]</a></h4><div class='texpara'><div id='lib:coroutine_handle,constructor'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:coroutine_handle,constructor'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
<span class='keyword'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
</code></div></div></div><div class='para' id='coroutine.handle.con-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5313'>#</a></div><div class='texpara'><div id='coroutine.handle.con-1.sentence-1' class='sentence'><i >Postconditions</i>: <span class='texttt'>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> <span class='literal'>nullptr</span></span><a class='hidden_link' href='#coroutine.handle.con-1.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,from_promise'><div id='lib:from_promise,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:from_promise,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>static</span> <span class='keyword added'>constexpr</span> coroutine_handle from_promise<span class='parenthesis'>(</span>Promise<span class='operator'>&amp;</span> p<span class='parenthesis'>)</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.con-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5324'>#</a></div><div class='texpara'><div id='coroutine.handle.con-2.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'>p</span> is a reference to a promise object of a coroutine<a class='hidden_link' href='#coroutine.handle.con-2.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.con-3'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-3'>3</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5328'>#</a></div><div class='texpara'><div id='coroutine.handle.con-3.sentence-1' class='sentence'><i >Postconditions</i>: <span class='texttt'>addressof<span class='parenthesis'>(</span>h<span class='operator'>.</span>promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> addressof<span class='parenthesis'>(</span>p<span class='parenthesis'>)</span></span><a class='hidden_link' href='#coroutine.handle.con-3.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.con-4'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-4'>4</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5332'>#</a></div><div class='texpara'><div id='coroutine.handle.con-4.sentence-1' class='sentence'><i >Returns</i>: A coroutine handle <span class='texttt'>h</span> referring to the coroutine<a class='hidden_link' href='#coroutine.handle.con-4.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,operator='><div id='lib:operator=,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator=,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> coroutine_handle<span class='operator'>&amp;</span> <span class='keyword'>operator</span><span class='operator'>=</span><span class='parenthesis'>(</span>nullptr_t<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.con-5'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-5'>5</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5343'>#</a></div><div class='texpara'><div id='coroutine.handle.con-5.sentence-1' class='sentence'><i >Postconditions</i>: <span class='texttt'>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> <span class='literal'>nullptr</span></span><a class='hidden_link' href='#coroutine.handle.con-5.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.con-6'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.con-6'>6</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5347'>#</a></div><div class='texpara'><div id='coroutine.handle.con-6.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'><span class='operator'>*</span><span class='keyword'>this</span></span><a class='hidden_link' href='#coroutine.handle.con-6.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.conv' class='section'><h4 ><a class='secnum' href='#coroutine.handle.conv' style='min-width:95pt'>17.12.4.3</a> Conversion <a class='abbr_ref' href='coroutine.handle.conv'>[coroutine.handle.conv]</a></h4><div class='texpara'><div id='lib:coroutine_handle,operator_coroutine_handle<>'><div id='lib:operator_coroutine_handle<>,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator_coroutine_handle%3c%3e,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>operator</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.conv-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.conv-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5360'>#</a></div><div class='texpara'><div id='coroutine.handle.conv-1.sentence-1' class='sentence'><i >Effects</i>: Equivalent to: <span class='texttt'><span class='keyword'>return</span> coroutine_<span class='shy'></span>handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='operator'>&#x200b;::&#x200b;</span>from_<span class='shy'></span>address<span class='parenthesis'>(</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span>;</span></div></div></div></div></div><div id='coroutine.handle.export.import' class='section'><h4 ><a class='secnum' href='#coroutine.handle.export.import' style='min-width:95pt'>17.12.4.4</a> Export/import <a class='abbr_ref' href='coroutine.handle.export.import'>[coroutine.handle.export.import]</a></h4><div class='texpara'><div id='lib:coroutine_handle,address'><div id='lib:address,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:address,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>void</span><span class='operator'>*</span> address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.export.import-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.export.import-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5373'>#</a></div><div class='texpara'><div id='coroutine.handle.export.import-1.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'>ptr</span><a class='hidden_link' href='#coroutine.handle.export.import-1.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,from_address'><div id='lib:from_address,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:from_address,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>static</span> <span class='keyword'>constexpr</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='operator'>::</span>from_address<span class='parenthesis'>(</span><span class='keyword'>void</span><span class='operator'>*</span> addr<span class='parenthesis'>)</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.export.import-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.export.import-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5384'>#</a></div><div class='texpara'><div id='coroutine.handle.export.import-2.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'>addr</span> was obtained via a prior call to <span class='texttt'>address</span>
on an object whose type is a specialization of <span class='texttt'>coroutine_<span class='shy'></span>handle</span><a class='hidden_link' href='#coroutine.handle.export.import-2.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.export.import-3'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.export.import-3'>3</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5389'>#</a></div><div class='texpara'><div id='coroutine.handle.export.import-3.sentence-1' class='sentence'><i >Postconditions</i>: <span class='texttt'>from_<span class='shy'></span>address<span class='parenthesis'>(</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> <span class='operator'>*</span><span class='keyword'>this</span></span><a class='hidden_link' href='#coroutine.handle.export.import-3.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,from_address_'><div id='lib:from_address,coroutine_handle_'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:from_address,coroutine_handle_'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>static</span> <span class='keyword'>constexpr</span> coroutine_handle<span class='anglebracket'>&lt;</span>Promise<span class='anglebracket'>&gt;</span> coroutine_handle<span class='anglebracket'>&lt;</span>Promise<span class='anglebracket'>&gt;</span><span class='operator'>::</span>from_address<span class='parenthesis'>(</span><span class='keyword'>void</span><span class='operator'>*</span> addr<span class='parenthesis'>)</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.export.import-4'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.export.import-4'>4</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5400'>#</a></div><div class='texpara'><div id='coroutine.handle.export.import-4.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'>addr</span> was obtained via a prior call to <span class='texttt'>address</span>
on an object of type <span class='mathit'>cv</span> <span class='texttt'>coroutine_<span class='shy'></span>handle<span class='anglebracket'>&lt;</span>Promise<span class='anglebracket'>&gt;</span></span><a class='hidden_link' href='#coroutine.handle.export.import-4.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.export.import-5'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.export.import-5'>5</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5405'>#</a></div><div class='texpara'><div id='coroutine.handle.export.import-5.sentence-1' class='sentence'><i >Postconditions</i>: <span class='texttt'>from_<span class='shy'></span>address<span class='parenthesis'>(</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> <span class='operator'>*</span><span class='keyword'>this</span></span><a class='hidden_link' href='#coroutine.handle.export.import-5.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.observers' class='section'><h4 ><a class='secnum' href='#coroutine.handle.observers' style='min-width:95pt'>17.12.4.5</a> Observers <a class='abbr_ref' href='coroutine.handle.observers'>[coroutine.handle.observers]</a></h4><div class='texpara'><div id='lib:coroutine_handle,operator_bool'><div id='lib:operator_bool,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator_bool,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>explicit</span> <span class='keyword'>operator</span> <span class='keyword'>bool</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.observers-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.observers-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5418'>#</a></div><div class='texpara'><div id='coroutine.handle.observers-1.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='operator'>!</span><span class='operator'>=</span> <span class='literal'>nullptr</span></span><a class='hidden_link' href='#coroutine.handle.observers-1.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,done'><div id='lib:done,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:done,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> <span class='keyword'>bool</span> done<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.observers-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.observers-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5429'>#</a></div><div class='texpara'><div id='coroutine.handle.observers-2.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'><span class='operator'>*</span><span class='keyword'>this</span></span> refers to a suspended coroutine<a class='hidden_link' href='#coroutine.handle.observers-2.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.observers-3'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.observers-3'>3</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5433'>#</a></div><div class='texpara'><div id='coroutine.handle.observers-3.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'><span class='literal'>true</span></span> if the coroutine is suspended at its
final suspend point, otherwise <span class='texttt'><span class='literal'>false</span></span><a class='hidden_link' href='#coroutine.handle.observers-3.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.resumption' class='section'><h4 ><a class='secnum' href='#coroutine.handle.resumption' style='min-width:95pt'>17.12.4.6</a> Resumption <a class='abbr_ref' href='coroutine.handle.resumption'>[coroutine.handle.resumption]</a></h4><div class='para' id='coroutine.handle.resumption-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.resumption-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5441'>#</a></div><div class='texpara'><div id='coroutine.handle.resumption-1.sentence-1' class='sentence'>Resuming a coroutine via <span class='texttt'>resume</span>, <span class='texttt'><span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span></span>, or <span class='texttt'>destroy</span>
on an execution agent other than the one on which it was suspended
has <a class='index' id=':resuming_a_coroutine_on_a_different_execution_agent'></a>implementation-defined behavior
unless
each execution agent either is
an instance of <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>thread</span> or <span class='texttt'>std<span class='operator'>&#x200b;::&#x200b;</span>jthread</span>,
or is the thread that executes <span class='texttt'>main</span><a class='hidden_link' href='#coroutine.handle.resumption-1.sentence-1'>.</a></div> <div id='coroutine.handle.resumption-note-1' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#coroutine.handle.resumption-note-1'>1</a></i>:&ensp;<div id='coroutine.handle.resumption-1.sentence-2' class='sentence'>A coroutine that is resumed on a different execution agent should
avoid relying on consistent thread identity throughout, such as holding
a mutex object across a suspend point<a class='hidden_link' href='#coroutine.handle.resumption-1.sentence-2'>.</a></div> —&nbsp;<i>end note</i>]</div></div> <div id='coroutine.handle.resumption-note-2' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#coroutine.handle.resumption-note-2'>2</a></i>:&ensp;<div id='coroutine.handle.resumption-1.sentence-3' class='sentence'>A concurrent resumption of the coroutine can result in a data race<a class='hidden_link' href='#coroutine.handle.resumption-1.sentence-3'>.</a></div> —&nbsp;<i>end note</i>]</div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,resume'><div id='lib:resume,coroutine_handle'><div id='lib:coroutine_handle,operator()'><div id='lib:operator(),coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator(),coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> <span class='keyword'>void</span> <span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
<span class='keyword added'>constexpr</span> <span class='keyword'>void</span> resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
</code></div></div></div></div></div></div><div class='para' id='coroutine.handle.resumption-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.resumption-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5466'>#</a></div><div class='texpara'><div id='coroutine.handle.resumption-2.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'><span class='operator'>*</span><span class='keyword'>this</span></span> refers to a suspended coroutine<a class='hidden_link' href='#coroutine.handle.resumption-2.sentence-1'>.</a></div> <div id='coroutine.handle.resumption-2.sentence-2' class='sentence'>The coroutine is not suspended at its final suspend point<a class='hidden_link' href='#coroutine.handle.resumption-2.sentence-2'>.</a></div></div></div></div><div class='para' id='coroutine.handle.resumption-3'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.resumption-3'>3</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5471'>#</a></div><div class='texpara'><div id='coroutine.handle.resumption-3.sentence-1' class='sentence'><i >Effects</i>: Resumes the execution of the coroutine<a class='hidden_link' href='#coroutine.handle.resumption-3.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,destroy'><div id='lib:destroy,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:destroy,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> <span class='keyword'>void</span> destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.resumption-4'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.resumption-4'>4</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5482'>#</a></div><div class='texpara'><div id='coroutine.handle.resumption-4.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'><span class='operator'>*</span><span class='keyword'>this</span></span> refers to a suspended coroutine<a class='hidden_link' href='#coroutine.handle.resumption-4.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.resumption-5'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.resumption-5'>5</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5486'>#</a></div><div class='texpara'><div id='coroutine.handle.resumption-5.sentence-1' class='sentence'><i >Effects</i>: Destroys the coroutine (<a href='dcl.fct.def.coroutine' title='9.5.4&emsp;Coroutine definitions'>[dcl.<span class='shy'></span>fct.<span class='shy'></span>def.<span class='shy'></span>coroutine]</a>)<a class='hidden_link' href='#coroutine.handle.resumption-5.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.promise' class='section'><h4 ><a class='secnum' href='#coroutine.handle.promise' style='min-width:95pt'>17.12.4.7</a> Promise access <a class='abbr_ref' href='coroutine.handle.promise'>[coroutine.handle.promise]</a></h4><div class='texpara'><div id='lib:coroutine_handle,promise'><div id='lib:promise,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:promise,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> Promise<span class='operator'>&amp;</span> promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.promise-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.promise-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5499'>#</a></div><div class='texpara'><div id='coroutine.handle.promise-1.sentence-1' class='sentence'><i >Preconditions</i>: <span class='texttt'><span class='operator'>*</span><span class='keyword'>this</span></span> refers to a coroutine<a class='hidden_link' href='#coroutine.handle.promise-1.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.promise-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.promise-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5503'>#</a></div><div class='texpara'><div id='coroutine.handle.promise-2.sentence-1' class='sentence'><i >Returns</i>: A reference to the promise of the coroutine<a class='hidden_link' href='#coroutine.handle.promise-2.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.compare' class='section'><h4 ><a class='secnum' href='#coroutine.handle.compare' style='min-width:95pt'>17.12.4.8</a> Comparison operators <a class='abbr_ref' href='coroutine.handle.compare'>[coroutine.handle.compare]</a></h4><div class='texpara'><div id='lib:coroutine_handle,operator!='><div id='lib:operator!=,coroutine_handle'><div id='lib:coroutine_handle,operator=='><div id='lib:operator==,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator==,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>bool</span> <span class='keyword'>operator</span><span class='operator'>=</span><span class='operator'>=</span><span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> x, coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> y<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div></div></div><div class='para' id='coroutine.handle.compare-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.compare-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5517'>#</a></div><div class='texpara'><div id='coroutine.handle.compare-1.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'>x<span class='operator'>.</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='operator'>=</span><span class='operator'>=</span> y<span class='operator'>.</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span></span><a class='hidden_link' href='#coroutine.handle.compare-1.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle,operator<=>'><div id='lib:operator<=>,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator%3c=%3e,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> strong_ordering <span class='keyword'>operator</span><span class='anglebracket'>&lt;</span><span class='operator'>=</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> x, coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span> y<span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.compare-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.compare-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5528'>#</a></div><div class='texpara'><div id='coroutine.handle.compare-2.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'>compare_<span class='shy'></span>three_<span class='shy'></span>way<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span>x<span class='operator'>.</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span>, y<span class='operator'>.</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span></span><a class='hidden_link' href='#coroutine.handle.compare-2.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.hash' class='section'><h4 ><a class='secnum' href='#coroutine.handle.hash' style='min-width:95pt'>17.12.4.9</a> Hash support <a class='abbr_ref' href='coroutine.handle.hash'>[coroutine.handle.hash]</a></h4><div class='texpara'><div id='lib:coroutine_handle,hash'><div id='lib:hash,coroutine_handle'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:hash,coroutine_handle'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='keyword'>class</span> P<span class='anglebracket'>&gt;</span> <span class='keyword'>struct</span> hash<span class='anglebracket'>&lt;</span>coroutine_handle<span class='anglebracket'>&lt;</span>P<span class='anglebracket'>&gt;</span><span class='anglebracket'>&gt;</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.hash-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.hash-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5541'>#</a></div><div class='texpara'><div id='coroutine.handle.hash-1.sentence-1' class='sentence'>The specialization is enabled (<a href='unord.hash' title='22.10.19&emsp;Class template hash'>[unord.<span class='shy'></span>hash]</a>)<a class='hidden_link' href='#coroutine.handle.hash-1.sentence-1'>.</a></div></div></div></div></div></div><div id='coroutine.noop' class='section'><h3 ><a class='secnum' href='#coroutine.noop' style='min-width:80pt'>17.12.5</a> No-op coroutines <a class='abbr_ref' href='coroutine.noop'>[coroutine.noop]</a></h3><div id='coroutine.promise.noop' class='section'><h4 ><a class='secnum' href='#coroutine.promise.noop' style='min-width:95pt'>17.12.5.1</a> Class <span class='texttt'>noop_<span class='shy'></span>coroutine_<span class='shy'></span>promise</span> <a class='abbr_ref' href='coroutine.promise.noop'>[coroutine.promise.noop]</a></h4><div class='texpara'><div id='lib:noop_coroutine_promise'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:noop_coroutine_promise'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>struct</span> noop_coroutine_promise <span class='curlybracket'>{</span><span class='curlybracket'>}</span>;
</code></div></div></div><div class='para' id='coroutine.promise.noop-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.promise.noop-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5555'>#</a></div><div class='texpara'><div id='coroutine.promise.noop-1.sentence-1' class='sentence'>The class <span class='texttt'>noop_<span class='shy'></span>coroutine_<span class='shy'></span>promise</span> defines the promise type for
the coroutine referred to
by <span class='texttt'>noop_<span class='shy'></span>coroutine_<span class='shy'></span>handle</span> (<a href='#coroutine.syn' title='17.12.2&emsp;Header &lt;coroutine&gt; synopsis'>[coroutine.<span class='shy'></span>syn]</a>)<a class='hidden_link' href='#coroutine.promise.noop-1.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.noop' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop' style='min-width:95pt'>17.12.5.2</a> Class <span class='texttt'>coroutine_<span class='shy'></span>handle&lt;noop_<span class='shy'></span>coroutine_<span class='shy'></span>promise&gt;</span> <a class='abbr_ref' href='coroutine.handle.noop'>[coroutine.handle.noop]</a></h4><div id='coroutine.handle.noop.general' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.general' style='min-width:110pt'>17.12.5.2.1</a> General <a class='abbr_ref' href='coroutine.handle.noop.general'>[coroutine.handle.noop.general]</a></h4><div class='texpara'><span id='lib:coroutine_handle<noop_coroutine_promise>'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><span class='codeblock'><span class='keyword'>namespace</span> std <span class='curlybracket'>{</span>
  <span class='keyword'>template</span><span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span>
  <span class='keyword'>struct</span> coroutine_handle<span class='anglebracket'>&lt;</span>noop_coroutine_promise<span class='anglebracket'>&gt;</span>
  <span class='curlybracket'>{</span>
    <span class='comment'>// <a href='#coroutine.handle.noop.conv' title='17.12.5.2.2&emsp;Conversion'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>noop.<span class='shy'></span>conv]</a>, conversion</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>operator</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.noop.observers' title='17.12.5.2.3&emsp;Observers'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>noop.<span class='shy'></span>observers]</a>, observers</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>explicit</span> <span class='keyword'>operator</span> <span class='keyword'>bool</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>constexpr</span> <span class='keyword'>bool</span> done<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.noop.resumption' title='17.12.5.2.4&emsp;Resumption'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>noop.<span class='shy'></span>resumption]</a>, resumption</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> <span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.noop.promise' title='17.12.5.2.5&emsp;Promise access'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>noop.<span class='shy'></span>promise]</a>, promise access</span>
    <span class='keyword added'>constexpr</span> noop_coroutine_promise<span class='operator'>&amp;</span> promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;

    <span class='comment'>// <a href='#coroutine.handle.noop.address' title='17.12.5.2.6&emsp;Address'>[coroutine.<span class='shy'></span>handle.<span class='shy'></span>noop.<span class='shy'></span>address]</a>, address</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span><span class='operator'>*</span> address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
  <span class='keyword'>private</span><span class='operator'>:</span>
    <span class='keyword added'>constexpr</span> coroutine_handle<span class='parenthesis'>(</span><i ><span class='texttt'>unspecified</span></i><span class='parenthesis'>)</span>;
    <span class='keyword'>void</span><span class='operator'>*</span> ptr;  <span class='comment'>// <i >exposition only</i></span>
  <span class='curlybracket'>}</span>;
<span class='curlybracket'>}</span>
</span></span></div></div><div id='coroutine.handle.noop.conv' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.conv' style='min-width:110pt'>17.12.5.2.2</a> Conversion <a class='abbr_ref' href='coroutine.handle.noop.conv'>[coroutine.handle.noop.conv]</a></h4><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,operator_coroutine_handle<>'><div id='lib:operator_coroutine_handle<>,coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator_coroutine_handle%3c%3e,coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>operator</span> coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.noop.conv-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.conv-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5603'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.conv-1.sentence-1' class='sentence'><i >Effects</i>: Equivalent to: <span class='texttt'><span class='keyword'>return</span> coroutine_<span class='shy'></span>handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='operator'>&#x200b;::&#x200b;</span>from_<span class='shy'></span>address<span class='parenthesis'>(</span>address<span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>)</span>;</span></div></div></div></div></div><div id='coroutine.handle.noop.observers' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.observers' style='min-width:110pt'>17.12.5.2.3</a> Observers <a class='abbr_ref' href='coroutine.handle.noop.observers'>[coroutine.handle.noop.observers]</a></h4><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,operator_bool'><div id='lib:operator_bool,coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator_bool,coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>explicit</span> <span class='keyword'>operator</span> <span class='keyword'>bool</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.noop.observers-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.observers-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5616'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.observers-1.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'><span class='literal'>true</span></span><a class='hidden_link' href='#coroutine.handle.noop.observers-1.sentence-1'>.</a></div></div></div></div><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,done'><div id='lib:done,coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:done,coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>bool</span> done<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.noop.observers-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.observers-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5627'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.observers-2.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'><span class='literal'>false</span></span><a class='hidden_link' href='#coroutine.handle.noop.observers-2.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.noop.resumption' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.resumption' style='min-width:110pt'>17.12.5.2.4</a> Resumption <a class='abbr_ref' href='coroutine.handle.noop.resumption'>[coroutine.handle.noop.resumption]</a></h4><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,destroy'><div id='lib:destroy,coroutine_handle<noop_coroutine_promise>'><div id='lib:coroutine_handle<noop_coroutine_promise>,resume'><div id='lib:resume,coroutine_handle<noop_coroutine_promise>'><div id='lib:coroutine_handle<noop_coroutine_promise>,operator()'><div id='lib:operator(),coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:operator(),coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>void</span> <span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
<span class='keyword'>constexpr</span> <span class='keyword'>void</span> resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
<span class='keyword'>constexpr</span> <span class='keyword'>void</span> destroy<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div></div></div></div></div><div class='para' id='coroutine.handle.noop.resumption-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.resumption-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5644'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.resumption-1.sentence-1' class='sentence'><i >Effects</i>: None<a class='hidden_link' href='#coroutine.handle.noop.resumption-1.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.noop.resumption-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.resumption-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5648'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.resumption-2.sentence-1' class='sentence'><i >Remarks</i>: If <span class='texttt'>noop_<span class='shy'></span>coroutine_<span class='shy'></span>handle</span> is converted to <span class='texttt'>coroutine_<span class='shy'></span>handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span></span>,
calls to <span class='texttt'><span class='keyword'>operator</span><span class='parenthesis'>(</span><span class='parenthesis'>)</span></span>, <span class='texttt'>resume</span> and <span class='texttt'>destroy</span> on that handle
will also have no observable effects<a class='hidden_link' href='#coroutine.handle.noop.resumption-2.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.noop.promise' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.promise' style='min-width:110pt'>17.12.5.2.5</a> Promise access <a class='abbr_ref' href='coroutine.handle.noop.promise'>[coroutine.handle.noop.promise]</a></h4><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,promise'><div id='lib:promise,coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:promise,coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> noop_coroutine_promise<span class='operator'>&amp;</span> promise<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.noop.promise-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.promise-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5663'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.promise-1.sentence-1' class='sentence'><i >Returns</i>: A reference to the promise object associated with this
coroutine handle<a class='hidden_link' href='#coroutine.handle.noop.promise-1.sentence-1'>.</a></div></div></div></div></div><div id='coroutine.handle.noop.address' class='section'><h4 ><a class='secnum' href='#coroutine.handle.noop.address' style='min-width:110pt'>17.12.5.2.6</a> Address <a class='abbr_ref' href='coroutine.handle.noop.address'>[coroutine.handle.noop.address]</a></h4><div class='texpara'><div id='lib:coroutine_handle<noop_coroutine_promise>,address'><div id='lib:address,coroutine_handle<noop_coroutine_promise>'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:address,coroutine_handle%3cnoop_coroutine_promise%3e'>🔗</a></div><code class='itemdeclcode'><span class='keyword'>constexpr</span> <span class='keyword'>void</span><span class='operator'>*</span> address<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span>;
</code></div></div></div></div><div class='para' id='coroutine.handle.noop.address-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.address-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5677'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.address-1.sentence-1' class='sentence'><i >Returns</i>: <span class='texttt'>ptr</span><a class='hidden_link' href='#coroutine.handle.noop.address-1.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.handle.noop.address-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.handle.noop.address-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5681'>#</a></div><div class='texpara'><div id='coroutine.handle.noop.address-2.sentence-1' class='sentence'><i >Remarks</i>: A <span class='texttt'>noop_<span class='shy'></span>coroutine_<span class='shy'></span>handle</span>'s <span class='texttt'>ptr</span> is always a
non-null pointer value<a class='hidden_link' href='#coroutine.handle.noop.address-2.sentence-1'>.</a></div></div></div></div></div></div><div id='coroutine.noop.coroutine' class='section'><h4 ><a class='secnum' href='#coroutine.noop.coroutine' style='min-width:95pt'>17.12.5.3</a> Function <span class='texttt'>noop_<span class='shy'></span>coroutine</span> <a class='abbr_ref' href='coroutine.noop.coroutine'>[coroutine.noop.coroutine]</a></h4><div class='texpara'><div id='lib:noop_coroutine'><div class='itemdecl'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:noop_coroutine'>🔗</a></div><code class='itemdeclcode'><span class='keyword added'>constexpr</span> noop_coroutine_handle noop_coroutine<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>noexcept</span>;
</code></div></div></div><div class='para' id='coroutine.noop.coroutine-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.noop.coroutine-1'>1</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5695'>#</a></div><div class='texpara'><div id='coroutine.noop.coroutine-1.sentence-1' class='sentence'><i >Returns</i>: A handle to a coroutine that has no observable effects
when resumed or destroyed<a class='hidden_link' href='#coroutine.noop.coroutine-1.sentence-1'>.</a></div></div></div></div><div class='para' id='coroutine.noop.coroutine-2'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.noop.coroutine-2'>2</a></div><div class='itemdescr'><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5700'>#</a></div><div class='texpara'><div id='coroutine.noop.coroutine-2.sentence-1' class='sentence'><i >Remarks</i>: A handle returned from <span class='texttt'>noop_<span class='shy'></span>coroutine</span> may or may not
compare equal to a handle returned from another invocation
of <span class='texttt'>noop_<span class='shy'></span>coroutine</span><a class='hidden_link' href='#coroutine.noop.coroutine-2.sentence-1'>.</a></div></div></div></div></div></div><div id='coroutine.trivial.awaitables' class='section'><h3 ><a class='secnum' href='#coroutine.trivial.awaitables' style='min-width:80pt'>17.12.6</a> Trivial awaitables <a class='abbr_ref' href='coroutine.trivial.awaitables'>[coroutine.trivial.awaitables]</a></h3><div class='texpara'><span id='lib:suspend_always,await_resume'><span id='lib:await_resume,suspend_always'><span id='lib:suspend_always,await_suspend'><span id='lib:await_suspend,suspend_always'><span id='lib:suspend_always,await_ready'><span id='lib:await_ready,suspend_always'><span id='lib:suspend_always'><span id='lib:suspend_never,await_resume'><span id='lib:await_resume,suspend_never'><span id='lib:suspend_never,await_suspend'><span id='lib:await_suspend,suspend_never'><span id='lib:suspend_never,await_ready'><span id='lib:await_ready,suspend_never'><span id='lib:suspend_never'><div class='marginalizedparent'><a class='itemDeclLink' href='#lib:suspend_never'>🔗</a></div><span class='codeblock'><span class='keyword'>namespace</span> std <span class='curlybracket'>{</span>
  <span class='keyword'>struct</span> suspend_never <span class='curlybracket'>{</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>bool</span> await_ready<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> <span class='literal'>true</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> await_suspend<span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> await_resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
  <span class='curlybracket'>}</span>;
  <span class='keyword'>struct</span> suspend_always <span class='curlybracket'>{</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>bool</span> await_ready<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span> <span class='keyword'>return</span> <span class='literal'>false</span>; <span class='curlybracket'>}</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> await_suspend<span class='parenthesis'>(</span>coroutine_handle<span class='anglebracket'>&lt;</span><span class='anglebracket'>&gt;</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
    <span class='keyword'>constexpr</span> <span class='keyword'>void</span> await_resume<span class='parenthesis'>(</span><span class='parenthesis'>)</span> <span class='keyword'>const</span> <span class='keyword'>noexcept</span> <span class='curlybracket'>{</span><span class='curlybracket'>}</span>
  <span class='curlybracket'>}</span>;
<span class='curlybracket'>}</span>
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></div><div class='para nonNormativeOnly' id='coroutine.trivial.awaitables-1'><div class='marginalizedparent'><a class='marginalized' href='#coroutine.trivial.awaitables-1'>1</a></div><div class='sourceLinkParent'><a class='sourceLink' href='http://github.com/Eelis/draft/tree/dbf90c5d424d121918e0ad72c62d97ef0059d67e/source/support.tex#L5732'>#</a></div><div class='texpara'><div id='coroutine.trivial.awaitables-note-1' class='note'><div class='texpara'>[<i>Note&nbsp;<a href='#coroutine.trivial.awaitables-note-1'>1</a></i>:&ensp;<div id='coroutine.trivial.awaitables-1.sentence-1' class='sentence'>The types <span class='texttt'>suspend_<span class='shy'></span>never</span> and <span class='texttt'>suspend_<span class='shy'></span>always</span> can be used
to indicate that an <a href='expr.await#nt:await-expression' title='7.6.2.4&emsp;Await&emsp;[expr.await]'><span id='ntref:await-expression'><span class='textsf'><i >await-expression</i></span></span></a> either never
suspends or always suspends, and in either case does not produce a value<a class='hidden_link' href='#coroutine.trivial.awaitables-1.sentence-1'>.</a></div> —&nbsp;<i>end note</i>]</div></div></div></div></div>
</div>	<h3 id='feature-test-macros'><a href='#feature-test-macros'>Feature test macros</a></h3>
<div class="wording"><h2><a href="http://eel.is/c++draft/cpp.predefined">15.11 Predefined macro names [cpp.predefined]</a></h2><div class="description"><span class="added"><code>__cpp_constexpr_coroutines 2026??</code></span></div></div><div class="wording"><h2><a href="http://eel.is/c++draft/cpp.predefined">17.3.2 Header &lt;version&gt; synopsis [version.syn]</a></h2><div class="description"><span class="added"><code>#define __cpp_lib_constexpr_coroutines 2026?? // also in coroutine</code></span></code></span></div></div></div></div></article>
</div><script>
	hljs.addPlugin(mergeHTMLPlugin);
	hljs.highlightAll();
</script>
</body>
</html>
