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

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

	body {
		counter-reset: example figure issue;

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	p {
		margin: 1em 0;
	}

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

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

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

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

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

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

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

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

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

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

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

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

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

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

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

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

  /* Do something nice. */

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

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

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

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

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

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

	img {
		border-style: none;
	}

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

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

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

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

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

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

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

	blockquote {
		border-color: silver;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


/*
Alternate table alignment rules

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

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

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

Possible extra rowspan handling

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

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

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


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

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

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

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

	/* @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 {
			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; }
		}
	/* } */

	@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 {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


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

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

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

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

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

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

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

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

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

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

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



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

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

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

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

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

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

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
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-selflinks */

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

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

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

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

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

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">P2137R0<br>Goals and priorities for C++</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2020-03-02">2020-03-02</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/p2137r0">https://wg21.link/p2137r0</a>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><span class="p-name fn"></span>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:chandlerc@google.com">Chandler Carruth</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:tcosta@nvidia.com">Timothy Costa</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:hfinkel@anl.gov">Hal Finkel</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:dmitrig@google.com">Dmitri Gribenko</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:dshollm@sandia.gov">D. S. Hollman</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:ckennelly@google.com">Chris Kennelly</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:tkoeppe@google.com">Thomas Köppe</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:lebrungrandt@ornl.gov">Damien Lebrun-Grandie</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:blelbach@nvidia.com">Bryce Adelstein Lelbach</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:joshl@google.com">Josh Levenberg</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:nliber@anl.gov">Nevin Liber</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:palmer@google.com">Chris Palmer</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:scogland1@llnl.gov">Tom Scogland</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:richardsmith@google.com">Richard Smith</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:david.stone@uber.com">David Stone</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:crtrott@sandia.gov">Christian Trott</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:titus@google.com">Titus Winters</a>
     <dt>Audience:
     <dd>EWG
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This paper describes the goals and priorities which the authors believe make

  C++ an especially effective programming language for our use cases. That
  said, our experience, use cases, and needs are clearly not those of every
  user. We aren’t pushing to directly build consensus on these points. Rather,
  this is presented as a vehicle to advertise our needs from C++ as
  a high-performance systems language.</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="#goals"><span class="secno">1</span> <span class="content">Language goals</span></a>
     <ol class="toc">
      <li><a href="#performance"><span class="secno">1.1</span> <span class="content">Performance-critical software</span></a>
      <li><a href="#evolution"><span class="secno">1.2</span> <span class="content">Both software and language evolution</span></a>
      <li><a href="#simplicity"><span class="secno">1.3</span> <span class="content">Code that is simple and easy to read, understand, and write</span></a>
      <li><a href="#safety"><span class="secno">1.4</span> <span class="content">Practical safety guarantees and testing mechanisms</span></a>
      <li><a href="#fast"><span class="secno">1.5</span> <span class="content">Fast and scalable development</span></a>
      <li><a href="#platforms"><span class="secno">1.6</span> <span class="content">Modern hardware architectures, OS platforms, and environments</span></a>
     </ol>
    <li>
     <a href="#non-goals"><span class="secno">2</span> <span class="content">Non-goals</span></a>
     <ol class="toc">
      <li><a href="#abi"><span class="secno">2.1</span> <span class="content">Stable language and library ABI</span></a>
      <li><a href="#compatibility"><span class="secno">2.2</span> <span class="content">Backwards or forwards compatibility</span></a>
      <li><a href="#binary-libraries"><span class="secno">2.3</span> <span class="content">Legacy compiled libraries without source code or ability to rebuild</span></a>
      <li><a href="#compilation-and-linking"><span class="secno">2.4</span> <span class="content">Support for existing compilation and linking models</span></a>
     </ol>
    <li><a href="#feature-prioritization"><span class="secno">3</span> <span class="content">Prioritizing across domain-motivated features</span></a>
    <li><a href="#acknowledgements"><span class="secno">4</span> <span class="content">Acknowledgements</span></a>
   </ol>
  </nav>
  <main>
   <p>Historically, C++ has seemed at times to be aligned with the goals and
priorities we will outline here—often enough to lend credence to these
priorities, but erratically enough to create confusion and friction within the
committee and community. We believe that many divisive issues in the committee
come from a disagreement on either stated or assumed priorities. As Chandler
and Titus said in <a href="https://www.youtube.com/watch?v=LJh5QCV4wDg">their joint CppCon
talk</a> this year: a programming
language is a tool, and different tools are good for different purposes. We
think there is great value in priorities that differentiate C++ from the
plethora of programming languages, rather than following the crowd and
regressing to the mean. But the most important thing is for C++ to state its
priorities clearly and explicitly. The knowledge of what to expect would
improve the entire community’s ability to evaluate and use the language.</p>
   <p>We strongly encourage the direction group and committee leadership to lead
ongoing discussions on this topic.</p>
   <h2 class="heading settled" data-level="1" id="goals"><span class="secno">1. </span><span class="content">Language goals</span><a class="self-link" href="#goals"></a></h2>
   <p>What are our goals for the C++ language? We believe it must support:</p>
   <ol>
    <li data-md>
     <p>Performance-critical software</p>
    <li data-md>
     <p>Both software and language evolution</p>
    <li data-md>
     <p>Code that is simple and easy to read, understand, and write</p>
    <li data-md>
     <p>Practical safety guarantees and testing mechanisms</p>
    <li data-md>
     <p>Fast and scalable development</p>
    <li data-md>
     <p>Current hardware architectures, OS platforms, and environments as they
  evolve</p>
   </ol>
   <p>These are in rough priority order. While there may be nuances where this order
does not apply, we generally want to prioritize in this manner.</p>
   <p><strong>Performance as the top priority is the defining aspect of C++</strong> for our
users. No other programming language provides the performance-critical
facilities of C++. This should be the unique value proposition of the C++
programming language.</p>
   <p>Overall, these priorities imply a set of long-term goals and are at least
somewhat aspirational. Practical concerns, of course, limit our ability to
simply or easily achieve these goals, but we think they still describe the
direction in which the overall design of C++ should be moving. We feel the
design of each and every feature or facility should be rooted in these
priorities. Some features and facilities are also directly motivated by these
priorities—without them users would be unable to address these goals. However,
there is also a broad range of features and facilities (especially
domain-focused libraries) which are equally compatible with these priorities
and may require some other ranking function to provide roadmap-level
prioritization.</p>
   <p>Below, we discuss these priorities in more detail to give a deeper
understanding of both the nature and motivation of these goals. We also call
out non-goals and provide a more detailed outline of the target audience.</p>
   <h3 class="heading settled" data-level="1.1" id="performance"><span class="secno">1.1. </span><span class="content">Performance-critical software</span><a class="self-link" href="#performance"></a></h3>
   <p>All software consumes resources (time, memory, compute, power, etc.), and in
many cases raw resource usage is not the biggest concern. Instead, algorithmic
efficiency or business logic dominates these concerns. However, there exists
software where the rate of resource consumption—its performance—is critical to
its successful operation. Another way to think about when performance is
critical: would a performance regression be considered a bug for users? Would
it even be noticed?</p>
   <p>Our goal is to support software where its performance with respect to some set
of resource constraints is critical to its successful operation. This
overarching goal can be decomposed into a few specific aspects.</p>
   <p><strong>Provide the programmer control over every aspect of performance.</strong> When faced
with some performance problem, the programmer should always have tools within
C++ to address it. This does not mean that the programmer is necessarily
concerned with ultimate performance at every moment, but in the most
constrained scenarios they must be able to “open up the hood” without switching
to another language.</p>
   <p><strong>Code should perform predictably.</strong> The reader (and writer) of code should be
able to easily understand its expected performance, given sufficient background
knowledge of the environment in which it will run. This need not be precise,
but instead can use heuristics and guidelines to avoid surprise. The key
priority is that performance, whether good or bad, is unsurprising to users of
the C++ language. Even pleasant surprises, when too frequent, can become
a problem due to establishing brittle baseline performance that cannot be
reliably sustained.</p>
   <p><strong>Leave no room for a lower level language.</strong> Whether to gain control over
performance problems or to gain access to hardware facilities, programmers
should not need to leave the rules and structure of the language.</p>
   <h3 class="heading settled" data-level="1.2" id="evolution"><span class="secno">1.2. </span><span class="content">Both software and language evolution</span><a class="self-link" href="#evolution"></a></h3>
   <p>Titus Winters writes in <a href="https://abseil.io/resources/wapi18-winters.pdf">"Non-Atomic Refactoring and Software Sustainability"</a>:</p>
   <blockquote>
    <p>What is the difference between programming and software engineering? These are
nebulous concepts and thus there are many possible answers, but my favorite
definition is this: Software engineering is programming integrated over time.
All of the hard parts of engineering come from dealing with time:
compatibility over time, dealing with changes to underlying infrastructure and
dependencies, and working with legacy code or data. Fundamentally, it is
a different task to produce a programming solution to a problem (that solves
the current [instance] of the problem) vs. an engineering solution (that
solves current instances, future instances that we can predict, and - through
flexibility - allows updates to solve future instances we may not be able to
predict).</p>
   </blockquote>
   <p>From this definition of "software engineering" vs. "programming" we suggest
that C++ should prioritize being more of a "software engineering" language, and
less of a "programming" language. We specifically are interested in dealing
with the time-oriented aspects of software built in this language.</p>
   <p><strong>Support maintaining and evolving software written in C++ for decades.</strong> The
life expectancy of some software will be long and the software will not be
static or unchanging in that time. Mistakes will be made and need to be
corrected. New functionality will be introduced and old functionality retired
and removed. The design of C++ must support and ease every step of this
process. This ranges from emphasizing testing and continuous integration to
tooling and the ability to make <a href="https://youtu.be/v_yzLe-wnfk">multi-step
changes</a>. It also includes constraints on the
design of the language itself: we should avoid, or at least minimize, language
features that encourage unchangeable constructs. For example, any feature with
a contract that cannot be strengthened or weakened without breaking the
expected usage patterns is inherently hostile to refactoring. Similarly,
features or conventions that require simultaneously updating all users of an
API when extending it are inherently hostile towards long-term maintenance of
software.</p>
   <p><strong>Support maintaining and evolving the language itself for decades.</strong> Historically, we have not gotten the design of most language features correct
on our first or second try. And we shouldn’t expect that to change going
forward either. As a consequence, there must be a built-in plan and ability to
move C++ forward at a reasonable pace and with a reasonable cost.
Simultaneously, an evolving language must not leave software behind to
languish, but bring software forward. This requirement should not imply
compatibility, but instead some (likely tool-assisted) migratability.</p>
   <p><strong>Be mindful of legacy.</strong> We support several 100s of millions of lines of C++
code. Globally, there may be as many as 50 billion lines of C++ code. Any
evolution of C++ that fails to account for the human investment (training) and
legacy code (representing significant capital) is doomed from the start. Note
that our _priority_ is restricted to legacy _source code_. Full support,
whether across the full language feature set or with full performance, for
legacy code beyond that (such as precompiled binaries we call out below) is not
a prioritized goal. While that still leaves many options open (such as
dedicated and potentially slower features), it does limit the degree to which
legacy use cases beyond source code should shape the language design.</p>
   <h3 class="heading settled" data-level="1.3" id="simplicity"><span class="secno">1.3. </span><span class="content">Code that is simple and easy to read, understand, and write</span><a class="self-link" href="#simplicity"></a></h3>
   <p>While this is perhaps the least unique (among programming languages) of the
goals we list here, and the one most widely shared and discussed in C++'s
evolution today, we feel it is important to state it, explain all of what we
mean by this, and fit it into our prioritization scheme.</p>
   <p>Software, especially at scale and over time, already imposes a burden on
engineers due to its complexity. The C++ language should strive for simplicity
to reduce the complexity burden on reading, understanding, and writing code.
The behavior of code should be easily understood, especially by those
unfamiliar with the software system. Consider engineers attempting to diagnose
a serious outage under time pressure—every second spent trying to understand
the _language_ is one not spent understanding the _problem_.</p>
   <p>While the source code of our software may be read far more often by machines,
humans are the most expensive readers (and writers) of software. As
a consequence, we need to optimize for human reading, understanding,
maintaining, and writing of software, in that order.</p>
   <p><strong>Excellent ergonomics.</strong> Human capabilities and limitations in the domains of
perception, memory, reasoning, and decision-making affect interactions between
humans and systems. Ergonomic language design takes human factors into account
to increase productivity and comfort, reduces errors and fatigue, making C++
more suitable for humans to use. We can also say that ergonomic designs are
accessible to humans. “Readability” is a related, but a more focused concept,
connected to only the process of reading code. “Ergonomics” covers all
activities where humans interact with C++: reading, writing, designing,
discussing, reviewing, and refactoring code, as well as learning and teaching
C++. A few examples:</p>
   <ul>
    <li data-md>
     <p>C++ should not use symbols that are difficult to type, see, or differentiate
  from similar symbols in commonly used contexts.</p>
    <li data-md>
     <p>Syntax should be easily parsed and scanned by any human in any development
  environment, not just a machine or a human aided by semantic hints from an
  IDE.</p>
    <li data-md>
     <p>Code with similar behavior should use similar syntax, and code with
  different behavior different syntax. Behavior in this context should include
  both the functionality and performance of the code. This is part of
  conceptual integrity.</p>
    <li data-md>
     <p>Explicitness must be balanced against conciseness as verbosity and ceremony
  add cognitive overhead for the reader, while explicitness reduces the amount
  of outside context the reader must have or assume.</p>
    <li data-md>
     <p>Ordinary tasks should not require extraordinary care, because humans cannot
  consistently avoid making mistakes for an extended amount of time.</p>
   </ul>
   <p><strong>Support tooling at every layer of the developer experience, including IDEs.</strong> The design and implementation of C++ should facilitate both the ease of
producing such tools and their effectiveness. Syntax and textual structures that
are difficult to recognize and mechanically change without losing meaning should
be avoided.</p>
   <p><strong>Support software outside of the primary use cases well.</strong> There are
surprisingly high costs for engineers to switch languages. Even when the primary
goal is to support performance-critical software, other kinds of software should
not be penalized unnecessarily.</p>
   <blockquote>
    <p>"The right tool for the job is often the tool you are already using —<wbr>adding new tools has a higher cost than many people appreciate."
—<a href="https://twitter.com/id_aa_carmack/status/989951283900514304">John Carmack</a></p>
   </blockquote>
   <p>The result of this principle is that there is and will always be a large amount
of software written in C++ despite being outside the primary use case. This may
be due to familiarity of the engineering team, due to existing libraries written
in C++, or due to other ecosystem effects.</p>
   <p><strong>Focus on enabling better code patterns rather than restricting bad ones.</strong> Adding restrictions to otherwise general facilities can have
a disproportionately negative impact in the (possibly rare) cases when they get
in the way. Instead, C++ should focus on enabling better patterns, encouraging
their use, and creating incentives to ensure people prefer them. The "bad"
pattern may be critical for some rare user or some future use case. Put
differently, we will not always be able to prevent engineers from writing bad or
unnecessarily complex code, and that is okay. We should instead focus on helping
reduce the rate that this occurs accidentally, and enabling interface designs,
naming patterns, tooling, and diagnostics that warn about dangerous or
surprising patterns. This takes the language out of the business of legislating
these types of issues.</p>
   <p>A concrete example is that we should continue to allow dropping type-system
enforced ownership (<code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>unique_ptr</c-><c- o>::</c-><c- n>release</c-></code>) for the edge cases where this
is important. But we can and should ensure that using type-system enforced
ownership is the easiest (and ideally default) approach when allocating memory.</p>
   <p><strong>The behavior and semantics of code should be clearly and simply specified
whenever possible.</strong> Leaving behavior undefined in some cases for invalid,
buggy, or non-portable code may be necessary but comes at a high cost and should
be avoided whenever other priorities (such as performance) allow. Every case
where behavior is left undefined should be clearly spelled out with a strong
rationale for this tradeoff. The code patterns without defined behavior should
be teachable and understandable by engineers. And finally, there must be
mechanisms available to detect undefined behavior, at best statically, and at
worst dynamically with high probability and at minimal cost.</p>
   <p><strong>Adhere to the principle of least surprise.</strong> Defaults should match typical
usage patterns. Implicit features should be unsurprising and expected, while
explicit syntax should inform the reader about any behavior which might
otherwise be surprising. The core concepts of implicit vs. explicit syntax are
well articulated in <a href="https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html#implicit-vs-explicit">the Rust
community</a>,
despite some specific examples and conclusions not necessarily adhering to this
principle.</p>
   <p><strong>Design features to be simple to implement.</strong> Syntax, structure, language, and
library features should be chosen while keeping the complexity of the
implementation manageable. This reduces bugs, and will in most cases make the
features easier to understand.</p>
   <h3 class="heading settled" data-level="1.4" id="safety"><span class="secno">1.4. </span><span class="content">Practical safety guarantees and testing mechanisms</span><a class="self-link" href="#safety"></a></h3>
   <p>Our goal is to add as much language-level safety and security to C++ as possible
when balanced against the pragmatic need for software performance, programmer
ergonomics, and continued support of existing/legacy C and C++ code. This
results in a hybrid strategy where we prove as much safety as we can (within
these constraints) at compile time, and combine this with dynamic runtime
checking and a strong testing methodology ranging from unit tests through
integration and system tests all the way to coverage-directed fuzz testing. We
have specific criteria that are important for this strategy to be successful:</p>
   <p><strong>Make unsafe or risky aspects of an operation, interface, or type explicit and
syntactically visible.</strong> This will allow the software to use the precise
flexibility needed and to minimize its exposure, while still aiding the reader.
It can also help the reader more by indicating the specific nature of risk faced
by a given construct. More simply, safe things shouldn’t look like unsafe things
and unsafe things should be easily recognized when reading code.</p>
   <p><strong>Common patterns of unsafe or risky code must support static checking.</strong> Waiting until a dynamic check is too late for the 80% case. A canonical example
here are <a href="https://clang.llvm.org/docs/ThreadSafetyAnalysis.html">thread-safety
annotations</a> for basic
mutex lock management to allow static checking. This handles the common
patterns, and we use dynamic checks (TSan, deadlock detection) to handle edge
cases.</p>
   <p><strong>All unsafe or risky operations and interfaces must support some dynamic
checking.</strong> Users need _some_ way to test and verify that their code using any
such interface is in fact correct. Uncheckable unsafety removes any ability for
the user to gain confidence. This means we need to design features with unsafe
or risky aspects with dynamic checking in mind. A concrete example of this can
be seen in facilities that allow indexing into an array: such facilities should
be designed to have the bounds of the array available to implement bounds
checking when desirable. These dynamic checks may even need to be designed using
high-cost techniques that only apply to continuous integration and testing (such
as Sanitizers and shadow memory), but the key thing is that they are available
in some form to verify whether the underlying code is correct.</p>
   <h3 class="heading settled" data-level="1.5" id="fast"><span class="secno">1.5. </span><span class="content">Fast and scalable development</span><a class="self-link" href="#fast"></a></h3>
   <p>Engineers interact with many language tools that need different levels of
processing. IDEs and editor tools often use minimal parsing to give rapid
feedback. Engineers will also iterate repeatedly on any compile error. Building,
testing, and debugging complete the "edit, test, debug" cycle that is the
critical path of software development iteration. Each step needs to be fast and
scalable. Raw speed is essential for small projects and local development.
Scalability is necessary to address the large software systems we currently use.</p>
   <p><strong>Syntax should parse with bounded, small look-ahead.</strong> Using syntax that
requires unbounded look-ahead or fully general backtracking adds significant
complexity to parsing and makes it harder to provide high quality error
messages. The result is both slower iteration and more iterations,
a multiplicative negative impact on productivity. Humans aren’t immune either
and can be confused by constructs that appear to mean one thing but actually
mean another. Instead, we should design for syntax that is fast to parse, with
easy and reliable error messages.</p>
   <p><strong>No semantic or contextual information used when parsing.</strong> The more context,
and especially the more _semantic_ context, required for merely parsing code,
the fewer options available to improve the performance of tools and compilation.
Cross-file context has an especially damaging effect on the potential
distributed build graph options. Without these options, we will again be unable
to provide fast programmer iteration as the codebase scales up.</p>
   <p><strong>Support separate compilation, including parallel and distributed strategies.</strong> We cannot assume coarse-grained compilation without blocking fundamental
scalability options for build systems of large software.</p>
   <h3 class="heading settled" data-level="1.6" id="platforms"><span class="secno">1.6. </span><span class="content">Modern hardware architectures, OS platforms, and environments</span><a class="self-link" href="#platforms"></a></h3>
   <p>We of course continue to care that C++ supports all of the major, modern
platforms, the hardware architectures they run on, and the environments in which
their software runs. However, this only forms a fairly small and focused subset
of the platforms that have historically been supported and motivated specific
aspects of the C++ design. We would suggest this be narrowed as much as
possible. An initial non-exhaustive list of platforms we believe should continue
to be prioritized:</p>
   <ul>
    <li data-md>
     <p>Linux</p>
    <li data-md>
     <p>Android</p>
    <li data-md>
     <p>Windows</p>
    <li data-md>
     <p>macOS, iOS, watchOS, tvOS</p>
    <li data-md>
     <p>Fuchsia</p>
    <li data-md>
     <p>WebAssembly</p>
    <li data-md>
     <p>OS/kernel</p>
    <li data-md>
     <p>QNX</p>
    <li data-md>
     <p>Bare-metal</p>
   </ul>
   <p>Similarly, we should prioritize support for 64-bit little-endian hardware,
including:</p>
   <ul>
    <li data-md>
     <p>x86-64</p>
    <li data-md>
     <p>AArch64 (ARM 64-bit)</p>
    <li data-md>
     <p>PPC64LE (Power ISA, 64-bit, Little Endian)</p>
    <li data-md>
     <p>RV64I (RISC-V 64-bit)</p>
   </ul>
   <p>We believe C++ should continue to strive to support some GPUs, other restricted
computational hardware and environments, and embedded environments, although
likely not all historical platforms of this form. While this should absolutely
include future and emerging hardware and platforms, those shouldn’t
_disproportionately_ shape the fundamental library and language design -- they
remain relatively new and narrow in user base at least initially.</p>
   <p>We do not need to prioritize support for historical platforms. To use a hockey
metaphor, C++ should not skate to where the puck is, much less where the puck
was twenty years ago. We have existing systems to support those platforms where
necessary. Instead, C++ should be forward-leaning in its platform support. To
give a non-exhaustive list of example, we should not prioritize support for:</p>
   <ul>
    <li data-md>
     <p>Byte sizes other than 8-bits, or non-power-of-two word sizes</p>
    <li data-md>
     <p>Source code encodings other than UTF-8</p>
    <li data-md>
     <p>Big- or mixed-endian (at least for computation; accessing encoded data
  remains useful)</p>
    <li data-md>
     <p>Non-2’s-complement integer formats (we supported C++20 dropping support for
  this)</p>
    <li data-md>
     <p>Non-IEEE 754 floating point format as default floating point types</p>
    <li data-md>
     <p>Source code in file systems that don’t support file extensions or nested
  directories</p>
   </ul>
   <p>A specific open question is whether supporting 32-bit hardware and environments
(including for example x32) is an important goal. While some communities,
especially in the embedded space, currently rely on this, it comes at
a significant cost and without significant advantage to other communities. We
would like to attempt to address the needs of these communities within a 64-bit
model to simplify things long-term, but this may prove impossible.</p>
   <h2 class="heading settled" data-level="2" id="non-goals"><span class="secno">2. </span><span class="content">Non-goals</span><a class="self-link" href="#non-goals"></a></h2>
   <p>There are common or expected goals of many programming languages that we
explicitly call out as non-goals for the C++ language from our perspective. That
doesn’t make these things bad in any way, but reflects the fact that they do not
provide meaningful value to us and come with serious costs and/or risks.</p>
   <h3 class="heading settled" data-level="2.1" id="abi"><span class="secno">2.1. </span><span class="content">Stable language and library ABI</span><a class="self-link" href="#abi"></a></h3>
   <p>We would prefer to provide better, dedicated mechanisms to decompose software
subsystems in ways that scale over time rather than providing a stable ABI
across the language and libraries. Our experience is that providing broad
ABI-level stability for high-level constructs is a significant and permanent
burden on their design. It becomes an impediment to evolution, which is one of
our stated goals.</p>
   <p>This doesn’t preclude having low-level language features or tools to create
specific and curated stable ABIs (or even serializable protocols). Using any
such facilities will also cause developers to explicitly state where they are
relying on ABI and isolating it (in source) from code which does not need that
stability. However, these facilities would only expose a restricted set of
language features to avoid coupling the high-level language to particular
stabilized interfaces. There is a wide range of such facilities that should be
explored, from serialization-based systems like <a href="https://developers.google.com/protocol-buffers">protobufs</a> or <a href="https://docs.python.org/3/library/pickle.html">pickling in
Python</a>, to <a href="https://docs.microsoft.com/en-us/windows/win32/com/com-objects-and-interfaces">COM</a> or Swift’s <a href="https://swift.org/blog/library-evolution/">“resilience”</a> model. The
specific approach should be designed specifically around the goals outlined
above in order to fit the C++ language.</p>
   <h3 class="heading settled" data-level="2.2" id="compatibility"><span class="secno">2.2. </span><span class="content">Backwards or forwards compatibility</span><a class="self-link" href="#compatibility"></a></h3>
   <p>Our goals are focused on _migration_ from one version of C++ to the next rather
than _compatibility_ between them. This is rooted in our experience with
evolving software over time more generally and a <a href="https://abseil.io/blog/20171004-cppcon-plenary">live-at-head
model</a>. Any transition, whether
based on backward compatibility or a migration plan, will require some manual
intervention despite our best efforts, due to <a href="http://www.hyrumslaw.com">Hyrum’s
Law</a>, and so we should acknowledge that upgrades
require active migrations.</p>
   <h3 class="heading settled" data-level="2.3" id="binary-libraries"><span class="secno">2.3. </span><span class="content">Legacy compiled libraries without source code or ability to rebuild</span><a class="self-link" href="#binary-libraries"></a></h3>
   <p>We consider it a non-goal to support legacy code for which the source code is no
longer available, though we do sympathize with such use cases and would like to
see tooling mentioned above allow easier bridging between ABIs in these cases.
Similarly, plugin ABIs aren’t our particular concern, yet we’re interested in
seeing tooling which can help bridge between programs and plugins which use
different ABIs.</p>
   <h3 class="heading settled" data-level="2.4" id="compilation-and-linking"><span class="secno">2.4. </span><span class="content">Support for existing compilation and linking models</span><a class="self-link" href="#compilation-and-linking"></a></h3>
   <p>We are willing to change the compilation and linking model as necessary to
achieve these goals. Compilation models and linking models should be designed to
suit the needs of C++ and its use cases, tools, and environments, not what
happens to have been implemented thus far in compilers and linkers.</p>
   <p>A concrete example of this non-goal: it means platforms that cannot update their
compiler and linker when updating the C++ language are not supported.</p>
   <h2 class="heading settled" data-level="3" id="feature-prioritization"><span class="secno">3. </span><span class="content">Prioritizing across domain-motivated features</span><a class="self-link" href="#feature-prioritization"></a></h2>
   <p>Any language or library facility should be prioritized first and foremost
according to the top-level language goals above, and how well the facility meets
those goals. However, many facilities or features will meet these criteria
equally well. These features often serve different domains or users of the
language, and we still need an effective way to prioritize them. This
prioritization is significantly different from everything before as it doesn’t
impact the specific design of the feature itself, and is only intended to guide
how equally well-designed facilities are prioritized for incremental enhancement
of the language.</p>
   <p>At this stage, the primary prioritization should be based on the relative
cost-benefit ratio of the feature. The cost is a function of the effort required
to specify and implement the feature. The benefit is the number of impacted
users and the magnitude of that impact. We don’t expect to have concrete numbers
for these, but we expect prioritization decisions between features to be
expressed using this framework.</p>
   <p>Secondarily, priority should be given based on effort: both effort already
invested and effort ready to commit to the feature. This should not overwhelm
the primary metric, but given two equally impactful features we should focus on
the one that is moving fastest.</p>
   <h2 class="heading settled" data-level="4" id="acknowledgements"><span class="secno">4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#acknowledgements"></a></h2>
   <p>Many people contributed suggestions, ideas, and helped create this document but
may not completely agree with the exact set of goals and their priorities. We’d
like to credit their help writing it without them feeling pressured to sign onto
such a specific position, and so some are listed here:</p>
   <ul>
    <li data-md>
     <p>Jeff Snyder</p>
    <li data-md>
     <p>Lee Howes</p>
    <li data-md>
     <p>Louis Brandy</p>
    <li data-md>
     <p>David Goldblatt</p>
    <li data-md>
     <p>Michael Spencer</p>
   </ul>
   <p>That said, this is an incomplete list and we thank all the others who did
significant work to help arrive at this document.</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>