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

/* color variables included separately for reliability */

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

	html {
	}

	body {
		counter-reset: example figure issue;

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

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

		color: black;
		color: var(--text);
		background: white top left fixed no-repeat;
		background: var(--bg) top left fixed no-repeat;
		background-size: 25px auto;
	}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	h1, h2, h3 {
		color: #005A9C;
		color: var(--heading-text);
	}

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

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

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

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

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

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

	p {
		margin: 1em 0;
	}

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

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

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

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

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

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

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	 padding: .5em;
	 border: thin solid #ddd;
	 border: thin solid var(--algo-border);
	 border-radius: .5em;
	 margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	 margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	 margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	margin-left: -2em;
	}
	dl.switch {
	padding-left: 2em;
	}
	dl.switch > dt {
	text-indent: -1.5em;
	margin-top: 1em;
	}
	dl.switch > dt + dt {
	margin-top: 0;
	}
	dl.switch > dt::before {
	content: '\21AA';
	padding: 0 0.5em 0 0;
	display: inline-block;
	width: 1em;
	text-align: right;
	line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: inherit;
	}
	dfn var {
		font-style: normal;
	}

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

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

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

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

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

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

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

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

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		hyphens: none;
		text-transform: none;
		text-align: left;
		text-align: start;
		font-variant: normal;
		orphans: 3;
		widows: 3;
		page-break-before: avoid;
	}
	pre code,
	code code {
		font-size: 100%;
	}

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

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

	/* Do something nice. */

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

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

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		color: var(--a-normal-text);
		text-decoration: underline #707070;
		text-decoration: underline var(--a-normal-underline);
		text-decoration-skip-ink: none;
	}
	a:visited {
		color: #034575;
		color: var(--a-visited-text);
		text-decoration-color: #bbb;
		text-decoration-color: var(--a-visited-underline);
	}

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

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

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

	img {
		border-style: none;
	}

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

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

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

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

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

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

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


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

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

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

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

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

	.issue {
		border-color: #e05252;
		border-color: var(--issue-border);
		background: #fbe9e9;
		background: var(--issue-bg);
		color: black;
		color: var(--issue-text);
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		color: #831616;
		color: var(--issueheading-text);
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	  or use class="marker" to mark up the issue number in source. */

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

	.example {
		border-color: #e0cb52;
		border-color: var(--example-border);
		background: #fcfaee;
		background: var(--example-bg);
		color: black;
		color: var(--example-text);
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		color: #574b0f;
		color: var(--exampleheading-text);
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	  or use class="marker" to mark up the example number in source. */

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

	.note {
		border-color: #52e052;
		border-color: var(--note-border);
		background: #e9fbe9;
		background: var(--note-bg);
		color: black;
		color: var(--note-text);
		overflow: auto;
	}

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

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

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

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

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

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

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

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

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

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

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: hsla(40,100%,50%,0.95);
		background: var(--warning-bg);
		color: black;
		color: var(--warning-text);
		padding: .75em 1em;
		border: red;
		border: var(--warning-border);
		border-style: solid none;
		box-shadow: 0 2px 8px black;
		text-align: center;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


/*
Alternate table alignment rules

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

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

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

Possible extra rowspan handling

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

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

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


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

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding: 0.1rem 1px 0;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Switch to using border-bottom for underlines */
		text-decoration: none;
		border-bottom: 1px solid;
		/* Reverse color scheme */
		color: black;
		color: var(--toclink-text);
		border-color: #3980b5;
		border-color: var(--toclink-underline);
	}
	.toc a:visited {
		color: black;
		color: var(--toclink-visited-text);
		border-color: #054572;
		border-color: var(--toclink-visited-underline);
	}
	.toc a:focus,
	.toc a:hover {
		background: rgba(75%, 75%, 75%, .25);
		background: var(--a-hover-bg);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

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

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

	/* @supports not (display:grid) { */
		.toc > li			{ margin: 1.5rem 0;	}
		.toc > li li		 { margin: 0.3rem 0;	}
		.toc > li li li	  { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}
		.toc > li li li li .secno { font-size: 85%; }
		.toc > li li li li li .secno { font-size: 100%; }

		.toc li {
			clear: both;
		}

		:not(li) > .toc			 { margin-left:  5rem; }
		.toc .secno				 { margin-left: -5rem; }
		.toc > li li li .secno	  { margin-left: -7rem; }
		.toc > li li li li .secno	{ margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc			 { margin-left:  4rem; }
			.toc .secno				 { margin-left: -4rem; }
			.toc > li li li			 { margin-left:  1rem; }
			.toc > li li li .secno	  { margin-left: -5rem; }
			.toc > li li li li .secno	{ margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
		/* Loosen it on wide screens */
		@media screen and (min-width: 78em) {
			body:not(.toc-inline) :not(li) > .toc			 { margin-left:  4rem; }
			body:not(.toc-inline) .toc .secno				 { margin-left: -4rem; }
			body:not(.toc-inline) .toc > li li li			 { margin-left:  1rem; }
			body:not(.toc-inline) .toc > li li li .secno	  { margin-left: -5rem; }
			body:not(.toc-inline) .toc > li li li li .secno	{ margin-left: -6rem; }
			body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			  comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom: 3px solid #054572;
			border-bottom: 3px solid var(--toclink-underline);
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


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

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

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

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

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

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		color: black;
		color: var(--indextable-hover-text);
		background: #f7f8f9;
		background: var(--indextable-hover-bg);
	}

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

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

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

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

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

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

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

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

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

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

.outdated-warning span {
	display: block;
}

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

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

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

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

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



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

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good item positioning:
		  "content column" is 50ems wide at max; less on smaller screens.
		  Extra space (after ToC + content) is empty on the right.

		  1. When item < content column, centers item in column.
		  2. When content < item < available, left-aligns.
		  3. When item > available, fills available + scroll bar.
		*/
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

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

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			* http://lea.verou.me/2012/04/background-attachment-local/
			*
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
						top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
						top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
						white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style>
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }

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

:root {
	/* Default (light) theme */
	--del-text-color: rgb(255, 25, 25);
	--del-text-decoration-color: rgba(180, 6, 6, 0.5);
	--del-text-background-color: rgba(255, 175, 175, 0.5);
	--ins-text-color: rgb(10, 180, 35);
	--ins-text-decoration-color: rgba(10, 180, 35, 0.5);
	--ins-text-background-color: rgba(175, 250, 190, 0.5);
	--diff-ins-text-color: rgb(0, 238, 255);
	--diff-ins-text-decoration-color: rgba(99, 0, 129, 0.5);
	--diff-ins-text-background-color: rgba(175, 222, 250, 0.5);
	--diff-del-text-color: rgb(225, 148, 255);
	--diff-del-text-decoration-color: rgba(99, 0, 129, 0.5);
	--diff-del-text-background-color: rgba(244, 175, 250, 0.5);
}

/* dark theme */
@media (prefers-color-scheme: dark) {
	:root {
		--del-text-color: rgb(255, 52, 52);
		--del-text-decoration-color: rgba(82, 25, 25, 0.5);
		--del-text-background-color: rgba(82, 25, 25, 0.5);
		--ins-text-color: rgb(140, 255, 140);
		--ins-text-decoration-color: rgba(140, 255, 140, 0.5);
		--ins-text-background-color: rgba(25, 82, 25, 0.5);
		--diff-ins-text-color: rgb(91, 250, 255);
		--diff-ins-text-decoration-color: rgba(91, 250, 255, 0.5);
		--diff-ins-text-background-color: rgba(0, 56, 94, 0.5);
		--diff-del-text-color: rgb(244, 175, 250);
		--diff-del-text-decoration-color: rgba(244, 175, 250, 0.5);
		--diff-del-text-background-color: rgba(152, 0, 199, 0.5);
	}
}

@media print {
	.pagebreak { break-after: always }
}

.tg  {
	border-collapse: collapse;
	border-spacing:0;
}

.tg td{
	padding:10px 10px;
	border-style: solid;
	border-width:1px;
	overflow: hidden;
	word-break: normal;
	border-color: var(--table-border-color, inherit);
}
.tg th{
	font-weight: normal;
	padding: 10px 10px;
	border-style: solid;
	border-width: 1px;
	overflow: hidden;
	word-break: normal;
	border-color: black;
}
.tg .tg-c3ow { 
	border-color: inherit;
	text-align: center;
	vertical-align: top
}

.ins, ins, ins p, ins div, span.ins, span.ins * {
	background-color: var(--ins-text-background-color);
	background: var(--ins-text-background-color);
	color: var(--ins-text-color);
	text-decoration: underline;
	text-decoration-color: var(--ins-text-decoration-color);
}

.diff-ins, diff-ins, diff-ins p, diff-ins div, span.diff-ins, span.diff-ins * {
	background-color: var(--diff-ins-text-background-color);
	background: var(--diff-ins-text-background-color);
	color: var(--diff-ins-text-color);
	text-decoration: underline double;
	text-decoration-color: var(--diff-ins-text-decoration-color);
}

.del, del, del p, del div, span.del, span.del * {
	background-color: var(--del-text-background-color);
	background: var(--del-text-background-color);
	color: var(--del-text-color);
	text-decoration: line-through;
	text-decoration-color: var(--del-text-decoration-color);
}

.diff-del, diff-del, diff-del p, diff-del div, span.diff-del, span.diff-del * {
	background-color: var(--diff-del-text-background-color);
	background: var(--diff-del-text-background-color);
	color: var(--diff-del-text-color);
	text-decoration: line-through double;
	text-decoration-color: var(--diff-del-text-decoration-color);
}

code.c-kw {
	font-weight: bold;
}

math, span.math {
	font-family: serif;
	font-style: italic;
}

ul {
	list-style-type: "— ";
}

.wording-clause {
	counter-reset: wording-paragraph;
}

.wording-clause-header {
	font-size: 115%;
	display: block;
	padding-bottom: 1em;
	clear: both;
}

.wording-clause-number {
	font-weight: bold;
}

.wording-clause-title {
	font-weight: bold;
	margin: 2em;
}

.wording-clause-stable-tag {
	float: right;
}

.wording-clause-section-title {
	font-size: 105%;
	font-weight: bold;
}

.clause-stable-tag {
	float: right;
}

.footnote-ref {
	font-size: 75%;
	vertical-align: super;
}

.footnote {
	font-size: 75%;
	vertical-align: bottom;
}

div.wording-section {
	counter-reset: wording-paragraph;
}

div.wording-numbered, div.wording-newnumbered {
	margin-left: 2.5em;
	margin-top: 1em;
	margin-bottom: 1em;
}

div.wording-numbered:before, div.wording-newnumbered:before {
	position: absolute;
	margin-left: -2.5em;
	display: block;
}

div.wording-numbered:before {
	content: counter(wording-paragraph);
	counter-increment: wording-paragraph;
	font-size: smaller;
}

div.wording-newnumbered:before {
	content: counter(wording-paragraph)"✨";
	counter-increment: wording-paragraph;
	font-size: smaller;
}

div.wording-numbered-list ul, div.wording-newnumbered ul {
	counter-reset: wording-list-item;
}

div.wording-numbered-list li, div.wording-newnumbered li {
	margin-left: 4em;
}

div.wording-numbered-list li:before, div.wording-newnumbered li:before {
	position: absolute;
	margin-left: -4em;
	display: block;
}

div.wording-numbered-list li:before {
	font-size: smaller;
	content: "(" counter(wording-paragraph) "." counter(wording-list-item) ")";
	counter-increment: wording-list-item;
}

div.wording-newnumbered-list li:before {
	content: "(✨" counter(wording-paragraph) "." counter(wording-list-item) ")";
	counter-increment: wording-list-item;
}

div.wording-numbered-0 {
	counter-reset: wording-paragraph -1;
}

div.wording-numbered-1 {
	counter-reset: wording-paragraph 0;
}

div.wording-numbered-2 {
	counter-reset: wording-paragraph 1;
}

div.wording-numbered-3 {
	counter-reset: wording-paragraph 2;
}

div.wording-numbered-4 {
	counter-reset: wording-paragraph 3;
}

div.wording-numbered-5 {
	counter-reset: wording-paragraph 4;
}

div.wording-numbered-6 {
	counter-reset: wording-paragraph 5;
}

div.wording-numbered-7 {
	counter-reset: wording-paragraph 6;
}

div.wording-numbered-8 {
	counter-reset: wording-paragraph 7;
}

div.wording-numbered-9 {
	counter-reset: wording-paragraph 8;
}

div.wording-numbered-10 {
	counter-reset: wording-paragraph 9;
}

div.wording-numbered-11 {
	counter-reset: wording-paragraph 10;
}

div.wording-numbered-12 {
	counter-reset: wording-paragraph 11;
}

div.wording-numbered-13 {
	counter-reset: wording-paragraph 12;
}

div.wording-numbered-14 {
	counter-reset: wording-paragraph 13;
}

div.wording-numbered-15 {
	counter-reset: wording-paragraph 14;
}

div.wording-numbered-16 {
	counter-reset: wording-paragraph 15;
}

div.wording-numbered-17 {
	counter-reset: wording-paragraph 16;
}

div.wording-numbered-18 {
	counter-reset: wording-paragraph 17;
}

div.wording-numbered-19 {
	counter-reset: wording-paragraph 18;
}

div.wording-numbered-20 {
	counter-reset: wording-paragraph 19;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
	:root {
		--bg-color: rgba(0, 0, 0, 0);
	}

	ins { background: rgba(0, 20, 0); color: rgba(115, 255, 110); }
	del { background: rgba(20, 0, 0); color: rgb(255, 124, 124); text-decoration: line-through; }
	recent-ins { background: rgba(0, 20, 0); color: rgba(80, 80, 255); }
	recent-del { background: rgba(20, 0, 0); color: rgb(255, 156, 56); text-decoration: line-through; }
	blockquote .highlight:not(.idl) { padding: 0.5em }
	blockquote ins .highlight:not(.idl) { background: rgba( 0, 20, 0); }
	blockquote del .highlight:not(.idl) { background: rgba(20,  0, 0); }
	blockquote code.highlight:not(.idl) { background: inherit; padding: initial; }

	c-[a] { color: #e783b4 } /* Keyword.Declaration */
	c-[b] { color: #e783b4 } /* Keyword.Type */
	c-[c] { color: #6ad4cc } /* Comment */
	c-[d] { color: #6ad4cc } /* Comment.Multiline */
	c-[e] { color: #92cbf5 } /* Name.Attribute */
	c-[f] { color: #b58900 } /* Name.Tag */
	c-[g] { color: #cb4b16 } /* Name.Variable */
	c-[k] { color: #e783b4 } /* Keyword */
	c-[l] { color: #a2b1b6 } /* Literal */
	c-[m] { color: #a2b1b6 } /* Literal.Number */
	c-[n] { color: #92cbf5 } /* Name */
	c-[o] { color: #a2b1b6 } /* Operator */
	c-[p] { color: #a2b1b6 } /* Punctuation */
	c-[s] { color: #a0a3e5 } /* Literal.String */
	c-[t] { color: #a0a3e5 } /* Literal.String.Single */
	c-[u] { color: #a0a3e5 } /* Literal.String.Double */
	c-[ch] { color: #6ad4cc } /* Comment.Hashbang */
	c-[cp] { color: #6ad4cc } /* Comment.Preproc */
	c-[cpf] { color: #6ad4cc } /* Comment.PreprocFile */
	c-[c1] { color: #6ad4cc } /* Comment.Single */
	c-[cs] { color: #6ad4cc } /* Comment.Special */
	c-[kc] { color: #e783b4 } /* Keyword.Constant */
	c-[kn] { color: #e783b4 } /* Keyword.Namespace */
	c-[kp] { color: #e783b4 } /* Keyword.Pseudo */
	c-[kr] { color: #e783b4 } /* Keyword.Reserved */
	c-[ld] { color: #a2b1b6 } /* Literal.Date */
	c-[nc] { color: #92cbf5 } /* Name.Class */
	c-[no] { color: #92cbf5 } /* Name.Constant */
	c-[nd] { color: #92cbf5 } /* Name.Decorator */
	c-[ni] { color: #92cbf5 } /* Name.Entity */
	c-[ne] { color: #92cbf5 } /* Name.Exception */
	c-[nf] { color: #92cbf5 } /* Name.Function */
	c-[nl] { color: #92cbf5 } /* Name.Label */
	c-[nn] { color: #92cbf5 } /* Name.Namespace */
	c-[py] { color: #92cbf5 } /* Name.Property */
	c-[ow] { color: #a2b1b6 } /* Operator.Word */
	c-[mb] { color: #a2b1b6 } /* Literal.Number.Bin */
	c-[mf] { color: #a2b1b6 } /* Literal.Number.Float */
	c-[mh] { color: #a2b1b6 } /* Literal.Number.Hex */
	c-[mi] { color: #a2b1b6 } /* Literal.Number.Integer */
	c-[mo] { color: #a2b1b6 } /* Literal.Number.Oct */
	c-[sa] { color: #a0a3e5 } /* Literal.String.Affix */
	c-[sb] { color: #a0a3e5 } /* Literal.String.Backtick */
	c-[sc] { color: #a0a3e5 } /* Literal.String.Char */
	c-[dl] { color: #a0a3e5 } /* Literal.String.Delimiter */
	c-[sd] { color: #a0a3e5 } /* Literal.String.Doc */
	c-[se] { color: #a0a3e5 } /* Literal.String.Escape */
	c-[sh] { color: #a0a3e5 } /* Literal.String.Heredoc */
	c-[si] { color: #a0a3e5 } /* Literal.String.Interpol */
	c-[sx] { color: #a0a3e5 } /* Literal.String.Other */
	c-[sr] { color: #a0a3e5 } /* Literal.String.Regex */
	c-[ss] { color: #a0a3e5 } /* Literal.String.Symbol */
	c-[fm] { color: #92cbf5 } /* Name.Function.Magic */
	c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
	c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
	c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
	c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
	c-[il] { color: #a2b1b6 } /* Literal.Number.Integer.Long */

	blockquote c-[b] { color: #e783b4 } /* Keyword.Type */
	blockquote c-[a] { color: #e783b4 } /* Keyword.Declaration */
	blockquote c-[c] { color: #6ad4cc } /* Comment */
	blockquote c-[d] { color: #6ad4cc } /* Comment.Multiline */
	blockquote c-[e] { color: #92cbf5 } /* Name.Attribute */
	blockquote c-[f] { color: #b58900 } /* Name.Tag */
	blockquote c-[g] { color: #cb4b16 } /* Name.Variable */
	blockquote c-[k] { color: #e783b4 } /* Keyword */
	blockquote c-[l] { color: #a2b1b6 } /* Literal */
	blockquote c-[m] { color: #a2b1b6 } /* Literal.Number */
	blockquote c-[n] { color: #92cbf5 } /* Name */
	blockquote c-[o] { color: #a2b1b6 } /* Operator */
	blockquote c-[p] { color: #a2b1b6 } /* Punctuation */
	blockquote c-[s] { color: #a0a3e5 } /* Literal.String */
	blockquote c-[t] { color: #a0a3e5 } /* Literal.String.Single */
	blockquote c-[u] { color: #a0a3e5 } /* Literal.String.Double */
	blockquote c-[ch] { color: #6ad4cc } /* Comment.Hashbang */
	blockquote c-[cp] { color: #6ad4cc } /* Comment.Preproc */
	blockquote c-[cpf] { color: #6ad4cc } /* Comment.PreprocFile */
	blockquote c-[c1] { color: #6ad4cc } /* Comment.Single */
	blockquote c-[cs] { color: #6ad4cc } /* Comment.Special */
	blockquote c-[kc] { color: #e783b4 } /* Keyword.Constant */
	blockquote c-[kn] { color: #e783b4 } /* Keyword.Namespace */
	blockquote c-[kp] { color: #e783b4 } /* Keyword.Pseudo */
	blockquote c-[kr] { color: #e783b4 } /* Keyword.Reserved */
	blockquote c-[ld] { color: #a2b1b6 } /* Literal.Date */
	blockquote c-[nc] { color: #92cbf5 } /* Name.Class */
	blockquote c-[no] { color: #92cbf5 } /* Name.Constant */
	blockquote c-[nd] { color: #92cbf5 } /* Name.Decorator */
	blockquote c-[ni] { color: #92cbf5 } /* Name.Entity */
	blockquote c-[ne] { color: #92cbf5 } /* Name.Exception */
	blockquote c-[nf] { color: #92cbf5 } /* Name.Function */
	blockquote c-[nl] { color: #92cbf5 } /* Name.Label */
	blockquote c-[nn] { color: #92cbf5 } /* Name.Namespace */
	blockquote c-[py] { color: #92cbf5 } /* Name.Property */
	blockquote c-[ow] { color: #a2b1b6 } /* Operator.Word */
	blockquote c-[mb] { color: #a2b1b6 } /* Literal.Number.Bin */
	blockquote c-[mf] { color: #a2b1b6 } /* Literal.Number.Float */
	blockquote c-[mh] { color: #a2b1b6 } /* Literal.Number.Hex */
	blockquote c-[mi] { color: #a2b1b6 } /* Literal.Number.Integer */
	blockquote c-[mo] { color: #a2b1b6 } /* Literal.Number.Oct */
	blockquote c-[sa] { color: #a0a3e5 } /* Literal.String.Affix */
	blockquote c-[sb] { color: #a0a3e5 } /* Literal.String.Backtick */
	blockquote c-[sc] { color: #a0a3e5 } /* Literal.String.Char */
	blockquote c-[dl] { color: #a0a3e5 } /* Literal.String.Delimiter */
	blockquote c-[sd] { color: #a0a3e5 } /* Literal.String.Doc */
	blockquote c-[se] { color: #a0a3e5 } /* Literal.String.Escape */
	blockquote c-[sh] { color: #a0a3e5 } /* Literal.String.Heredoc */
	blockquote c-[si] { color: #a0a3e5 } /* Literal.String.Interpol */
	blockquote c-[sx] { color: #a0a3e5 } /* Literal.String.Other */
	blockquote c-[sr] { color: #a0a3e5 } /* Literal.String.Regex */
	blockquote c-[ss] { color: #a0a3e5 } /* Literal.String.Symbol */
	blockquote c-[fm] { color: #92cbf5 } /* Name.Function.Magic */
	blockquote c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
	blockquote c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
	blockquote c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
	blockquote c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
	blockquote c-[il] { color: #a2b1b6 } /* Literal.Number.Integer.Long */
}

@media (prefers-color-scheme: light) {
	:root {
		--bg-color: rgba(255, 255, 255, 0);
	}
	ins { background: rgba(200, 255, 200); color: rgba(0, 20, 0); }
	del { background: rgba(255, 200, 200); color: rgb(20, 0, 0); text-decoration: line-through; }
	blockquote .highlight:not(.idl) { padding: 0.5em }
	blockquote ins .highlight:not(.idl) { background: rgba(200, 255, 200); }
	blockquote del .highlight:not(.idl) { background: rgba(255, 200, 200); }
	blockquote code.highlight:not(.idl) { background: inherit; padding: initial; }
}
</style>
<style>/* style-autolinks */

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

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

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

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

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

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

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

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

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

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

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

    --heading-text: #005a9c;

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

    --algo-border: #def;

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

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

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

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

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

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

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

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

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

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

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

    --datacell-border: silver;

    --indexinfo-text: #707070;

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

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

    --editedrec-bg: darkorange;
}</style>
<style>/* style-counters */

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

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

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

a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* style-md-lists */

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

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

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

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

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

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

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

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

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

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

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

        --heading-text: #8af;

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

        --algo-border: #456;

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

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

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

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

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

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

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

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

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

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

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

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

        --datacell-border: silver;

        --indexinfo-text: #aaa;

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

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

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

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

    c-[a] { color: #d33682 } /* Keyword.Declaration */
    c-[b] { color: #d33682 } /* Keyword.Type */
    c-[c] { color: #2aa198 } /* Comment */
    c-[d] { color: #2aa198 } /* Comment.Multiline */
    c-[e] { color: #268bd2 } /* Name.Attribute */
    c-[f] { color: #b58900 } /* Name.Tag */
    c-[g] { color: #cb4b16 } /* Name.Variable */
    c-[k] { color: #d33682 } /* Keyword */
    c-[l] { color: #657b83 } /* Literal */
    c-[m] { color: #657b83 } /* Literal.Number */
    c-[n] { color: #268bd2 } /* Name */
    c-[o] { color: #657b83 } /* Operator */
    c-[p] { color: #657b83 } /* Punctuation */
    c-[s] { color: #6c71c4 } /* Literal.String */
    c-[t] { color: #6c71c4 } /* Literal.String.Single */
    c-[u] { color: #6c71c4 } /* Literal.String.Double */
    c-[ch] { color: #2aa198 } /* Comment.Hashbang */
    c-[cp] { color: #2aa198 } /* Comment.Preproc */
    c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
    c-[c1] { color: #2aa198 } /* Comment.Single */
    c-[cs] { color: #2aa198 } /* Comment.Special */
    c-[kc] { color: #d33682 } /* Keyword.Constant */
    c-[kn] { color: #d33682 } /* Keyword.Namespace */
    c-[kp] { color: #d33682 } /* Keyword.Pseudo */
    c-[kr] { color: #d33682 } /* Keyword.Reserved */
    c-[ld] { color: #657b83 } /* Literal.Date */
    c-[nc] { color: #268bd2 } /* Name.Class */
    c-[no] { color: #268bd2 } /* Name.Constant */
    c-[nd] { color: #268bd2 } /* Name.Decorator */
    c-[ni] { color: #268bd2 } /* Name.Entity */
    c-[ne] { color: #268bd2 } /* Name.Exception */
    c-[nf] { color: #268bd2 } /* Name.Function */
    c-[nl] { color: #268bd2 } /* Name.Label */
    c-[nn] { color: #268bd2 } /* Name.Namespace */
    c-[py] { color: #268bd2 } /* Name.Property */
    c-[ow] { color: #657b83 } /* Operator.Word */
    c-[mb] { color: #657b83 } /* Literal.Number.Bin */
    c-[mf] { color: #657b83 } /* Literal.Number.Float */
    c-[mh] { color: #657b83 } /* Literal.Number.Hex */
    c-[mi] { color: #657b83 } /* Literal.Number.Integer */
    c-[mo] { color: #657b83 } /* Literal.Number.Oct */
    c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
    c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
    c-[sc] { color: #6c71c4 } /* Literal.String.Char */
    c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
    c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
    c-[se] { color: #6c71c4 } /* Literal.String.Escape */
    c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
    c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
    c-[sx] { color: #6c71c4 } /* Literal.String.Other */
    c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
    c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
    c-[fm] { color: #268bd2 } /* Name.Function.Magic */
    c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
    c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
    c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
    c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
    c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
}
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P1967R6<br><code class="highlight"><c- cp>#embed</c-></code> - a scannable, tooling-friendly binary resource inclusion mechanism</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">Published Proposal, <time class="dt-updated" datetime="2022-05-12">2022-05-12</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt class="editor">Authors:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:phdofthehouse@gmail.com">JeanHeyd Meneide</a>
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:shepherd@soasis.org">Shepherd (Shepherd's Oasis LLC)</a>
     <dt>Latest:
     <dd><a href="https://thephd.dev/_vendor/future_cxx/papers/d1967.html">https://thephd.dev/_vendor/future_cxx/papers/d1967.html</a>
     <dt>Paper Source:
     <dd><a href="https://github.com/ThePhD/future_cxx/blob/main/papers/source/d1967.bs">GitHub ThePhD/future_cxx</a>
     <dt>Implementation:
     <dd><a href="https://github.com/ThePhD/embed">GitHub ThePhD/embed</a>
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Audience:
     <dd>EWG
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>Pulling binary data into a program often involves external tools and build system coordination. Many programs need binary data such as images, encoded text, icons and other data in a specific format. Current state of the art for working with such static data in C includes creating files which contain solely string literals, directly invoking the linker to create data blobs to access through carefully named extern variables, or generating large brace-delimited lists of integers to place into arrays. As binary data has grown larger, these approaches have begun to have drawbacks and issues scaling. From parsing 5 megabytes worth of integer literal expressions into AST nodes to arbitrary string literal length limits in compilers, portably putting binary data in a C program has become an arduous task that taxes build infrastructure and compilation memory and time. This proposal provides a flexible preprocessor directive for making this data available to the user in a straightforward manner.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#changelog"><span class="secno">1</span> <span class="content">Changelog</span></a>
     <ol class="toc">
      <li><a href="#changelog-r6"><span class="secno">1.1</span> <span class="content">Revision 5  - May 12<sup>th</sup>, 2022</span></a>
      <li><a href="#changelog-r5"><span class="secno">1.2</span> <span class="content">Revision 5  - April 12<sup>th</sup>, 2022</span></a>
      <li><a href="#changelog-r4"><span class="secno">1.3</span> <span class="content">Revision 4  - June 15<sup>th</sup>, 2021</span></a>
      <li><a href="#changelog-r3"><span class="secno">1.4</span> <span class="content">Revision 3 - April 15<sup>th</sup>, 2021</span></a>
      <li><a href="#changelog-r2"><span class="secno">1.5</span> <span class="content">Revision 2 - October 25<sup>th</sup>, 2020</span></a>
      <li><a href="#changelog-r1"><span class="secno">1.6</span> <span class="content">Revision 1 - April 10<sup>th</sup>, 2020</span></a>
      <li><a href="#changelog-r0"><span class="secno">1.7</span> <span class="content">Revision 0 - January 5<sup>th</sup>, 2020</span></a>
     </ol>
    <li>
     <a href="#polls"><span class="secno">2</span> <span class="content">Polls &amp; Votes</span></a>
     <ol class="toc">
      <li><a href="#polls-july.2021.c++"><span class="secno">2.1</span> <span class="content">July 2021 Virtual C++ meeting</span></a>
      <li><a href="#polls-september.2020.c++"><span class="secno">2.2</span> <span class="content">September 2020 Virtual C++ EWG Meeting</span></a>
      <li><a href="#polls-april.2020.c"><span class="secno">2.3</span> <span class="content">April 2020 Virtual C Meeting</span></a>
     </ol>
    <li>
     <a href="#intro"><span class="secno">3</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#intro-motivation"><span class="secno">3.1</span> <span class="content">Motivation</span></a>
      <li>
       <a href="#design-efficiency-metrics"><span class="secno">3.2</span> <span class="content">But <em>How</em> Expensive Is This?</span></a>
       <ol class="toc">
        <li><a href="#intro-metrics-speed"><span class="secno">3.2.1</span> <span class="content">Speed</span></a>
        <li><a href="#intro-metrics-space"><span class="secno">3.2.2</span> <span class="content">Memory Size</span></a>
        <li><a href="#intro-metrics-analysis"><span class="secno">3.2.3</span> <span class="content">Analysis</span></a>
       </ol>
     </ol>
    <li>
     <a href="#design"><span class="secno">4</span> <span class="content">Design</span></a>
     <ol class="toc">
      <li>
       <a href="#design-familiar"><span class="secno">4.1</span> <span class="content">Goal: Simplicity and Familiarity</span></a>
       <ol class="toc">
        <li><a href="#design-familiar-paths"><span class="secno">4.1.1</span> <span class="content">Existing Practice - Search Paths</span></a>
        <li><a href="#design-familiar-distributed"><span class="secno">4.1.2</span> <span class="content">Existing Practice - Discoverable and Distributable</span></a>
       </ol>
      <li>
       <a href="#design-syntax"><span class="secno">4.2</span> <span class="content">Syntax</span></a>
       <ol class="toc">
        <li>
         <a href="#design-syntax-parameters"><span class="secno">4.2.1</span> <span class="content">Parameters</span></a>
         <ol class="toc">
          <li><a href="#design-syntax-parameters-limit"><span class="secno">4.2.1.1</span> <span class="content">Limit Parameter</span></a>
          <li><a href="#design-syntax-parameters-non_empty"><span class="secno">4.2.1.2</span> <span class="content">Non-Empty Prefix and Suffix</span></a>
          <li><a href="#design-syntax-parameters-empty"><span class="secno">4.2.1.3</span> <span class="content">Empty Signifier</span></a>
         </ol>
       </ol>
      <li><a href="#design-constexpr"><span class="secno">4.3</span> <span class="content">Constant Expressions</span></a>
      <li><a href="#design-__has_embed"><span class="secno">4.4</span> <span class="content"><code class="highlight"><c- n>__has_embed</c-></code></span></a>
      <li><a href="#design-endianness"><span class="secno">4.5</span> <span class="content">Bit Blasting: Endianness</span></a>
     </ol>
    <li><a href="#implementation"><span class="secno">5</span> <span class="content">Implementation Experience</span></a>
    <li><a href="#alternative"><span class="secno">6</span> <span class="content">Alternative Syntax</span></a>
    <li>
     <a href="#wording"><span class="secno">7</span> <span class="content">Wording</span></a>
     <ol class="toc">
      <li><a href="#wording-intent"><span class="secno">7.1</span> <span class="content">Intent</span></a>
      <li><a href="#wording-feature_test"><span class="secno">7.2</span> <span class="content">Proposed Feature Test Macro</span></a>
      <li>
       <a href="#wording-specification"><span class="secno">7.3</span> <span class="content">Proposed Language Wording</span></a>
       <ol class="toc">
        <li><a href="#wording-specification-cpp.predefined"><span class="secno">7.3.1</span> <span class="content">Append to §14.8.1 Predefined macro names [<strong>cpp.predefined</strong>] an additional entry</span></a>
        <li><a href="#wording-specification-cpp.pre"><span class="secno">7.3.2</span> <span class="content">Add to the <em>control-line</em> production in §15.1 Preamble [<strong>cpp.pre</strong>] a new grammar production, as well as a supporting <em>embed-attribute-list</em> production</span></a>
        <li><a href="#wording-specification-cpp.cond"><span class="secno">7.3.3</span> <span class="content">Modify §15.2 Conditional inclusion [<strong>cpp.cond</strong>] to include a new "has-embed-expression" by modifying paragraph 1 and adding a new paragraph 5 after the current paragraph 4</span></a>
        <li><a href="#wording-specification-cpp.res"><span class="secno">7.3.4</span> <span class="content">Add a new sub-clause §15.4 Resource inclusion [<strong>cpp.res</strong>]</span></a>
        <li><a href="#wording-specification-cpp.res.param"><span class="secno">7.3.5</span> <span class="content">Add a new sub-clause §15.4.1 under Resource Inclusion for Embed parameters [<strong>cpp.res.param</strong>]</span></a>
       </ol>
     </ol>
    <li><a href="#acknowledgements"><span class="secno">8</span> <span class="content">Acknowledgements</span></a>
    <li>
     <a href="#appendix"><span class="secno">9</span> <span class="content">Appendix</span></a>
     <ol class="toc">
      <li>
       <a href="#appendix-existing"><span class="secno">9.1</span> <span class="content">Existing Tools</span></a>
       <ol class="toc">
        <li><a href="#appendix-existing-pre_processing_tools"><span class="secno">9.1.1</span> <span class="content">Pre-Processing Tools</span></a>
        <li><a href="#appendix-existing-python"><span class="secno">9.1.2</span> <span class="content"><code class="highlight"><c- n>python</c-></code></span></a>
        <li><a href="#appendix-existing-ld"><span class="secno">9.1.3</span> <span class="content"><code class="highlight"><c- n>ld</c-></code></span></a>
        <li><a href="#appendix-existing-incbin"><span class="secno">9.1.4</span> <span class="content"><code class="highlight"><c- n>incbin</c-></code></span></a>
        <li><a href="#appendix-existing-external.xxd"><span class="secno">9.1.5</span> <span class="content"><code class="highlight"><c- n>xxd</c-></code>, but done Raw</span></a>
       </ol>
      <li><a href="#appendix-existing-type_flexibility"><span class="secno">9.2</span> <span class="content">Type Flexibility</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <div class="pagebreak"></div>
   <h2 class="heading settled" data-level="1" id="changelog"><span class="secno">1. </span><span class="content">Changelog</span><a class="self-link" href="#changelog"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="changelog-r6"><span class="secno">1.1. </span><span class="content">Revision 5  - May 12<sup>th</sup>, 2022</span><a class="self-link" href="#changelog-r6"></a></h3>
   <ul>
    <li data-md>
     <p>Minor typo and grammar fixes in the wording.</p>
   </ul>
   <h3 class="heading settled" data-level="1.2" id="changelog-r5"><span class="secno">1.2. </span><span class="content">Revision 5  - April 12<sup>th</sup>, 2022</span><a class="self-link" href="#changelog-r5"></a></h3>
   <ul>
    <li data-md>
     <p>Additional syntax changes based on feedback from Joseph Myers, Hubert Tong, Jens Maurer, other implementers, and users.</p>
    <li data-md>
     <p>Minor wording tweaks and typo clean up.</p>
    <li data-md>
     <p>An implementation <a href="https://godbolt.org/z/Kb3ejE7q5">available in Godbolt (since last revision as well and noted below)</a>.</p>
    <li data-md>
     <p>The paper’s source code has been refactored:</p>
     <ul>
      <li data-md>
       <p>Separated WG21 paper from WG14 paper.</p>
      <li data-md>
       <p>Core paper together (rationale, reasoning), included in both C and C++ papers since rationale is identical.</p>
     </ul>
    <li data-md>
     <p>Changed <code class="highlight"><c- n>__has_embed</c-></code> to match feedback from last standards meeting, nominally that an empty resource returns <code class="highlight"><c- mi>2</c-></code> instead of <code class="highlight"><c- mi>1</c-></code> (but both decay to a truthy value during preprocessor conditional inclusion expressions). Modified the wording and the prose in <a href="#design-__has_embed">§ 4.4 __has_embed</a> to match.</p>
    <li data-md>
     <p>The wording for the limit parameter (<a href="#wording-specification-cpp.res.param">§ 7.3.5 Add a new sub-clause §15.4.1 under Resource Inclusion for Embed parameters [cpp.res.param]</a>) adjusted to perform macro expansion, at least once. Exact wording may need help.</p>
   </ul>
   <h3 class="heading settled" data-level="1.3" id="changelog-r4"><span class="secno">1.3. </span><span class="content">Revision 4  - June 15<sup>th</sup>, 2021</span><a class="self-link" href="#changelog-r4"></a></h3>
   <ul>
    <li data-md>
     <p>Vastly improve C++ wording after June 3rd, 2021 discussion.</p>
    <li data-md>
     <p>Change syntax after comments from implementers of scanners / dependency trackers, and comments from implementers that were supported by users.</p>
    <li data-md>
     <p>Add support for "named parameter" implementation extensions.</p>
   </ul>
   <h3 class="heading settled" data-level="1.4" id="changelog-r3"><span class="secno">1.4. </span><span class="content">Revision 3 - April 15<sup>th</sup>, 2021</span><a class="self-link" href="#changelog-r3"></a></h3>
   <ul>
    <li data-md>
     <p>Added post C meeting fixes to prepare for hopeful success next meeting.</p>
    <li data-md>
     <p>Added 2 more examples to C and C++ wording.</p>
    <li data-md>
     <p>Vastly improved wording and reduced ambiguities in syntax and semantics.</p>
    <li data-md>
     <p>Fixed various wording issues.</p>
   </ul>
   <h3 class="heading settled" data-level="1.5" id="changelog-r2"><span class="secno">1.5. </span><span class="content">Revision 2 - October 25<sup>th</sup>, 2020</span><a class="self-link" href="#changelog-r2"></a></h3>
   <ul>
    <li data-md>
     <p>Added post C++ meeting notes and discussion.</p>
    <li data-md>
     <p>Removed type or bit specifications from the <code class="highlight"><c- cp>#embed</c-></code> directive.</p>
    <li data-md>
     <p>Moved "Type Flexibility" section and related notes to the Appendix as they are now unpursued.</p>
   </ul>
   <h3 class="heading settled" data-level="1.6" id="changelog-r1"><span class="secno">1.6. </span><span class="content">Revision 1 - April 10<sup>th</sup>, 2020</span><a class="self-link" href="#changelog-r1"></a></h3>
   <ul>
    <li data-md>
     <p>Added post C meeting notes and discussion.</p>
    <li data-md>
     <p>Added discussion of potential endianness.</p>
    <li data-md>
     <p>Improved wording section at the end to be more detailed in handling preprocessor (which does not understand types).</p>
   </ul>
   <h3 class="heading settled" data-level="1.7" id="changelog-r0"><span class="secno">1.7. </span><span class="content">Revision 0 - January 5<sup>th</sup>, 2020</span><a class="self-link" href="#changelog-r0"></a></h3>
   <ul>
    <li data-md>
     <p>Initial release.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="polls"><span class="secno">2. </span><span class="content">Polls &amp; Votes</span><a class="self-link" href="#polls"></a></h2>
   <p>The votes for the C++ Committee are as follows:</p>
   <ul>
    <li data-md>
     <p>SF: Strongly in Favor</p>
    <li data-md>
     <p>F: In Favor</p>
    <li data-md>
     <p>N: Neutral</p>
    <li data-md>
     <p>A: Against</p>
    <li data-md>
     <p>SA: Strongly Against</p>
   </ul>
   <h3 class="heading settled" data-level="2.1" id="polls-july.2021.c++"><span class="secno">2.1. </span><span class="content">July 2021 Virtual C++ meeting</span><a class="self-link" href="#polls-july.2021.c++"></a></h3>
   <p>No votes were taken at this meeting, since it was mostly directional and about the changing of the syntax to better fit tools and scanners. In particular, it was more or less unanimously encouraged to:</p>
   <ul>
    <li data-md>
     <p>re-do the syntax to be <code class="highlight"><c- cp>#embed header-name additional-tokens...</c-></code> instead of <code class="highlight"><c- cp>#embed limit-parameter header-name</c-></code>;</p>
    <li data-md>
     <p>the <code class="highlight"><c- n>additional</c-><c- o>-</c-><c- n>tokens</c-></code> should be reshaped into a parameter specification, giving both standard parameters (such as making a named <code class="highlight"><c- n>limit</c-><c- p>(</c-><c- n>integer</c-><c- o>-</c-><c- n>constant</c-><c- p>)</c-></code> argument) and implementation-defined ones (such as <code class="highlight"><c- n>clang</c-><c- o>::</c-><c- n>elementy_type</c-><c- p>(</c-><c- b>short</c-><c- p>)</c-></code>);</p>
    <li data-md>
     <p>and, the wording should include some recommendation or specification for "as-if by fread" to make wording easier.</p>
   </ul>
   <p>All of these recommendations were incorporated below.</p>
   <h3 class="heading settled" data-level="2.2" id="polls-september.2020.c++"><span class="secno">2.2. </span><span class="content">September 2020 Virtual C++ EWG Meeting</span><a class="self-link" href="#polls-september.2020.c++"></a></h3>
   <p>"We want <code class="highlight"><c- cp>#embed [optional limit] header-name</c-></code> (no type name, no other specification) as a feature."</p>
   <table>
    <thead>
     <tr>
      <th>SF
      <th>F
      <th>N
      <th>A
      <th>SA
    <tbody>
     <tr>
      <td>2
      <td>16
      <td>3
      <td>0
      <td>1
   </table>
   <p>This vote gained the most consensus in the Committee. While there were some individuals who wanted to be able to specify a type, there was stronger interest in not specifying a type at all and always producing a list of integer literals suitable to be used anywhere an <code class="highlight"><c- n>comma</c-><c- o>-</c-><c- n>separated</c-> <c- n>list</c-></code> was valid.</p>
   <p>"We want to explore allowing an optional sequence of tokens to specify a type to <code class="highlight"><c- cp>#embed</c-></code>."</p>
   <table>
    <thead>
     <tr>
      <th>SF
      <th>F
      <th>N
      <th>A
      <th>SA
    <tbody>
     <tr>
      <td>1
      <td>9
      <td>4
      <td>4
      <td>3
   </table>
   <p>Further need was also expressed for <code class="highlight"><c- k>constexpr</c-></code> of different types of variables, so we would rather focus that ability into a sister feature, <a href="/_vendor/future_cxx/d1140.html"><code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>embed</c-></code></a>. There was also an expression to augment <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>bitcast</c-><c- o>&lt;</c-><c- p>...</c-><c- o>></c-><c- p>(...)</c-></code> to handle arrays of data, which would be a follow-on proposal. There was a great amount of interest in the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>bitcast</c-></code> direction, which means a paper should be written to follow up on it.</p>
   <h3 class="heading settled" data-level="2.3" id="polls-april.2020.c"><span class="secno">2.3. </span><span class="content">April 2020 Virtual C Meeting</span><a class="self-link" href="#polls-april.2020.c"></a></h3>
   <p>"We want to have a proper preprocessor <code class="highlight"><c- cp>#embed ...</c-></code> over a <code class="highlight"><c- cp>#pragma _STDC embed ...</c-></code>-based directive."</p>
   <p>This had UNANIMOUS CONSENT to pursue a proper preprocessor directive and NOT use the <code class="highlight"><c- cp>#pragma</c-></code> syntax. It is noted that the author deems this to be the best decision!</p>
   <p><strong>The following poll was later superceded in the C and C++ Committees.</strong></p>
   <p>"We want to specify embed as using <code class="highlight"><c- cp>#embed [bits-per-element] header-name</c-></code> rather than <code class="highlight"><c- cp>#embed [pp-tokens-for-type] header-name</c-></code>." (2-way poll.)</p>
   <table>
    <thead>
     <tr>
      <th>Y
      <th>N
      <th>A
    <tbody>
     <tr>
      <td>10
      <td>2
      <td>3
   </table>
   <ul>
    <li data-md>
     <p>Y: 10 bits-per-element (Ye)</p>
    <li data-md>
     <p>N: 2 type-based (Nay)</p>
    <li data-md>
     <p>A: 4 Abstain (Abstain)</p>
   </ul>
   <p>This poll will be a bit harder to accommodate properly. Using a <i><code class="highlight"><c- n>constant</c-><c- o>-</c-><c- n>expression</c-></code></i> that produces a numeric constant means that the max-length specifier is now ambiguous. The syntax of the directive may need to change to accommodate further exploration.</p>
   <h2 class="heading settled" data-level="3" id="intro"><span class="secno">3. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>For well over 40 years, people have been trying to plant data into executables for varying reasons. Whether it is to provide a base image with which to flash hardware in a hard reset, icons that get packaged with an application, or scripts that are intrinsically tied to the program at compilation time, there has always been a strong need to couple and ship binary data with an application.</p>
   <p>Neither C nor C++ makes this easy for users to do, resulting in many individuals reaching for utilities such as <code class="highlight"><c- n>xxd</c-></code>, writing python scripts, or engaging in highly platform-specific linker calls to set up <code class="highlight"><c- k>extern</c-></code> variables pointing at their data. Each of these approaches come with benefits and drawbacks. For example, while working with the linker directly allows injection of very large amounts of data (5 MB and upwards), it does not allow accessing that data at any other point except runtime. Conversely, doing all of these things portably across systems and additionally maintaining the dependencies of all these resources and files in build systems both like and unlike <code class="highlight"><c- n>make</c-></code> is a tedious task.</p>
   <p>Thusly, we propose a new preprocessor directive whose sole purpose is to be <code class="highlight"><c- cp>#include</c-></code>, but for binary data: <code class="highlight"><c- cp>#embed</c-></code>.</p>
   <h3 class="heading settled" data-level="3.1" id="intro-motivation"><span class="secno">3.1. </span><span class="content">Motivation</span><a class="self-link" href="#intro-motivation"></a></h3>
   <p>The reason this needs a new language feature is simple: current source-level encodings of "producing binary" to the compiler are incredibly inefficient both ergonomically and mechanically. Creating a brace-delimited list of numerics in C comes with baggage in the form of how numbers and lists are formatted. C’s preprocessor and the forcing of tokenization also forces an unavoidable cost to lexer and parser handling of values.</p>
   <p>Therefore, using arrays with specific initialized values of any significant size becomes borderline impossible. One would <a href="https://groups.google.com/forum/#!topic/comp.std.c/zWFEXDvyTwM">think this old problem</a> would be work-around-able in a succinct manner. Given how old this desire is (that comp.std.c thread is not even the oldest recorded feature request), proper solutions would have arisen. Unfortunately, that could not be farther from the truth. Even the compilers themselves suffer build time and memory usage degradation, as contributors to the LLVM compiler ran the gamut of <a href="http://lists.llvm.org/pipermail/llvm-dev/2020-January/138225.html">the biggest problems that motivate this proposal</a> in a matter of a week or two earlier this very year. Luke is not alone in his frustrations: developers all over suffer from the inability to include binary in their program quickly and perform <a href="https://twitter.com/oe1cxw/status/1008361214018244608">exceptional gymnastics</a> to get around the compiler’s inability to handle these cases.</p>
   <p>C developer progress is impeded regarding the <a href="https://twitter.com/pcwalton/status/1233521726262300672">inability to handle this use case</a>, and it leaves both old and new programmers wanting.</p>
   <h3 class="heading settled" data-level="3.2" id="design-efficiency-metrics"><span class="secno">3.2. </span><span class="content">But <em>How</em> Expensive Is This?</span><a class="self-link" href="#design-efficiency-metrics"></a></h3>
   <p>Many different options as opposed to this proposal were seriously evaluated. Implementations were attempted in at least 2 production-use compilers, and more in private. To give an idea of usage and size, here are results for various compilers on a machine with the following specification:</p>
   <ul>
    <li data-md>
     <p>Intel Core i7 @ 2.60 GHz</p>
    <li data-md>
     <p>24.0 GB RAM</p>
    <li data-md>
     <p>Debian Sid or Windows 10</p>
    <li data-md>
     <p>Method: Execute command hundreds of times, stare extremely hard at <code class="highlight"><c- n>htop</c-></code>/Task Manager</p>
   </ul>
   <p>While <code class="highlight"><c- n>time</c-></code> and <code class="highlight"><c- n>Measure</c-><c- o>-</c-><c- n>Command</c-></code> work well for getting accurate timing information and can be run several times in a loop to produce a good average value, tracking memory consumption without intrusive efforts was much harder and thusly relied on OS reporting with fixed-interval probes. Memory usage is therefore approximate and may not represent the actual maximum of consumed memory. All of these are using the latest compiler built from source if available, or the latest technology preview if available. Optimizations at <code class="highlight"><c- o>-</c-><c- n>O2</c-></code> (GCC &amp; Clang style)/<code class="highlight"><c- o>/</c-><c- n>O2</c-> <c- o>/</c-><c- n>Ob2</c-></code> (MSVC style) or equivalent were employed to generate the final executable.</p>
   <h4 class="heading settled" data-level="3.2.1" id="intro-metrics-speed"><span class="secno">3.2.1. </span><span class="content">Speed</span><a class="self-link" href="#intro-metrics-speed"></a></h4>
   <table>
    <thead>
     <tr>
      <th>Strategy
      <th>40 kilobytes
      <th>400 kilobytes
      <th>4 megabytes
      <th>40 megabytes
    <tbody>
     <tr>
      <td><code class="highlight"><c- cp>#embed</c-></code> GCC
      <td>0.236 s
      <td>0.231 s
      <td>0.300 s
      <td>1.069 s
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated GCC
      <td>0.406 s
      <td>2.135 s
      <td>23.567 s
      <td>225.290 s
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated Clang
      <td>0.366 s
      <td>1.063 s
      <td>8.309 s
      <td>83.250 s
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated MSVC
      <td>0.552 s
      <td>3.806 s
      <td>52.397 s
      <td>Out of Memory
   </table>
   <h4 class="heading settled" data-level="3.2.2" id="intro-metrics-space"><span class="secno">3.2.2. </span><span class="content">Memory Size</span><a class="self-link" href="#intro-metrics-space"></a></h4>
   <table>
    <thead>
     <tr>
      <th>Strategy
      <th>40 kilobytes
      <th>400 kilobytes
      <th>4 megabytes
      <th>40 megabytes
    <tbody>
     <tr>
      <td><code class="highlight"><c- cp>#embed</c-></code> GCC
      <td>17.26 MB
      <td>17.96 MB
      <td>53.42 MB
      <td>341.72 MB
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated GCC
      <td>24.85 MB
      <td>134.34 MB
      <td>1,347.00 MB
      <td>12,622.00 MB
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated Clang
      <td>41.83 MB
      <td>103.76 MB
      <td>718.00 MB
      <td>7,116.00 MB
     <tr>
      <td><code class="highlight"><c- n>xxd</c-></code>-generated MSVC
      <td>~48.60 MB
      <td>~477.30 MB
      <td>~5,280.00 MB
      <td>Out of Memory
   </table>
   <h4 class="heading settled" data-level="3.2.3" id="intro-metrics-analysis"><span class="secno">3.2.3. </span><span class="content">Analysis</span><a class="self-link" href="#intro-metrics-analysis"></a></h4>
   <p>The numbers here are not reassuring that compiler developers can reduce the memory and compilation time burdens with regard to large initializer lists. Furthermore, privately owned compilers and other static analysis tools perform almost exponentially worse here, taking vastly more memory and thrashing CPUs to 100% for several minutes (to sometimes several hours if e.g. the Swap is engaged due to lack of main memory). Every compiler must always consume a certain amount of memory in a relationship directly linear to the number of tokens produced. After that, it is largely implementation-dependent what happens to the data.</p>
   <p>The GNU Compiler Collection (GCC) uses a tree representation and has many places where it spawns extra "garbage", as its called in the various bug reports and work items from implementers. There has been a 16+ year effort on the part of GCC to reduce its memory usage and speed up initializers (<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=12245">C Bug Report</a> and <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14179">C++ Bug Report</a>). Significant improvements have been made and there is plenty of room for GCC to improve here with respect to compiler and memory size. Somewhat unfortunately, one of the current changes in flight for GCC is the removal of all location information beyond the 256th initializer of large arrays in order to save on space. This technique is not viable for static analysis compilers that promise to recreate source code exactly as was written, and therefore discarding location or token information for large initializers is not a viable cross-implementation strategy.</p>
   <p>LLVM’s Clang, on the other hand, is much more optimized. They maintain a much better scaling and ratio but still suffer the pain of their token overhead and Abstract Syntax Tree representation, though to a much lesser degree than GCC. A bug report was filed but talk from two prominent LLVM/Clang developers made it clear that optimizing things any further would <a href="https://bugs.llvm.org/show_bug.cgi?id=44399">require an extremely large refactor of parser internals with a lot of added functionality</a>, with potentially dubious gains. As part of this proposal, the implementation provided does attempt to do some of these optimizations, and follows some of the work done in <a href="https://cor3ntin.github.io/posts/arrays/">this post</a> to try and prove memory and file size savings. (The savings in trying to optimize parsing large array literals were "around 10%", compared to the order-of-magnitude gains from <code class="highlight"><c- cp>#embed</c-></code> and similar techniques).</p>
   <p>Microsoft Visual C (MSVC) scales the worst of all the compilers, even when given the benefit of being on its native operating system. Both Clang and GCC outperform MSVC on Windows 10 or WINE as of the time of writing.</p>
   <p>Linker tricks on all platforms perform better with time (though slower than <code class="highlight"><c- cp>#embed</c-></code> implementation), but force the data to be optimizer-opaque (even on the most aggressive "Link Time Optimization" or "Whole Program Optimization" modes compilers had). Linker tricks are also exceptionally non-portable: whether it is the <code class="highlight"><c- n>incbin</c-></code> assembly command supported by certain compilers, specific invocations of <code class="highlight"><c- n>rc</c-><c- p>.</c-><c- n>exe</c-></code>/<code class="highlight"><c- n>objcopy</c-></code> or others, non-portability plagues their usefulness in writing Cross-Platform C (see Appendix for listing of techniques). This makes C decidedly unlike the "portable assembler" advertised by its proponents (and my Professors and co-workers).</p>
   <h2 class="heading settled" data-level="4" id="design"><span class="secno">4. </span><span class="content">Design</span><a class="self-link" href="#design"></a></h2>
   <p>There are two design goals at play here, sculpted to specifically cover industry standard practices with build systems and C programs.</p>
   <p>The first is to enable developers to get binary content quickly and easily into their applications. This can be icons/images, scripts, tiny sound effects, hardcoded firmware binaries, and more. In order to support this use case, this feature was designed for simplicity and builds upon widespread existing practice.</p>
   <p>The second is extensibility. We recognize that talking to arbitrary places on either the file system, network, or similar has different requirements. After feedback from an implementer about syntax for extensions, we reached out to various users of the beta builds or custom builds using <code class="highlight"><c- cp>#embed</c-></code>-like things. It turns out many of them have needs that, since they are the ones building and in some cases patching over/maintaining their compiler, have needs for extensible attributes that can be passed to <code class="highlight"><c- cp>#embed</c-></code> directives. Therefore, we structured the syntax in a way that is favorable to "simple" scanning tools but powerful enough to handle arbitrary directives and future extension points.</p>
   <h3 class="heading settled" data-level="4.1" id="design-familiar"><span class="secno">4.1. </span><span class="content">Goal: Simplicity and Familiarity</span><a class="self-link" href="#design-familiar"></a></h3>
   <p>Providing a directive that mirrors <code class="highlight"><c- cp>#include</c-></code> makes it natural and easy to understand and use this new directive. It accepts both chevron-delimited (<code class="highlight"><c- o>&lt;></c-></code>) and quote-delimited (<code class="highlight"><c- s>""</c-></code>) strings like <code class="highlight"><c- cp>#include</c-></code> does. This matches the way people have been generating files to <code class="highlight"><c- cp>#include</c-></code> in their programs, libraries and applications: matching the semantics here preserves the same mental model. This makes it easy to teach and use, since it follows the same principles:</p>
<pre class="language-cpp highlight"><c- d>/* default is unsigned char */</c->
<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>icon_display_data</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
		<c- cp>#embed "art.png"</c->
<c- p>};</c->

<c- d>/* specify any type which can be initialized form integer constant expressions will do */</c->
<c- k>const</c-> <c- b>char</c-> <c- n>reset_blob</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
		<c- cp>#embed "data.bin"</c->
<c- p>};</c->
</pre>
   <p>Because of its design, it also lends itself to being usable in a wide variety of contexts and with a wide variety of vendor extensions. For example:</p>
<pre class="language-cpp highlight"><c- d>/* attributes work just as well */</c->
<c- k>const</c-> <c- b>signed</c-> <c- b>char</c-> <c- n>aligned_data_str</c-><c- p>[]</c-> <c- n>__attribute__</c-> <c- p>((</c-><c- n>aligned</c-> <c- p>(</c-><c- mi>8</c-><c- p>)))</c-> <c- o>=</c-> <c- p>{</c->
		<c- cp>#embed "attributes.xml"</c->
<c- p>};</c->
</pre>
   <p>The above code obeys the alignment requirements for an implementation that understands GCC directives, without needing to add special support in the <code class="highlight"><c- cp>#embed</c-></code> directive for it: it is just another array initializer, like everything else.</p>
   <h4 class="heading settled" data-level="4.1.1" id="design-familiar-paths"><span class="secno">4.1.1. </span><span class="content">Existing Practice - Search Paths</span><a class="self-link" href="#design-familiar-paths"></a></h4>
   <p>It follows the same implementation experience guidelines as <code class="highlight"><c- cp>#include</c-></code> by leaving the search paths implementation defined, with the understanding that implementations are not monsters and will generally provide <code class="highlight"><c- o>-</c-><c- n>fembed</c-><c- o>-</c-><c- n>path</c-></code>/<code class="highlight"><c- o>-</c-><c- n>fembed</c-><c- o>-</c-><c- n>path</c-><c- o>=</c-></code> and other related flags as their users require for their systems. This gives implementers the space they need to serve the needs of their constituency.</p>
   <h4 class="heading settled" data-level="4.1.2" id="design-familiar-distributed"><span class="secno">4.1.2. </span><span class="content">Existing Practice - Discoverable and Distributable</span><a class="self-link" href="#design-familiar-distributed"></a></h4>
   <p>Build systems today understand the make dependency format, typically through use of the compiler flags <code class="highlight"><c- o>-</c-><c- p>(</c-><c- n>M</c-><c- p>)</c-><c- n>MD</c-></code> and friends. This sees widespread support, from CMake, Meson and Bazel to ninja and make. Even VC++ has a version of this flag -- <code class="highlight"><c- o>/</c-><c- n>showIncludes</c-></code> -- that gets parsed by build systems.</p>
   <p>This preprocessor directive fits perfectly into existing build architecture by being discoverable in the same way with the same tooling formats. It also blends perfectly with existing distributed build systems which preprocess their files with <code class="highlight"><c- o>-</c-><c- n>frewrite</c-><c- o>-</c-><c- n>includes</c-></code> before sending it up to the build farm, as <code class="highlight"><c- n>distcc</c-></code> and <code class="highlight"><c- n>icecc</c-></code> do.</p>
   <h3 class="heading settled" data-level="4.2" id="design-syntax"><span class="secno">4.2. </span><span class="content">Syntax</span><a class="self-link" href="#design-syntax"></a></h3>
   <p>The syntax for this feature is for an extensible preprocessor directive. The general form is:</p>
   <p><code class="highlight"><c- cp># embed &lt;header-name>|"header-name" parameters...</c-></code></p>
   <p>where <code class="highlight"><c- n>parameters</c-></code> refers to the syntax of <code class="highlight"><c- n>no_arg</c-></code>/<code class="highlight"><c- n>with_arg</c-><c- p>(</c-><c- n>values</c-><c- p>,</c-> <c- p>...)</c-></code>/<code class="highlight"><c- n>vendor</c-><c- o>::</c-><c- n>no_arg</c-></code>/<code class="highlight"><c- n>vendor</c-><c- o>::</c-><c- n>with_arg</c-><c- p>(</c-><c- n>tokens</c-><c- p>...)</c-></code> that is already part of the grammar. The syntax takes after many existing extensions in many preprocessor implementations and specifications, including OpenMP, Clang <code class="highlight"><c- cp>#pragma</c-></code>s, Microsoft <code class="highlight"><c- cp>#pragma</c-></code>s, and more. The named parameters was a recommendation by an implementer</p>
   <p>This syntax keeps the header-name, enclosed in angle brackets or quotation marks, first to allow a "simple" preprocessing tool to quickly scan for all the necessary dependency names without having to parse any of the names or parameters that come after. Both standard names and vendor/implementation-specific names can also be accommodated in the list of naked attributes, allowing for specific vendor extensions in a consistent manner while the standard can take the normal <code class="highlight"><c- n>foo</c-></code> names.</p>
   <h4 class="heading settled" data-level="4.2.1" id="design-syntax-parameters"><span class="secno">4.2.1. </span><span class="content">Parameters</span><a class="self-link" href="#design-syntax-parameters"></a></h4>
   <p>One of the things that’s critical about <code class="highlight"><c- cp>#embed</c-></code> is that, because it works with binary resources, those resources have characteristics very much different from source and header files present in a typical filesystem. There may be need for authentication (possibly networked), permission, access, additional processing (new-line normalization), and more that can be somewhat similarly specified through the implementation-defined parameters already available through the C and C++ Standards' "<code class="highlight"><c- n>fopen</c-></code>" function.</p>
   <p>However, adding a "mode" string similar to <code class="highlight"><c- n>fopen</c-></code>, while extensible, is archaic and hard to check. Therefore, the syntax allows for multiple "named expressions", encapsulated in parentheses, and marked with <code class="highlight"><c- o>::</c-></code> as a form of "namespacing" identifiers similar to <code class="highlight"><c- p>[[</c-><c- n>vendor</c-><c- o>::</c-><c- n>attr</c-><c- p>]]</c-></code> attribute-style syntax. However, parameters do not have the balanced square bracket <code class="highlight"><c- p>[[]]</c-></code> delimiters, and just use the <code class="highlight"><c- n>vendor</c-><c- o>::</c-><c- n>attr</c-></code> form with an optional parentheses-enclosed list of arguments.</p>
   <p>Some example attributes including interpreting the binary data as "text" rather than a bitstream with <code class="highlight"><c- n>clang</c-><c- o>::</c-><c- n>text</c-><c- p>(</c-><c- n>utf</c-><c- mi>-8</c-><c- p>)</c-></code>, providing authenticated access with <code class="highlight"><c- n>fs</c-><c- o>::</c-><c- n>auth</c-><c- p>(</c-><c- s>"username"</c-><c- p>,</c-> <c- s>"password"</c-><c- p>)</c-></code>, <code class="highlight"><c- n>yosys</c-><c- o>::</c-><c- n>type</c-><c- p>(</c-><c- n>hardware_entry</c-><c- p>)</c-></code> to change the element of each entry produced, and more. These are all things vendors have indicated they might support for their use cases.</p>
   <h5 class="heading settled" data-level="4.2.1.1" id="design-syntax-parameters-limit"><span class="secno">4.2.1.1. </span><span class="content">Limit Parameter</span><a class="self-link" href="#design-syntax-parameters-limit"></a></h5>
   <p>The earliest adopters and testers of the implementation reported problems when trying to access POSIX-style <code class="highlight"><c- b>char</c-></code> devices and pseudo-files that do not have a logical limitation. These "infinity files" served as the motivation for introducing the "limit" parameter; there are a number of resources which are logically infinite and thusly having a compiler read all of the data would result an Out of Memory error, much like with <code class="highlight"><c- cp>#include</c-></code> if someone did <code class="highlight"><c- cp>#include</c-> "/dev/urandom"</code>.</p>
   <p>The limit parameter is specified after the resource name in <code class="highlight"><c- cp>#embed</c-></code>, like so:</p>
<pre class="language-cpp highlight"><c- k>const</c-> <c- b>int</c-> <c- n>please_dont_oom_kill_me</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
	<c- cp>#embed "/dev/urandom" limit(512)</c->
<c- p>};</c->
</pre>
   <p>This prevents locking compilers in an infinite loop of reading from potentially limitless resources. Note the parameter is a hard upper bound, and not an exact requirement. A resource may expand to a 16-element list rather than a 512-element list, and that is entirely expected behavior. The limit is the number of elements allowed up to the maximum for this type.</p>
   <p>This does not provide a form of "timeout" for e.g. resources stored on a Network File System or an inactivity limit or similar. Implementations that utilize support for more robust handling of resource location schemes like Uniform Resource Identifiers (URIs) that may interface with resources that take extensive amounts of time to locate should provide implementation-defined extensions for timeout or inactivity checks.</p>
   <h5 class="heading settled" data-level="4.2.1.2" id="design-syntax-parameters-non_empty"><span class="secno">4.2.1.2. </span><span class="content">Non-Empty Prefix and Suffix</span><a class="self-link" href="#design-syntax-parameters-non_empty"></a></h5>
   <p>Something pointed out by others using this preprocessor directive is a problem similar to <code class="highlight"><c- n>__VA_ARGS__</c-></code>: when placing this parameter with other tokens before or after the <code class="highlight"><c- cp>#embed</c-></code> directive, it sometimes made it hard to properly anticipate whether a file was empty or not.</p>
   <p>The <code class="highlight"><c- cp>#embed</c-></code> proposal includes a prefix and suffix entry that applies if and only if the resource is non-empty:</p>
<pre class="language-cpp highlight"><c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>null_terminated_file_data</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
	<c- cp>#embed "might_be_empty.txt" \</c->
<c- cp>		prefix(0xEF, 0xBB, 0xBF, ) </c-><c- d>/* UTF-8 BOM */</c-><c- cp> \</c->
<c- cp>		suffix(,)</c->
	<c- mi>0</c-> <c- c1>// always null-terminated</c->
<c- p>};</c->
</pre>
   <p><code class="highlight"><c- n>prefix</c-></code> and <code class="highlight"><c- n>suffix</c-></code> only work if the <code class="highlight"><c- cp>#embed</c-></code> resource is not empty. If a user wants a prefix or suffix that appears unconditionally, they can simply just type the tokens they want before and after: there is nothing to be gained from adding a standards-mandated prefix and suffix that works in both the empty and non-empty case.</p>
   <h5 class="heading settled" data-level="4.2.1.3" id="design-syntax-parameters-empty"><span class="secno">4.2.1.3. </span><span class="content">Empty Signifier</span><a class="self-link" href="#design-syntax-parameters-empty"></a></h5>
   <p>This is for the case when the given resource exists, but it is empty. This allows a user to have a sequence of tokens between the parentheses passed to the <code class="highlight"><c- n>is_empty</c-></code> parameter here: <code class="highlight"><c- cp>#embed "blah" is_empty(SPECIAL_EMPTY_MARKER MORE TOKENS)</c-></code>.</p>
   <p>If <code class="highlight"><c- s>"blah"</c-></code> exists but is empty, this will replace the directive with the (potentially macro expanded) contents between the parentheses of the <code class="highlight"><c- n>is_empty</c-></code> parameter. This can also be combined with a <code class="highlight"><c- n>limit</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-></code> parameter to always have the <code class="highlight"><c- n>is_empty</c-></code> token return. This can be useful for macro-expanded integer constant expressions that may end up being 0.</p>
   <p>An example program <code class="highlight"><c- n>single</c-><c- o>-</c-><c- n>urandom</c-><c- p>.</c-><c- n>c</c-></code>:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
<c- cp>#define SOME_CONSTANT 0</c->
    <c- k>return</c->
<c- cp>#embed &lt;/dev/urandom> is_empty(0) limit(SOME_CONSTANT)</c->
    <c- p>;</c->
<c- p>}</c->
</pre>
   <p>This program will expand to the equivalent of <code class="highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- mi>0</c-><c- p>;</c-> <c- p>}</c-></code> if <code class="highlight"><c- n>SOME_CONSTANT</c-></code> is 0, or a single (random) <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code> value if it is 1. (If <code class="highlight"><c- n>SOME_CONSTANT</c-></code> is greater than 1, it produces a comma-delimited list of integers, which gets treated as a sequence to the comma operator after the <code class="highlight"><c- k>return</c-></code> keyword. <a href="https://godbolt.org/z/Kjn9nreY1">Some compilers warn about the left-hand operands having no effect</a>.)</p>
   <p>Previously, this was the only way to detect that the resource was empty. This functionality can be substituted with having to use <code class="highlight"><c- n>__has_embed</c-><c- p>(</c->…<c- p>)</c-></code> with the same contents and specifically check for the return value of <code class="highlight"><c- o>==</c-> <c- mi>2</c-></code>. While this change create some repeating-yourself friction in the identifier, there was only 1 user who actually needed the is_empty signifier, and that was only because they were using it to replace it with a very particularly sized and shaped data array. The <code class="highlight"><c- n>__has_embed</c-></code> technique worked just fine for them as well at the cost of some repetition (to check for embed parameters), and after some discussion with the user it was deemed okay to switch to this syntax, since during the discusison of <code class="highlight"><c- cp>#embed</c-></code> in the January/February 2022 WG14 C Standards Committee Meeting it was commented on that there were too many signifiers.</p>
   <p>We do not want to entirely lose that user’s use case, however, so we have made the <code class="highlight"><c- n>is_empty</c-></code> parameter an <strong>optional</strong> part of the wording, to be voted on as a <strong>separate</strong> piece.</p>
   <h3 class="heading settled" data-level="4.3" id="design-constexpr"><span class="secno">4.3. </span><span class="content">Constant Expressions</span><a class="self-link" href="#design-constexpr"></a></h3>
   <p>Both C and C++ compilers have rich constant folding capabilities. While C compilers only acknowledge a fraction of what is possible by larger implementations like MSVC, Clang, and GCC, C++ has an entire built-in compile-time programming bit, called <code class="highlight"><c- k>constexpr</c-></code>. Most typical solutions cannot be used as constant expressions because they are hidden behind run-time or link-time mechanisms (<code class="highlight"><c- n>objcopy</c-></code>, or the resource compiler <code class="highlight"><c- n>rc</c-><c- p>.</c-><c- n>exe</c-></code> on Windows, or the static library archiving tools). This means that many algorithms and data components which could strongly benefit from having direct access to the values of the integer constants do not because the compiler cannot "see" the data, or because Whole Program Optimization cannot be aggressive enough to do anything with those values at that point in the compilation (i.e., during the final linking stage).</p>
   <p>This makes <code class="highlight"><c- cp>#embed</c-></code> especially powerful, since it guarantees these values are available as-if it was written by as a sequence of integers whose values fit within an <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code>.</p>
   <h3 class="heading settled" data-level="4.4" id="design-__has_embed"><span class="secno">4.4. </span><span class="content"><code class="highlight"><c- n>__has_embed</c-></code></span><a class="self-link" href="#design-__has_embed"></a></h3>
   <p>C and C++ are support a <code class="highlight"><c- n>__has_include</c-></code> . It makes sense to have an analogous <code class="highlight"><c- n>__has_embed</c-></code> identifier. It can take a <code class="highlight"><c- n>__has_embed</c-><c- p>(</c-> <c- s>"header-name"</c-> <c- p>...</c-> <c- p>)</c-></code> or <code class="highlight"><c- n>__has_embed</c-> <c- p>(</c-><c- o>&lt;</c-><c- n>header</c-><c- o>-</c-><c- n>name</c-><c- o>></c-> <c- p>...</c-> <c- p>)</c-></code> resource name identifier, as well as additional arguments to let vendors pass in any additional arguments they need to properly access the file (following the same attribute-like parameters passed to the directive). <code class="highlight"><c- n>__has_embed</c-></code> evaluates to:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- mi>0</c-></code> if the reesource is not found or any parameter in the <code class="highlight"><c- n>embed</c-><c- o>-</c-><c- n>parameter</c-><c- o>-</c-><c- n>list</c-></code> does not exist; or,</p>
    <li data-md>
     <p><code class="highlight"><c- mi>1</c-></code> if the resource is found, it is not empty, and the <code class="highlight"><c- n>embed</c-><c- o>-</c-><c- n>parameter</c-><c- o>-</c-><c- n>list</c-></code> (including the vendor-specific ones) are supported; or,</p>
    <li data-md>
     <p><code class="highlight"><c- mi>2</c-></code> if the resource is found, it is empty, and the <code class="highlight"><c- n>embed</c-><c- o>-</c-><c- n>parameter</c-><c- o>-</c-><c- n>list</c-></code> (including the vendor-specific ones) are supported.</p>
   </ul>
   <p>This may raise questions of "TOCTTOU" (Time of Check to Time of Use) problems, but we already have these problems between <code class="highlight"><c- n>__has_include</c-></code> and <code class="highlight"><c- cp>#include</c-></code>. They are also already solved by existing implementations. For example, the LLVM/Clang compiler uses <code class="highlight"><c- n>FileManager</c-></code> and <code class="highlight"><c- n>SourceManager</c-></code> abstractions which cache files. GCC’s "libcpp" will cache already-opened files (up to a limit). Any TOCTTOU problems have already been managed and provided for using the current <code class="highlight"><c- cp>#include</c-></code> infrastructure of these compilers, and if any compiler wants a more streamlined and consistent experience they should deploy whatever Quality of Implementation (QoI) they see fit to achieve that goal.</p>
   <p>Finally, note that this directive DOES expand to <code class="highlight"><c- mi>0</c-></code> if a given parameters that the implementation does not support. This makes it easier to determine if a given vendor-specific embed directive is supported. In fact, support can be checked in most cases by using a combination of <code class="highlight"><c- n>__FILE__</c-></code> and <code class="highlight"><c- n>__has_embed</c-></code>:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
<c- cp>#if __has_embed (__FILE__ clang::element_type(short))</c->
	<c- c1>// load "short" values directly from memory</c->
	<c- b>short</c-> <c- n>meow</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed "bits.bin" clang::element_type(short)</c->
	<c- p>};</c->
<c- cp>#else</c->
	<c- c1>// no support for implementation-specifid</c->
	<c- c1>// clang::element_type parameter</c->
	<c- b>unsigned</c-> <c- b>char</c-> <c- n>meow_bytes</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed "bits.bin"</c->
	<c- p>};</c->
	<c- b>unsigned</c-> <c- b>short</c-> <c- n>meow</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
		<c- d>/* parse meow_bytes into short values</c->
<c- d>		   by-hand! */</c->
	<c- p>};</c->
<c- cp>#endif</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>For the C proposal, the wording for <code class="highlight"><c- n>__has_embed</c-><c- p>(...)</c-></code> returning <code class="highlight"><c- mi>2</c-></code> is optional, as it depends on whether or not the C Committee would like to solve this problem in one specific direction or another.</p>
   <h3 class="heading settled" data-level="4.5" id="design-endianness"><span class="secno">4.5. </span><span class="content">Bit Blasting: Endianness</span><a class="self-link" href="#design-endianness"></a></h3>
   <blockquote>
    <p>What would happen if you did <code class="highlight"><c- n>fread</c-></code> into an <code class="highlight"><c- b>int</c-></code>?</p>
    <p>that’s my answer 🙂</p>
    <p>– Isabella Muerte</p>
   </blockquote>
   <p>It’s a simple answer. While we may not be reading into <code class="highlight"><c- b>int</c-></code>, the idea here is that the interpretation of the directive is meant to get as close to directly copying the bitstream, as is possible. A compiler-magic based implementation like the ones provided as part of this paper have no endianness issues, but an implementation which writes out integer literals may need to be careful of host vs. target endianness to make sure it serializes correctly to the final binary. As a litmus test, the following code -- given a suitably sized <code class="highlight"><c- s>"foo.bin"</c-></code> resource -- should return <code class="highlight"><c- mi>0</c-></code>:</p>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;cstdio>
<c- cp>#include</c-> &lt;cstring>

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>foo0</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed "foo.bin"</c->
	<c- p>};</c->

	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>foo1</c-><c- p>[</c-><c- k>sizeof</c-><c- p>(</c-><c- n>foo0</c-><c- p>)];</c->
	<c- n>std</c-><c- o>::</c-><c- b>FILE</c-><c- o>*</c-> <c- n>fp</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fopen</c-><c- p>(</c-><c- s>"foo.bin"</c-><c- p>);</c->
	<c- k>if</c-> <c- p>(</c-><c- n>fp</c-> <c- o>==</c-> <c- k>nullptr</c-><c- p>)</c-> <c- p>{</c->
		<c- k>return</c-> <c- mi>1</c-><c- p>;</c->
	<c- p>}</c->
	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>foo1_read</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>fread</c-><c- p>(</c-><c- n>foo1</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>foo1</c-><c- p>),</c-> <c- n>fp</c-><c- p>);</c->
	<c- k>if</c-> <c- p>(</c-><c- n>foo1_read</c-> <c- o>!=</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>foo1</c-><c- p>))</c-> <c- p>{</c->
		<c- k>return</c-> <c- mi>1</c-><c- p>;</c->
	<c- p>}</c->
	<c- k>if</c-> <c- p>(</c-><c- n>memcmp</c-><c- p>(</c-><c- o>&amp;</c-><c- n>foo0</c-><c- p>[</c-><c- mi>0</c-><c- p>],</c-> <c- o>&amp;</c-><c- n>foo1</c-><c- p>[</c-><c- mi>0</c-><c- p>],</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>foo0</c-><c- p>))</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c-> <c- p>{</c->
		<c- k>return</c-> <c- mi>1</c-><c- p>;</c->
	<c- p>}</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>If the same file during both translation and execution, <code class="highlight"><c- s>"foo.bin"</c-></code>, is used here, this program should always return <code class="highlight"><c- mi>0</c-></code>. This is what the wording below attempts to achieve. Note that this is always a concern already, due to <code class="highlight"><c- n>CHAR_BIT</c-></code> and other target environment-specific variables that already exist; implementations have always been responsible for handling differences between the host and the target and this directive is no different. If the <code class="highlight"><c- n>CHAR_BIT</c-></code> of the host vs. the target is the same, then the directive is more simple. If it is not, then an implementation will have to perform translation.</p>
   <h2 class="heading settled" data-level="5" id="implementation"><span class="secno">5. </span><span class="content">Implementation Experience</span><a class="self-link" href="#implementation"></a></h2>
   <p>An implementation of this functionality is available in branches of both GCC and Clang, accessible right now with an internet connection through the online utility Compiler Explorer. The Clang compiler with this functionality is called <a href="https://godbolt.org/z/x5vhTrqvs">"x86-64 clang (thephd.dev)"</a> in the Compiler Explorer UI:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
    <c- k>return</c->
<c- cp>#embed &lt;/dev/urandom> limit(1)</c->
    <c- p>;</c->
<c- p>}</c->
</pre>
   <div class="pagebreak"></div>
   <h2 class="heading settled" data-level="6" id="alternative"><span class="secno">6. </span><span class="content">Alternative Syntax</span><a class="self-link" href="#alternative"></a></h2>
   <p>There were previous concerns about the syntax using pragma-like syntax and more. WG14 voted to keep the syntax as a plain <code class="highlight"><c- cp>#embed</c-></code> preprocessor directive, unanimously.</p>
   <p>Previously, different syntax was used to specify the limit and other kinds of parameters. These have been normalized to be a suffix of attribute-like parameters, at the request of an implementer and the C++ Standards Committee discussion of the paper in June 2021. It has had hugely positive feedback and users have reported the new syntax to be clearer, while other implementers have stated this is much better for them and the platforms for which they intend to add additional embed parameters.</p>
   <h2 class="heading settled" data-level="7" id="wording"><span class="secno">7. </span><span class="content">Wording</span><a class="self-link" href="#wording"></a></h2>
   <p>This wording is relative to C++'s latest working draft.</p>
   <h3 class="heading settled" data-level="7.1" id="wording-intent"><span class="secno">7.1. </span><span class="content">Intent</span><a class="self-link" href="#wording-intent"></a></h3>
   <p>The intent of the wording is to provide a preprocessing directive that:</p>
   <ul>
    <li data-md>
     <p>takes a quote or chevron delimited header-name -- potentially from the expansion of a macro -- and uses it to find a unique resource in an implementation-defined manner;</p>
    <li data-md>
     <p>behaves as if it produces a list of values suitable for the initialization of an array as well as initializes each <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code> element according to the specific environment limits found in an implementation-defined manner;</p>
    <li data-md>
     <p>errors if the size of the resource does not have enough bits to fully and properly initialize all the values generated by the directive;</p>
    <li data-md>
     <p>allows a limit parameter limiting the number of elements to be specified (but allowing less than the limit);</p>
    <li data-md>
     <p>produces a core constant expression that can be used to initialize <code class="highlight"><c- k>constexpr</c-></code> arrays;</p>
    <li data-md>
     <p>and, present such contents as if it is a list of values, such that it can be used to initialize arrays of known and unknown bound even if additional elements of the whole initialization list come before or after the directive.</p>
   </ul>
   <h3 class="heading settled" data-level="7.2" id="wording-feature_test"><span class="secno">7.2. </span><span class="content">Proposed Feature Test Macro</span><a class="self-link" href="#wording-feature_test"></a></h3>
   <p>The proposed feature test macro is <code class="highlight"><c- n>__cpp_pp_embed</c-></code> for the preprocessor functionality.</p>
   <h3 class="heading settled" data-level="7.3" id="wording-specification"><span class="secno">7.3. </span><span class="content">Proposed Language Wording</span><a class="self-link" href="#wording-specification"></a></h3>
   <h4 class="heading settled" data-level="7.3.1" id="wording-specification-cpp.predefined"><span class="secno">7.3.1. </span><span class="content">Append to §14.8.1 Predefined macro names [<strong>cpp.predefined</strong>] an additional entry</span><a class="self-link" href="#wording-specification-cpp.predefined"></a></h4>
   <blockquote>
    <ins>
<pre class="language-cpp highlight"><c- cp>#define __cpp_pp_embed     ????? </c-><c- d>/* 📝 NOTE: EDITOR VALUE HERE */</c->
</pre>
    </ins>
   </blockquote>
   <h4 class="heading settled" data-level="7.3.2" id="wording-specification-cpp.pre"><span class="secno">7.3.2. </span><span class="content">Add to the <em>control-line</em> production in §15.1 Preamble [<strong>cpp.pre</strong>] a new grammar production, as well as a supporting <em>embed-attribute-list</em> production</span><a class="self-link" href="#wording-specification-cpp.pre"></a></h4>
   <blockquote>
    <div class="wording-section">
     <div>
      <ins>
       <p><em>embed-parameter-list</em>:</p>
       <dl>
        <dd data-md>
         <p><em>attribute</em><sub>opt</sub></p>
        <dd data-md>
         <p><em>embed-parameter-list</em> <em>attribute</em><sub>opt</sub></p>
       </dl>
      </ins>
     </div>
     <div>
      <p><em>control-line</em>:</p>
      <dl>
       <dd data-md>
        <p>...<br></p>
       <dd data-md>
        <ins><code class="highlight"><c- cp># embed</c-></code> <em>pp-tokens</em> <em>new-line</em></ins>
      </dl>
     </div>
    </div>
   </blockquote>
   <h4 class="heading settled" data-level="7.3.3" id="wording-specification-cpp.cond"><span class="secno">7.3.3. </span><span class="content">Modify §15.2 Conditional inclusion [<strong>cpp.cond</strong>] to include a new "has-embed-expression" by modifying paragraph 1 and adding a new paragraph 5 after the current paragraph 4</span><a class="self-link" href="#wording-specification-cpp.cond"></a></h4>
   <blockquote>
    <ins>
     <p><em>has-embed-expression</em>:</p>
     <dl>
      <dd data-md>
       <p>...</p>
      <dd data-md>
       <p><code class="highlight"><c- n>__has_embed</c-></code> <code class="highlight"><c- p>(</c-></code> <em>header-name-tokens</em> <em>embed-parameter-list</em><sub>opt</sub> <code class="highlight"><c- p>)</c-></code> <em>new-line</em></p>
     </dl>
    </ins>
   </blockquote>
   <blockquote>
    <div class="wording-section">
     <div class="wording-numbered">
      <p>
       … and it may contain zero or more 
       <del><em>defined-macro-expressions</em> and/or <em>has-include-expressions</em> and/or <em>has-attribute-expressions</em> as unary operator expressions</del>
       <ins><em>defined-macro-expressions</em>, <em>has-include-expressions</em>, <em>has-attribute-expressions</em>, and/or <em>has-embed-expressions</em> as unary operator expressions</ins>
       .
      </p>
     </div>
     <div> … </div>
     <ins>
      <div class="wording-numbered wording-numbered-5">
       <p>The <em>resource</em> identified by the parenthesized preprocessing token sequence in each contained <em>has-embed-expression</em> is searched for as if that preprocessing token sequence were the <em>pp-tokens</em> in a <code class="highlight"><c- cp># embed</c-></code> directive ([<a href="#cpp.res">cpp.res</a>]). If such a directive would not satisfy the syntactic requirements of a <code class="highlight"><c- cp># embed</c-></code> directive, the program is ill-formed. The <em>has-embed-expression</em> evaluates to:</p>
       <div class="wording-numbered-list">
        <ul>
         <li data-md>
          <p><code class="highlight"><c- mi>0</c-></code> if the search fails or any given <em>embed parameters</em> in the <em>embed-parameter-list</em> are not supported.</p>
         <li data-md>
          <p>Otherwise, <code class="highlight"><c- mi>1</c-></code> if the search for the <em>resource</em> succeeds, all the given <em>embed parameters</em> in the <em>embed-parameter-list</em> are supported, and the <em>resource</em> is not empty.</p>
         <li data-md>
          <p>Otherwise, <code class="highlight"><c- mi>2</c-></code> if the search for the <em>resource</em> succeeds, all the given <em>embed parameters</em> in the <em>embed-parameter-list</em> are supported, and the <em>resource</em> is empty.</p>
        </ul>
       </div>
      </div>
     </ins>
    </div>
   </blockquote>
   <h4 class="heading settled" data-level="7.3.4" id="wording-specification-cpp.res"><span class="secno">7.3.4. </span><span class="content">Add a new sub-clause §15.4 Resource inclusion [<strong>cpp.res</strong>]</span><a class="self-link" href="#wording-specification-cpp.res"></a></h4>
   <blockquote>
    <ins>
     <div class="wording-section">
      <div class="wording-section-header" id="cpp.res"> <span class="wording-clause-number">15.4</span> <span class="wording-clause-title">Resource inclusion</span> <span class="wording-clause-stable-tag">[<b>cpp.res</b>]</span> </div>
      <div class="wording-numbered">
       <p>An <code class="highlight"><c- cp>#embed</c-></code> directive shall identify a <em>resource</em> that can be processed into a comma-delimited list of integer literals. A <em>resource</em> is a source of data accessible from the translation environment. An <code class="highlight"><c- cp># embed</c-></code> directive can take an arbitrary number of <em>attribute</em> token sequences after the <em>q-char-sequence</em> or <em>h-char-sequence</em>, separated by white space. This is the <em>embed-parameter-list</em>, described in ([<a href="#cpp.res.param">cpp.res.param</a>]). An <em>embed-parameter</em> is a single attribute in the <em>embed-parameter-list</em>. It has an <em>implementation-resource-width</em>, which is the implementation-defined size in bits of the located resource. It also has a <em>resource-width</em>, which is:</p>
       <div class="wording-numbered-list">
        <ul>
         <li data-md>
          <p>the number of bits as computed from the optionally-provided <code class="highlight"><c- n>limit</c-></code> <em>embed-parameter</em> ([<a href="#cpp.res.param.limit">cpp.res.param.limit</a>]), if present.</p>
         <li data-md>
          <p>Otherwise, the <em>implementation-resource-width</em>.</p>
        </ul>
       </div>
      </div>
      <div class="wording-numbered">
       <p>Let <em>embed-element-width</em> be:</p>
       <div class="wording-numbered-list">
        <ul>
         <li data-md>
          <p>an integer constant expression greater than zero determined from an implementation-defined embed parameter, if present.</p>
         <li data-md>
          <p>Otherwise, <code class="highlight"><c- n>CHAR_BIT</c-></code>.</p>
        </ul>
       </div>
       <p>The result of <code class="highlight"><c- p>(</c-><c- n>resource</c-><c- o>-</c-><c- n>width</c-><c- p>)</c-> <c- o>%</c-> <c- p>(</c-><c- n>embed</c-><c- o>-</c-><c- n>element</c-><c- o>-</c-><c- n>width</c-><c- p>)</c-></code> shall be zero, otherwise the program is ill-formed.</p>
       <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-><c- p>[])</c-> <c- p>{</c->
	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>coeffs</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- c1>// ill-formed if the resource-width is 6 bits and</c->
<c- c1>// the embed-element-width is CHAR_BIT (which is, at minimum, 8 bits)</c->
<c- cp>#embed "6_bits.bin"</c->
	<c- p>};</c->

	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>fac</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- c1>// may be ill-formed:</c->
<c- c1>// (resource-width) % (embed-element-width)</c->
<c- c1>// may not be 0 on an implementation where the resource-width is 12</c->
<c- cp>#embed "12_bits.bin"</c->
	<c- p>};</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
       <p>– <em>end example</em>]</p>
      </div>
      <div class="wording-numbered">
        A preprocessing directive of the form 
       <dl>
        <dd data-md>
         <p><code class="highlight"><c- cp># embed &lt;</c-></code> <em>h-char-sequence</em> <code class="highlight"><c- o>></c-></code> <em>embed-parameter-list</em><sub>opt</sub> <em>new-line</em></p>
       </dl>
       <p>searches a sequence of implementation-defined places for a <em>resource</em> identified uniquely by the specified sequence between the <code class="highlight"><c- o>&lt;</c-></code> and <code class="highlight"><c- o>></c-></code> delimiters, and causes the replacement of that directive by a comma-delimited list of integer constant expressions as specified below. How the places are specified or the <em>resource</em> identified is implementation-defined. [ <em>Note</em>: A mechanism similar to, but distinct from, the implementation-defined search paths used for ([<a href="http://eel.is/c++draft/cpp.include">cpp.include</a>]) is encouraged. — <em>end Note</em> ]</p>
       <p></p>
      </div>
      <div class="wording-numbered">
       <p>A preprocessing directive of the form</p>
       <dl>
        <dd data-md>
         <p><code class="highlight"><c- cp># embed</c-></code> <code class="highlight"><c- s>"</c-></code> <em>q-char-sequence</em> <code class="highlight"><c- s>"</c-></code> <em>embed-parameter-list</em><sub>opt</sub> <em>new-line</em></p>
       </dl>
       <p>searches a sequence of implementation-defined places for a <em>resource</em> identified uniquely by the specified sequence between the <code class="highlight"><c- s>"</c-></code> and <code class="highlight"><c- s>"</c-></code> delimiters. How the places are identified for the <em>resource</em> identified is implementation-defined. [ Note: A mechanism similar to, but distinct from, the implementation-defined search paths used for ([<a href="http://eel.is/c++draft/cpp.include">cpp.include</a>]) is encouraged. — end Note ] If this search is not supported, or if the search fails, the directive is reprocessed as if it read</p>
       <dl>
        <dd data-md>
         <p><code class="highlight"><c- cp># embed</c-></code> <code class="highlight"><c- o>&lt;</c-></code> <em>h-char-sequence</em> <code class="highlight"><c- o>></c-></code> <em>embed-parameter-list</em><sub>opt</sub> <em>new-line</em></p>
       </dl>
       <p>with the identical contained sequence (including " characters, if any) from the original directive.</p>
      </div>
      <div class="wording-numbered">
       <p>Either form of the <code class="highlight"><c- cp># embed</c-></code> directive expands to a comma-separated list of integer literals, where each integer literal is <code class="highlight"><c- k>static_cast</c-></code> ([<a href="http://eel.is/c++draft/expr.static.cast">expr.static.cast</a>]) to <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code>. Each integer literal shall have an implementation-defined value between <code class="highlight"><c- mi>0</c-></code> and <code class="highlight"><c- mi>2</c-><c- o>^</c-><sup><c- n>embed</c-><c- o>-</c-><c- n>element</c-><c- o>-</c-><c- n>width</c-></sup><c- mi>-1</c-></code>, inclusive. If that list is used to initialize a contiguous sequence of <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code>, the elements of the sequence from the comma-separated list shall contain values as-if <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>fread</c-></code> ([<a href="http://eel.is/c++draft/library.c">library.c</a>]) from the <em>resource</em> as a file during program execution. [ <em>Note</em>: Each integer literal produced should closely represent the bit stream of the resource unmodified. This may require an implementation to consider potential differences between translation and execution environments, endianness, and any other applicable sources of mismatch. — <em>end note</em>]</p>
       <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;cstring>
<c- cp>#include</c-> &lt;cstddef>
<c- cp>#include</c-> &lt;fstream>
<c- cp>#include</c-> &lt;vector>

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>d</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed &lt;data.dat></c->
	<c- p>};</c->
	<c- k>const</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- b>unsigned</c-> <c- b>char</c-><c- o>></c-> <c- n>vec_d</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed &lt;data.dat></c->
	<c- p>};</c->

	<c- k>constexpr</c-> <c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>expected_size</c-> <c- o>=</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>d</c-><c- p>);</c->

	<c- c1>// same file in execution environment</c->
	<c- c1>// as was embedded</c->
	<c- n>std</c-><c- o>::</c-><c- n>ifstream</c-> <c- n>f_source</c-><c- p>(</c-><c- s>"data.dat"</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>ios</c-><c- o>::</c-><c- n>binary</c-> <c- o>|</c-> <c- n>std</c-><c- o>::</c-><c- n>ios</c-><c- o>::</c-><c- n>in</c-><c- p>);</c-> 
	<c- b>unsigned</c-> <c- b>char</c-> <c- n>runtime_d</c-><c- p>[</c-><c- n>expected_size</c-><c- p>];</c->
	<c- b>char</c-><c- o>*</c-> <c- n>ifstream_ptr</c-> <c- o>=</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- b>char</c-><c- o>*></c-><c- p>(</c-><c- n>runtime_d</c-><c- p>);</c->
	<c- k>if</c-> <c- p>(</c-><c- o>!</c-><c- n>f_source</c-><c- p>.</c-><c- n>read</c-><c- p>(</c-><c- n>ifstream_ptr</c-><c- p>,</c-> <c- n>expected_size</c-><c- p>))</c->
		<c- k>return</c-> <c- mi>1</c-><c- p>;</c->

	<c- n>std</c-><c- o>::</c-><c- b>size_t</c-> <c- n>ifstream_size</c-> <c- o>=</c-> <c- n>f_source</c-><c- p>.</c-><c- n>gcount</c-><c- p>();</c->
	<c- k>if</c-> <c- p>(</c-><c- n>ifstream_size</c-> <c- o>!=</c-> <c- n>expected_size</c-><c- p>)</c->
		<c- k>return</c-> <c- mi>2</c-><c- p>;</c->

	<c- b>int</c-> <c- n>is_same</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>memcmp</c-><c- p>(</c-><c- o>&amp;</c-><c- n>d</c-><c- p>[</c-><c- mi>0</c-><c- p>],</c-> <c- n>ifstream_ptr</c-><c- p>,</c-> <c- n>ifstream_size</c-><c- p>);</c->
	<c- k>if</c-> <c- p>(</c-><c- n>is_same</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c->
		<c- k>return</c-> <c- mi>3</c-><c- p>;</c->

	<c- b>int</c-> <c- n>is_same_vec</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>memcmp</c-><c- p>(</c-><c- n>vec_d</c-><c- p>.</c-><c- n>data</c-><c- p>(),</c-> <c- n>ifstream_ptr</c-><c- p>,</c-> <c- n>ifstream_size</c-><c- p>);</c->
	<c- k>if</c-> <c- p>(</c-><c- n>is_same_vec</c-> <c- o>!=</c-> <c- mi>0</c-><c- p>)</c->
		<c- k>return</c-> <c- mi>4</c-><c- p>;</c->

	<c- c1>// if the file is the same as the one in the translation environment,</c->
	<c- c1>// the program reaches this statement and returns 0</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
       <p>— <em>end example</em>]</p>
      </div>
      <div class="wording-numbered">
       <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;cstddef>

<c- b>void</c-> <c- nf>have_you_any_wool</c-><c- p>(</c-><c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-><c- o>*</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- b>size_t</c-><c- p>);</c->

<c- b>int</c-> <c- nf>main</c-> <c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-><c- p>[])</c-> <c- p>{</c->
	<c- k>constexpr</c-> <c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>baa_baa</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed "black_sheep.ico"</c->
	<c- p>};</c->

	<c- n>have_you_any_wool</c-><c- p>(</c-><c- n>baa_baa</c-><c- p>,</c-> <c- k>sizeof</c-><c- p>(</c-><c- n>baa_baa</c-><c- p>));</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
       – <em>end example</em>] 
      </div>
      <div class="wording-numbered">
       <p>A preprocessing directive of the form</p>
       <dl>
        <dd data-md>
         <p><code class="highlight"><c- cp>#</c-></code> <code class="highlight"><c- n>embed</c-></code> <em>pp-tokens</em> <em>new-line</em></p>
       </dl>
       <p>(that does not match one of the two previous forms) is permitted. The preprocessing tokens after <code class="highlight"><c- n>embed</c-></code> in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms [ Note: Adjacent string literals are not concatenated into a single string literal; thus, an expansion that results in two string literals is an invalid directive. — end Note ]. The method by which a sequence of preprocessing tokens between a <code class="highlight"><c- o>&lt;</c-></code> and a <code class="highlight"><c- o>></c-></code> preprocessing token pair or a pair of <code class="highlight"><c- s>"</c-></code> characters is combined into a single <em>resource</em> name preprocessing token is implementation-defined.</p>
       <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- cp>#define INT_DATA_H "i.dat"</c->

<c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
	<c- b>int</c-> <c- n>i</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed INT_DATA_H</c->
	<c- p>};</c-> <c- c1>// well-formed if i.dat produces 1 value</c->
	<c- k>struct</c-> <c- nc>s</c-> <c- p>{</c->
		<c- b>double</c-> <c- n>a</c-><c- p>,</c-> <c- n>b</c-><c- p>,</c-> <c- n>c</c-><c- p>;</c->
		<c- k>struct</c-> <c- p>{</c-> <c- b>double</c-> <c- n>e</c-><c- p>,</c-> <c- n>f</c-><c- p>,</c-> <c- n>g</c-><c- p>;</c-> <c- p>};</c->
		<c- b>double</c-> <c- n>h</c-><c- p>,</c-> <c- n>i</c-><c- p>,</c-> <c- n>j</c-><c- p>;</c->
	<c- p>};</c->
	<c- n>s</c-> <c- n>x</c-> <c- o>=</c-> <c- p>{</c->
	<c- c1>// well-formed, initializes each element in</c->
	<c- c1>// order according to initialization rules for a</c->
	<c- c1>// brace-delimited, comma-separated list</c->
<c- cp>#embed "s.dat"</c->
	<c- p>};</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
       – <em>end example</em>] 
      </div>
     </div>
    </ins>
   </blockquote>
   <h4 class="heading settled" data-level="7.3.5" id="wording-specification-cpp.res.param"><span class="secno">7.3.5. </span><span class="content">Add a new sub-clause §15.4.1 under Resource Inclusion for Embed parameters [<strong>cpp.res.param</strong>]</span><a class="self-link" href="#wording-specification-cpp.res.param"></a></h4>
   <blockquote>
    <ins>
     <div class="wording-section" id="cpp.res.param">
      <div class="wording-section">
       <div class="wording-clause-header"> <span class="wording-clause-number">15.4.1</span> <span class="wording-clause-title">Embed parameters</span> <span class="wording-clause-stable-tag">[<b>cpp.res.param</b>]</span> </div>
       <div class="wording-numbered">
        <p>The <em>embed-parameter-list</em> contain <em>attributes</em> which may modify the result of the replacement for the <code class="highlight"><c- cp># embed</c-></code> preprocessing directive. The <em>attribute-tokens</em> defined below are <code class="highlight"><c- n>limit</c-></code>, <code class="highlight"><c- n>is_empty</c-></code>, <code class="highlight"><c- n>prefix</c-></code>, and <code class="highlight"><c- n>suffix</c-></code>.</p>
       </div>
       <div class="wording-numbered">
        <p>For an <em>attribute-token</em> (including an <em>attribute-scoped-token</em>) not specified in this clause, the behavior is implementation-defined. Tokens reserved as <em>embed-parameter-list</em> for future revisions of this document and implementations are the same as described for attribute as in ([<a href="http://eel.is/c++draft/dcl.attr.grammar">dcl.attr.grammar</a>]).</p>
       </div>
      </div>
      <div class="wording-section" id="cpp.res.param.limit">
       <div class="wording-section-header"> <span class="wording-clause-number">15.4.1.1</span> <span class="wording-clause-title"><code class="highlight"><c- n>limit</c-></code> parameter</span> <span class="wording-clause-stable-tag">[<b>cpp.res.param.limit</b>]</span> </div>
       <div class="wording-numbered">
        <p>The <em>attribute-token</em> <code class="highlight"><c- n>limit</c-></code> denotes a maximum number of elements that may be produced in the comma delimited list. It may appear zero, one, or multiple times in the <em>embed-parameter-list</em>. The most recent <code class="highlight"><c- n>limit</c-></code> <em>embed-parameter</em> in lexical order applies and the others are ignored. Its <em>attribute-argument-clause</em> shall be present and have the form:</p>
        <dl>
         <dd data-md>
          <p><code class="highlight"><c- p>(</c-></code> <em>constant-expression</em> <code class="highlight"><c- p>)</c-></code></p>
        </dl>
       </div>
       <div class="wording-numbered">
        <p>Its <em>attribute-argument-clause</em> shall be an integral constant expression greater than zero after evaluation, and be processed as described in conditional inclusion ([<a href="http://eel.is/c++draft/cpp.cond">cpp.cond</a>]). If the token <code class="highlight"><c- n>defined</c-></code> appears in the <em>attribute-argument-clause</em> the program is ill-formed. There shall be at least one processing of the <em>attribute-argument-clause</em> tokens just as in normal text.</p>
       </div>
       <div class="wording-numbered">
        <p>The resource width is:</p>
        <div class="wording-numbered-list">
         <ul>
          <li data-md>
           <p><code class="highlight"><c- mi>0</c-></code>, if the integer constant expression evaluates to <code class="highlight"><c- mi>0</c-></code>.</p>
          <li data-md>
           <p>Otherwise, the <em>implementation-resource-width</em>, if it is less than the <em>embed-element-width</em> multiplied by the integer constant expression.</p>
          <li data-md>
           <p>Otherwise, the <em>embed-element-width</em> multiplied by the integer constant expression, if it is less than or equal to the <em>implementation-resource-width</em>.</p>
         </ul>
        </div>
        <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;cassert>

<c- b>int</c-> <c- nf>main</c-> <c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-><c- p>[])</c-> <c- p>{</c->
	<c- k>constexpr</c-> <c- k>const</c-> <c- b>char</c-> <c- n>sound_signature</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed &lt;sdk/jump.wav> limit(2+2)</c->
	<c- p>};</c->

	<c- c1>// verify PCM WAV resource</c->
	<c- n>assert</c-><c- p>(</c-><c- n>sound_signature</c-><c- p>[</c-><c- mi>0</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'R'</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>sound_signature</c-><c- p>[</c-><c- mi>1</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'I'</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>sound_signature</c-><c- p>[</c-><c- mi>2</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'F'</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>sound_signature</c-><c- p>[</c-><c- mi>3</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'F'</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- k>sizeof</c-><c- p>(</c-><c- n>sound_signature</c-><c- p>)</c-> <c- o>==</c-> <c- mi>4</c-><c- p>);</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
        – <em>end example</em>] 
        <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>(</c-><c- b>int</c-><c- p>,</c-> <c- b>char</c-><c- o>*</c-><c- p>[])</c-> <c- p>{</c->
	<c- k>const</c-> <c- b>unsigned</c-> <c- b>char</c-> <c- n>scal</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- c1>// may be ill-formed: if resource-width is greater than 24,</c->
<c- c1>// or if ((resource-width * 1) % 24) is not equivalent to 0</c->
<c- cp>#embed "24_bits.bin" limit(1)</c->
	<c- p>};</c->

	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
        – <em>end example</em>] 
       </div>
      </div>
      <div class="wording-section" id="cpp.res.param.prefix">
       <div class="wording-section-header"> <span class="wording-clause-number">15.4.1.2</span> <span class="wording-clause-title"><code class="highlight"><c- n>prefix</c-></code> parameter</span> <span class="wording-clause-stable-tag">[<b>cpp.res.param.prefix</b>]</span> </div>
       <div class="wording-numbered">
        <p>The <em>attribute-token</em> <code class="highlight"><c- n>prefix</c-></code> denotes a maximum number of elements that may be produced in the comma delimited list. It may appear zero, one, or multiple times in the <em>embed-parameter-list</em>. The most recent <code class="highlight"><c- n>prefix</c-></code> <em>embed-parameter</em> in lexical order applies and the others are ignored. Its <em>attribute-argument-clause</em> shall be present and have the form:</p>
        <dl>
         <dd data-md>
          <p><code class="highlight"><c- p>(</c-></code> <em>pp-tokens</em><sub>opt</sub> <code class="highlight"><c- p>)</c-></code></p>
        </dl>
       </div>
       <div class="wording-numbered">
        <p>If the <em>resource</em> is empty, this <em>embed-parameter</em> is ignored. Otherwise, any <em>pp-tokens</em> specified shall be placed immediately before the expansion of the <code class="highlight"><c- cp># embed</c-></code> directive.</p>
       </div>
      </div>
      <div class="wording-section" id="cpp.res.param.suffix">
       <div class="wording-section-header"> <span class="wording-clause-number">15.4.1.3</span> <span class="clause-title"><code class="highlight"><c- n>suffix</c-></code> parameter</span> <span class="stable-tag">[<b>cpp.res.param.suffix</b>]</span> </div>
       <div class="wording-numbered">
        <p>The <em>attribute-token</em> <code class="highlight"><c- n>suffix</c-></code> denotes a maximum number of elements that may be produced in the comma delimited list. It may appear zero, one, or multiple times in the <em>embed-parameter-list</em>. The most recent <code class="highlight"><c- n>suffix</c-></code> <em>embed-parameter</em> in lexical order applies and the others are ignored. Its <em>attribute-argument-clause</em> shall be present and have the form:</p>
        <dl>
         <dd data-md>
          <p><code class="highlight"><c- p>(</c-></code> <em>pp-token</em><sub>opt</sub> <code class="highlight"><c- p>)</c-></code></p>
        </dl>
       </div>
       <div class="wording-numbered">
        <p>If the <em>resource</em> is empty, this <em>embed-parameter</em> is ignored. Otherwise, any <em>pp-tokens</em> specified shall be placed directly after the expansion of the <code class="highlight"><c- cp># embed</c-></code> directive.</p>
        <p>[ <em>Example</em>:</p>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;cstring>
<c- cp>#include</c-> &lt;cassert>

<c- cp>#ifndef SHADER_TARGET</c->
<c- cp>#define SHADER_TARGET "ches.glsl"</c->
<c- cp>#endif</c->

<c- k>extern</c-> <c- b>char</c-><c- o>*</c-> <c- n>merp</c-><c- p>;</c->

<c- b>void</c-> <c- nf>init_data</c-> <c- p>()</c-> <c- p>{</c->
	<c- k>constexpr</c-> <c- k>const</c-> <c- b>char</c-> <c- n>whl</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed SHADER_TARGET \</c->
<c- cp>		prefix(0xEF, 0xBB, 0xBF, ) </c-><c- d>/* UTF-8 BOM */</c-><c- cp> \</c->
<c- cp>		suffix(,)</c->
		<c- mi>0</c->
	<c- p>};</c->
	<c- c1>// always null terminated,</c->
	<c- c1>// contains BOM if not-empty</c->
	<c- b>bool</c-> <c- n>is_good</c-> <c- o>=</c-> <c- p>(</c-><c- k>sizeof</c-><c- p>(</c-><c- n>whl</c-><c- p>)</c-> <c- o>==</c-> <c- mi>1</c-> <c- o>&amp;&amp;</c-> <c- n>whl</c-><c- p>[</c-><c- mi>0</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'\0'</c-><c- p>)</c->
	<c- o>||</c-> <c- p>(</c-><c- n>whl</c-><c- p>[</c-><c- mi>0</c-><c- p>]</c-> <c- o>==</c-> '<c- mh>0xEF</c->' <c- o>&amp;&amp;</c-> <c- n>whl</c-><c- p>[</c-><c- mi>1</c-><c- p>]</c-> <c- o>==</c-> '<c- mh>0xBB</c->'
	    <c- o>&amp;&amp;</c-> <c- n>whl</c-><c- p>[</c-><c- mi>2</c-><c- p>]</c-> <c- o>==</c-> '<c- mh>0xBF</c->' <c- o>&amp;&amp;</c-> <c- n>whl</c-><c- p>[</c-><c- k>sizeof</c-><c- p>(</c-><c- n>whl</c-><c- p>)</c-> <c- o>-</c-> <c- mi>1</c-><c- p>]</c-> <c- o>==</c-> <c- sc>'\0'</c-><c- p>);</c->
	<c- n>assert</c-><c- p>(</c-><c- n>is_good</c-><c- p>);</c->
	<c- n>std</c-><c- o>::</c-><c- n>strcpy</c-><c- p>(</c-><c- n>merp</c-><c- p>,</c-> <c- n>whl</c-><c- p>);</c->
<c- p>}</c->
</pre>
        – <em>end example</em>] 
       </div>
      </div>
      <div class="wording-section" id="cpp.res.param.empty">
       <div class="wording-section-header"> <span class="wording-clause-number">15.4.1.3</span> <span class="wording-clause-title"><code class="highlight"><c- n>is_empty</c-></code> parameter</span> <span class="wording-clause-stable-tag">[<b>cpp.res.param.empty</b>]</span> </div>
       <div class="wording-numbered">
        <p>The <em>attribute-token</em> <code class="highlight"><c- n>is_empty</c-></code> denotes a sequence of tokens to use if the <em>resource</em> is empty. It may appear zero, one, or multiple times in the <em>embed-parameter-list</em>. The most recent <code class="highlight"><c- n>is_empty</c-></code> <em>embed-parameter</em> in lexical order applies and the others are ignored. Its <em>attribute-argument-clause</em> shall be present and have the form:</p>
        <dl>
         <dd data-md>
          <p><code class="highlight"><c- p>(</c-></code> <em>pp-tokens</em><sub>opt</sub> <code class="highlight"><c- p>)</c-></code></p>
        </dl>
       </div>
       <div class="wording-numbered">
        <p>If the <em>resource</em> is not empty, this <em>embed-parameter</em> is ignored. Otherwise, any <em>pp-tokens</em> specified shall be placed where the embed directive is.</p>
        <p>[ <em>Example</em>: If the file is empty, then this</p>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- k>const</c-> <c- b>char</c-> <c- n>x</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
<c- cp>#embed "empty_file.dat" \</c->
<c- cp>	is_empty((char)-1)</c->
<c- p>};</c->
</pre>
        <p>expands to</p>
<pre class="language-cpp highlight"><c- k>constexpr</c-> <c- k>const</c-> <c- b>char</c-> <c- n>x</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
	<c- p>(</c-><c- b>char</c-><c- p>)</c-><c- mi>-1</c->
<c- p>};</c->
</pre>
        <p>Otherwise, it expands to the contents of the file. – <em>end example</em>]</p>
        <p>[ <em>Example</em>: This resource is considered empty due to the <code class="highlight"><c- n>limit</c-><c- p>(</c-><c- mi>0</c-><c- p>)</c-></code> <em>embed-parameter</em>, always, including in <code class="highlight"><c- n>__has_embed</c-></code> clauses.</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>main</c-> <c- p>()</c-> <c- p>{</c->
<c- cp>#if __has_embed(&lt;/owo/uwurandom> limit(0) prefix(some tokens)) == 2</c->
	<c- c1>// if &lt;/owo/uwurandom> exits, this</c->
	<c- c1>// conditional inclusion branch is taken and the program</c->
	<c- c1>// returns 0.</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- cp>#else</c->
	<c- c1>// the resource does not exist</c->
	<c- cp>#error "The resource does not exist"</c->
<c- cp>#endif</c->
<c- p>}</c->
</pre>
        <p>– <em>end example</em>]</p>
       </div>
      </div>
     </div>
    </ins>
   </blockquote>
   <h2 class="heading settled" data-level="8" id="acknowledgements"><span class="secno">8. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Thank you to Alex Gilding for bolstering this proposal with additional ideas and motivation. Thank you to Aaron Ballman, David Keaton, and Rajan Bhakta for early feedback on this proposal. Thank you to the <a href="https://www.includecpp.org/"><code class="highlight"><c- cp>#include</c->&lt;C++></code></a> for bouncing lots of ideas off the idea in their Discord. Thank you to Hubert Tong for refining the proposal’s implementation-defined extension points.</p>
   <p>Thank you to the Lounge&lt;C++> for their continued support, and to rmf for the valuable early implementation feedback.</p>
   <div class="pagebreak"></div>
   <h2 class="heading settled" data-level="9" id="appendix"><span class="secno">9. </span><span class="content">Appendix</span><a class="self-link" href="#appendix"></a></h2>
   <h3 class="heading settled" data-level="9.1" id="appendix-existing"><span class="secno">9.1. </span><span class="content">Existing Tools</span><a class="self-link" href="#appendix-existing"></a></h3>
   <p>This section categorizes some of the platform-specific techniques used to work with C++ and some of the challenges they face. Other techniques used include pre-processing data, link-time based tooling, and assembly-time runtime loading. They are detailed below, for a complete picture of today’s landscape of options. They include both C and C++ options.</p>
   <h4 class="heading settled" data-level="9.1.1" id="appendix-existing-pre_processing_tools"><span class="secno">9.1.1. </span><span class="content">Pre-Processing Tools</span><a class="self-link" href="#appendix-existing-pre_processing_tools"></a></h4>
   <ol>
    <li data-md>
     <p>Run the tool over the data (<code class="highlight"><c- n>xxd</c-> <c- o>-</c-><c- n>i</c-> <c- n>xxd_data</c-><c- p>.</c-><c- n>bin</c-> <c- o>></c-> <c- n>xxd_data</c-><c- p>.</c-><c- n>h</c-></code>) to obtain the generated file (<code class="highlight"><c- n>xxd_data</c-><c- p>.</c-><c- n>h</c-></code>) and add a null terminator if necessary:</p>
   </ol>
<pre class="language-cpp highlight"><c- b>unsigned</c-> <c- b>char</c-> <c- n>xxd_data_bin</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
	<c- mh>0x48</c-><c- p>,</c-> <c- mh>0x65</c-><c- p>,</c-> <c- mh>0x6c</c-><c- p>,</c-> <c- mh>0x6c</c-><c- p>,</c-> <c- mh>0x6f</c-><c- p>,</c-> <c- mh>0x2c</c-><c- p>,</c-> <c- mh>0x20</c-><c- p>,</c-> <c- mh>0x57</c-><c- p>,</c-> <c- mh>0x6f</c-><c- p>,</c-> <c- mh>0x72</c-><c- p>,</c-> <c- mh>0x6c</c-><c- p>,</c-> <c- mh>0x64</c-><c- p>,</c->
	<c- mh>0x0a</c-><c- p>,</c-> <c- mh>0x00</c->
<c- p>};</c->
<c- b>unsigned</c-> <c- b>int</c-> <c- n>xxd_data_bin_len</c-> <c- o>=</c-> <c- mi>13</c-><c- p>;</c->
</pre>
   <ol start="2">
    <li data-md>
     <p>Compile <code class="highlight"><c- n>main</c-><c- p>.</c-><c- n>c</c-></code>:</p>
   </ol>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;stdlib.h>
<c- cp>#include</c-> &lt;stdio.h>

<c- c1>// prefix as const,</c->
<c- c1>// even if it generates some warnings in g++/clang++</c->
<c- k>const</c->
<c- cp>#include</c-> "xxd_data.h"

<c- b>int</c-> <c- n>main</c-><c- p>()</c-> <c- p>{</c->
		<c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- n>data</c-> <c- o>=</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>char</c-><c- o>*></c-><c- p>(</c-><c- n>xxd_data_bin</c-><c- p>);</c->
		<c- n>puts</c-><c- p>(</c-><c- n>data</c-><c- p>);</c-> <c- c1>// Hello, World!</c->
		<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>Others still use python or other small scripting languages as part of their build process, outputting data in the exact C++ format that they require.</p>
   <p>There are problems with the <code class="highlight"><c- n>xxd</c-> <c- o>-</c-><c- n>i</c-></code> or similar tool-based approach. Tokenization and Parsing data-as-source-code adds an enormous overhead to actually reading and making that data available.</p>
   <p>Binary data as C(++) arrays provide the overhead of having to comma-delimit every single byte present, it also requires that the compiler verify every entry in that array is a valid literal or entry according to the C++ language.</p>
   <p>This scales poorly with larger files, and build times suffer for any non-trivial binary file, especially when it scales into Megabytes in size (e.g., firmware and similar).</p>
   <h4 class="heading settled" data-level="9.1.2" id="appendix-existing-python"><span class="secno">9.1.2. </span><span class="content"><code class="highlight"><c- n>python</c-></code></span><a class="self-link" href="#appendix-existing-python"></a></h4>
   <p>Other companies are forced to create their own ad-hoc tools to embed data and files into their C++ code. MongoDB uses a <a href="https://github.com/mongodb/mongo/blob/master/site_scons/site_tools/jstoh.py">custom python script</a>, just to format their data for compiler consumption:</p>
<pre class="language-python highlight"><c- kn>import</c-> <c- nn>os</c->
<c- kn>import</c-> <c- nn>sys</c->

<c- k>def</c-> <c- nf>jsToHeader</c-><c- p>(</c-><c- n>target</c-><c- p>,</c-> <c- n>source</c-><c- p>):</c->
		<c- n>outFile</c-> <c- o>=</c-> <c- n>target</c->
		<c- n>h</c-> <c- o>=</c-> <c- p>[</c->
				<c- t>'#include "mongo/base/string_data.h"'</c-><c- p>,</c->
				<c- t>'#include "mongo/scripting/engine.h"'</c-><c- p>,</c->
				<c- t>'namespace mongo {'</c-><c- p>,</c->
				<c- t>'namespace JSFiles{'</c-><c- p>,</c->
		<c- p>]</c->
		<c- k>def</c-> <c- nf>lineToChars</c-><c- p>(</c-><c- n>s</c-><c- p>):</c->
				<c- k>return</c-> <c- t>','</c-><c- o>.</c-><c- n>join</c-><c- p>(</c->str<c- p>(</c->ord<c- p>(</c-><c- n>c</c-><c- p>))</c-> <c- k>for</c-> <c- n>c</c-> <c- ow>in</c-> <c- p>(</c-><c- n>s</c-><c- o>.</c-><c- n>rstrip</c-><c- p>()</c-> <c- o>+</c-> <c- t>'</c-><c- se>\n</c-><c- t>'</c-><c- p>))</c-> <c- o>+</c-> <c- t>','</c->
		<c- k>for</c-> <c- n>s</c-> <c- ow>in</c-> <c- n>source</c-><c- p>:</c->
				<c- n>filename</c-> <c- o>=</c-> str<c- p>(</c-><c- n>s</c-><c- p>)</c->
				<c- n>objname</c-> <c- o>=</c-> <c- n>os</c-><c- o>.</c-><c- n>path</c-><c- o>.</c-><c- n>split</c-><c- p>(</c-><c- n>filename</c-><c- p>)[</c-><c- mi>1</c-><c- p>]</c-><c- o>.</c-><c- n>split</c-><c- p>(</c-><c- t>'.'</c-><c- p>)[</c-><c- mi>0</c-><c- p>]</c->
				<c- n>stringname</c-> <c- o>=</c-> <c- t>'_jscode_raw_'</c-> <c- o>+</c-> <c- n>objname</c->

				<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- t>'constexpr char '</c-> <c- o>+</c-> <c- n>stringname</c-> <c- o>+</c-> <c- u>"[] = {"</c-><c- p>)</c->

				<c- k>with</c-> open<c- p>(</c-><c- n>filename</c-><c- p>,</c-> <c- t>'r'</c-><c- p>)</c-> <c- k>as</c-> <c- n>f</c-><c- p>:</c->
						<c- k>for</c-> <c- n>line</c-> <c- ow>in</c-> <c- n>f</c-><c- p>:</c->
								<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- n>lineToChars</c-><c- p>(</c-><c- n>line</c-><c- p>))</c->

				<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- u>"0};"</c-><c- p>)</c->
				<c- c1># symbols aren’t exported w/o this</c->
				<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- t>'extern const JSFile </c-><c- si>%s</c-><c- t>;'</c-> <c- o>%</c-> <c- n>objname</c-><c- p>)</c->
				<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- t>'const JSFile </c-><c- si>%s</c-><c- t> = { "</c-><c- si>%s</c-><c- t>", StringData(</c-><c- si>%s</c-><c- t>, sizeof(</c-><c- si>%s</c-><c- t>) - 1) };'</c-> <c- o>%</c->
								 <c- p>(</c-><c- n>objname</c-><c- p>,</c-> <c- n>filename</c-><c- o>.</c-><c- n>replace</c-><c- p>(</c-><c- t>'</c-><c- se>\\</c-><c- t>'</c-><c- p>,</c-> <c- t>'/'</c-><c- p>),</c-> <c- n>stringname</c-><c- p>,</c-> <c- n>stringname</c-><c- p>))</c->

		<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- u>"} // namespace JSFiles"</c-><c- p>)</c->
		<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- u>"} // namespace mongo"</c-><c- p>)</c->
		<c- n>h</c-><c- o>.</c-><c- n>append</c-><c- p>(</c-><c- u>""</c-><c- p>)</c->

		<c- n>text</c-> <c- o>=</c-> <c- t>'</c-><c- se>\n</c-><c- t>'</c-><c- o>.</c-><c- n>join</c-><c- p>(</c-><c- n>h</c-><c- p>)</c->

		<c- k>with</c-> open<c- p>(</c-><c- n>outFile</c-><c- p>,</c-> <c- t>'wb'</c-><c- p>)</c-> <c- k>as</c-> <c- n>out</c-><c- p>:</c->
				<c- k>try</c-><c- p>:</c->
						<c- n>out</c-><c- o>.</c-><c- n>write</c-><c- p>(</c-><c- n>text</c-><c- p>)</c->
				<c- k>finally</c-><c- p>:</c->
						<c- n>out</c-><c- o>.</c-><c- n>close</c-><c- p>()</c->


<c- k>if</c-> __name__ <c- o>==</c-> <c- u>"__main__"</c-><c- p>:</c->
		<c- k>if</c-> len<c- p>(</c-><c- n>sys</c-><c- o>.</c-><c- n>argv</c-><c- p>)</c-> <c- o>&lt;</c-> <c- mi>3</c-><c- p>:</c->
				print <c- u>"Must specify [target] [source] "</c->
				<c- n>sys</c-><c- o>.</c-><c- n>exit</c-><c- p>(</c-><c- mi>1</c-><c- p>)</c->
		<c- n>jsToHeader</c-><c- p>(</c-><c- n>sys</c-><c- o>.</c-><c- n>argv</c-><c- p>[</c-><c- mi>1</c-><c- p>],</c-> <c- n>sys</c-><c- o>.</c-><c- n>argv</c-><c- p>[</c-><c- mi>2</c-><c- p>:])</c->
</pre>
   <p>MongoDB were brave enough to share their code with me and make public the things they have to do: other companies have shared many similar concerns, but do not have the same bravery. We thank MongoDB for sharing.</p>
   <h4 class="heading settled" data-level="9.1.3" id="appendix-existing-ld"><span class="secno">9.1.3. </span><span class="content"><code class="highlight"><c- n>ld</c-></code></span><a class="self-link" href="#appendix-existing-ld"></a></h4>
   <p>A complete example (does not compile on Visual C++):</p>
   <ol>
    <li data-md>
     <p>Have a file ld_data.bin with the contents <code class="highlight"><c- n>Hello</c-><c- p>,</c-> <c- n>World</c-><c- o>!</c-></code>.</p>
    <li data-md>
     <p>Run <code class="highlight"><c- n>ld</c-> <c- o>-</c-><c- n>r</c-> <c- n>binary</c-> <c- o>-</c-><c- n>o</c-> <c- n>ld_data</c-><c- p>.</c-><c- n>o</c-> <c- n>ld_data</c-><c- p>.</c-><c- n>bin</c-></code>.</p>
    <li data-md>
     <p>Compile the following <code class="highlight"><c- n>main</c-><c- p>.</c-><c- n>cpp</c-></code> with <code class="highlight"><c- n>gcc</c-> <c- o>-</c-><c- n>std</c-><c- o>=</c-><c- n>c</c-><c- o>++</c-><c- mi>17</c-> <c- n>ld_data</c-><c- p>.</c-><c- n>o</c-> <c- n>main</c-><c- p>.</c-><c- n>cpp</c-></code>:</p>
   </ol>
<pre class="language-cpp highlight"><c- cp>#include</c-> &lt;stdlib.h>
<c- cp>#include</c-> &lt;stdio.h>

<c- cp>#define STRINGIZE_(x) #x</c->
<c- cp>#define STRINGIZE(x) STRINGIZE_(x)</c->

<c- cp>#ifdef __APPLE__</c->
<c- cp>#include</c-> &lt;mach-o/getsect.h>

<c- cp>#define DECLARE_LD_(LNAME) extern const unsigned char _section$__DATA__##LNAME[];</c->
<c- cp>#define LD_NAME_(LNAME) _section$__DATA__##LNAME</c->
<c- cp>#define LD_SIZE_(LNAME) (getsectbyLNAME("__DATA", "__" STRINGIZE(LNAME))->size)</c->
<c- cp>#define DECLARE_LD(LNAME) DECLARE_LD_(LNAME)</c->
<c- cp>#define LD_NAME(LNAME) LD_NAME_(LNAME)</c->
<c- cp>#define LD_SIZE(LNAME) LD_SIZE_(LNAME)</c->

<c- cp>#elif (defined __MINGW32__) </c-><c- d>/* mingw */</c->

<c- cp>#define DECLARE_LD(LNAME)                                 \</c->
<c- cp>	extern const unsigned char binary_##LNAME##_start[];    \</c->
<c- cp>	extern const unsigned char binary_##LNAME##_end[];</c->
<c- cp>#define LD_NAME(LNAME) binary_##LNAME##_start</c->
<c- cp>#define LD_SIZE(LNAME) ((binary_##LNAME##_end) - (binary_##LNAME##_start))</c->
<c- cp>#define DECLARE_LD(LNAME) DECLARE_LD_(LNAME)</c->
<c- cp>#define LD_NAME(LNAME) LD_NAME_(LNAME)</c->
<c- cp>#define LD_SIZE(LNAME) LD_SIZE_(LNAME)</c->

<c- cp>#else </c-><c- d>/* gnu/linux ld */</c->

<c- cp>#define DECLARE_LD_(LNAME)                                  \</c->
<c- cp>	extern const unsigned char _binary_##LNAME##_start[];     \</c->
<c- cp>	extern const unsigned char _binary_##LNAME##_end[];</c->
<c- cp>#define LD_NAME_(LNAME) _binary_##LNAME##_start</c->
<c- cp>#define LD_SIZE_(LNAME) ((_binary_##LNAME##_end) - (_binary_##LNAME##_start))</c->
<c- cp>#define DECLARE_LD(LNAME) DECLARE_LD_(LNAME)</c->
<c- cp>#define LD_NAME(LNAME) LD_NAME_(LNAME)</c->
<c- cp>#define LD_SIZE(LNAME) LD_SIZE_(LNAME)</c->
<c- cp>#endif</c->

<c- n>DECLARE_LD</c-><c- p>(</c-><c- n>ld_data_bin</c-><c- p>);</c->

<c- b>int</c-> <c- nf>main</c-><c- p>()</c-> <c- p>{</c->
	<c- k>const</c-> <c- b>char</c-><c- o>*</c-> <c- n>p_data</c-> <c- o>=</c-> <c- k>reinterpret_cast</c-><c- o>&lt;</c-><c- k>const</c-> <c- b>char</c-><c- o>*></c-><c- p>(</c-><c- n>LD_NAME</c-><c- p>(</c-><c- n>ld_data_bin</c-><c- p>));</c->
	<c- c1>// impossible, not null-terminated</c->
	<c- c1>//puts(p_data);</c->
	<c- c1>// must copy instead</c->
	<c- k>return</c-> <c- mi>0</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <p>This scales a little bit better in terms of raw compilation time but is shockingly OS, vendor and platform specific in ways that novice developers would not be able to handle fully. The macros are required to erase differences, lest subtle differences in name will destroy one’s ability to use these macros effectively. We omitted the code for handling VC++ resource files because it is excessively verbose than what is present here.</p>
   <p>N.B.: Because these declarations are <code class="highlight"><c- k>extern</c-></code>, the values in the array cannot be accessed at compilation/translation-time.</p>
   <h4 class="heading settled" data-level="9.1.4" id="appendix-existing-incbin"><span class="secno">9.1.4. </span><span class="content"><code class="highlight"><c- n>incbin</c-></code></span><a class="self-link" href="#appendix-existing-incbin"></a></h4>
   <p>There is a tool called <a href="https://github.com/graphitemaster/incbin"><code class="highlight"><c- n>incbin</c-></code></a> which is a 3rd party attempt at pulling files in at "assembly time". Its approach is incredibly similar to <code class="highlight"><c- n>ld</c-></code>, with the caveat that files must be shipped with their binary. It unfortunately falls prey to the same problems of cross-platform woes when dealing with Visual C, requiring additional pre-processing to work out in full.</p>
   <h4 class="heading settled" data-level="9.1.5" id="appendix-existing-external.xxd"><span class="secno">9.1.5. </span><span class="content"><code class="highlight"><c- n>xxd</c-></code>, but done Raw</span><a class="self-link" href="#appendix-existing-external.xxd"></a></h4>
   <p>Some people cannot even use the <code class="highlight"><c- n>xxd</c-></code> tool on their platforms because it cannot be used. This is the case where tools need to be able to package things, and therefore their build tools need to accommodate for not having their information. The way to help save for this is to create other small utilities that effectively <a href="https://github.com/Smattr/rumur/blob/main/misc/xxd.py">duplicate the tools, but in different ways</a>.</p>
   <p>This has affected packaging of Debian-style packages on multiple distributions.</p>
   <h3 class="heading settled" data-level="9.2" id="appendix-existing-type_flexibility"><span class="secno">9.2. </span><span class="content">Type Flexibility</span><a class="self-link" href="#appendix-existing-type_flexibility"></a></h3>
   <p><strong>Note:</strong> As per the vote in the September C++ Evolution Working Group Meeting, Type Flexibility is not being pursued in the preprocessor for various implementation and support splitting concerns.</p>
   <p>A type can be specified after the <code class="highlight"><c- cp>#embed</c-></code> to view the data in a very specific manner. This allows data to initialized as exactly that type.</p>
   <p>Type flexibility was not pursued for various implementation concerns. Chief among them was single-purpose preprocessors that did not have access to frontend information. This meant it was very hard to make a system that was both preprocessor conformant but did not require e.g. <code class="highlight"><c- k>sizeof</c-><c- p>(...)</c-></code> information at the point of preprocessor invocation. Therefore, the type flexibility feature was pulled from <code class="highlight"><c- cp>#embed</c-></code> and will be conglomerated in other additions such as <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>bitcast</c-></code> or <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>embed</c-></code>.</p>
<pre class="language-cpp highlight"><c- d>/* specify a type-name to change array type */</c->
<c- k>const</c-> <c- b>int</c-> <c- n>shorten_flac</c-><c- p>[]</c-> <c- o>=</c-> <c- p>{</c->
		<c- cp>#embed int "stripped_music.flac"</c->
<c- p>};</c->
</pre>
   <p>The contents of the resource are mapped in an implementation-defined manner to the data, such that it will use <code class="highlight"><c- k>sizeof</c-><c- p>(</c-><c- n>type</c-><c- o>-</c-><c- n>name</c-><c- p>)</c-> <c- o>*</c-> <c- n>CHAR_BIT</c-></code> bits for each element. If the file does not have enough bits to fill out a multiple of <code class="highlight"><c- k>sizeof</c-><c- p>(</c-><c- n>type</c-><c- o>-</c-><c- n>name</c-><c- p>)</c-> <c- o>*</c-> <c- n>CHAR_BIT</c-></code> bits, then a diagnostic is required. Furthermore, we require that the type passed to <code class="highlight"><c- cp>#embed</c-></code> that must one of the following fundamental types, signed or unsigned, spelled exactly in this manner:</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- b>char</c-></code>, <code class="highlight"><c- b>unsigned</c-> <c- b>char</c-></code>, <code class="highlight"><c- b>signed</c-> <c- b>char</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- b>short</c-></code>, <code class="highlight"><c- b>unsigned</c-> <c- b>short</c-></code>, <code class="highlight"><c- b>signed</c-> <c- b>short</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- b>int</c-></code>, <code class="highlight"><c- b>unsigned</c-> <c- b>int</c-></code>, <code class="highlight"><c- b>signed</c-> <c- b>int</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- b>long</c-></code>, <code class="highlight"><c- b>unsigned</c-> <c- b>long</c-></code>, <code class="highlight"><c- b>signed</c-> <c- b>long</c-></code></p>
    <li data-md>
     <p><code class="highlight"><c- b>long</c-> <c- b>long</c-></code>, <code class="highlight"><c- b>unsigned</c-> <c- b>long</c-> <c- b>long</c-></code>, <code class="highlight"><c- b>signed</c-> <c- b>long</c-> <c- b>long</c-></code></p>
   </ul>
   <p>More types can be supported by the implementation if the implementation so chooses (both the GCC and Clang prototypes described below support more than this). The reason exactly these types are required is because these are the only types for which there is a suitable way to obtain their size at pre-processor time. Quoting from §5.2.4.2.1, paragraph 1:</p>
   <blockquote>
    <p>The values given below shall be replaced by constant expressions suitable for use in <code class="highlight"><c- cp>#if</c-></code> preprocessing directives.</p>
   </blockquote>
   <p>This means that the types above have a specific size that can be properly initialized by a preprocessor entirely independent of a proper C frontend, without needing to know more than how to be a preprocessor. Originally, the proposal required that every use of <code class="highlight"><c- cp>#embed</c-></code> is accompanied by a <code class="highlight"><c- cp>#include</c-> &lt;limits.h></code> (or, in the case of C++, <code class="highlight"><c- cp>#include</c-> &lt;climits></code>). Instead, the proposal now lets the implementation "figure it out" on an implementation-by-implementation basis.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

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

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

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

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

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

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


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

    tocNav.appendChild(toggle);
  }

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

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

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

})();
</script>