<!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>P3831R0: Contract Labels Should Use Annotation Syntax</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;
			border-bottom: 3px solid transparent;
			margin-bottom: -3px;
		}
		#toc .content:hover,
		#toc .content:focus {
			background: rgba(75%, 75%, 75%, .25);
			background: var(--a-hover-bg);
			border-bottom-color: #054572;
			border-bottom-color: var(--toclink-underline);
		}
		#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 3f621ba99, updated Mon Jul 28 15:38:36 2025 -0700" name="generator">
  <link href="https://wg21.link/P3831R0" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
  <meta content="1ebc5851fdb148042365195f8bfe81910405735e" name="revision">
  <meta content="dark light" name="color-scheme">
<style>
table, th, td { border:1px solid grey; }
</style>
<style>/* Boilerplate: 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;
}

@media (prefers-color-scheme: dark) {
    :root {
        --selflink-text: black;
        --selflink-bg: silver;
        --selflink-hover-text: white;
    }
}
</style>
<style>/* Boilerplate: 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;
}

@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; }
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: style-issues */
a[href].issue-return {
    float: right;
    float: inline-end;
    color: var(--issueheading-text);
    font-weight: bold;
    text-decoration: none;
}
</style>
<style>/* Boilerplate: 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>/* Boilerplate: 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%;
}
.example > a.self-link,
.note > a.self-link,
.issue > a.self-link {
    /* These blocks are overflow:auto, so positioning outside
       doesn't work. */
    left: auto;
    right: 0;
}
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>/* Boilerplate: 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 */

@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">P3831R0<br>Contract Labels Should Use Annotation Syntax</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="2025-09-07">2025-09-07</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://wg21.link/P3831R0">https://wg21.link/P3831R0</a>
     <dt class="editor">Author:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:winmikedows@hotmail.com">Yihe Li</a>
     <dt>Audience:
     <dd>SG21
     <dt>Project:
     <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
     <dt>Target:
     <dd><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>
     <dt>Source:
     <dd><a href="https://github.com/Mick235711/wg21-papers/blob/main/P3831/P3831R0.bs">github.com/Mick235711/wg21-papers/blob/main/P3831/P3831R0.bs</a>
     <dt>Issue Tracking:
     <dd><a href="https://github.com/Mick235711/wg21-papers/issues">GitHub Mick235711/wg21-papers</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </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="#revisions"><span class="secno">1</span> <span class="content">Revision History</span></a>
     <ol class="toc">
      <li><a href="#r0"><span class="secno">1.1</span> <span class="content">R0 (2025-09 Mailing)</span></a>
     </ol>
    <li>
     <a href="#background"><span class="secno">2</span> <span class="content">Background and Motivation</span></a>
     <ol class="toc">
      <li><a href="#background-labels"><span class="secno">2.1</span> <span class="content">Contract Labels</span></a>
      <li><a href="#background-annotations"><span class="secno">2.2</span> <span class="content">Annotations</span></a>
      <li><a href="#prior-arts"><span class="secno">2.3</span> <span class="content">Prior Arts</span></a>
     </ol>
    <li>
     <a href="#design"><span class="secno">3</span> <span class="content">Design</span></a>
     <ol class="toc">
      <li><a href="##proposal-1-design"><span class="secno">3.1</span> <span class="content">Proposal 1: Assertion-Control Objects</span></a>
      <li><a href="##proposal-2-design"><span class="secno">3.2</span> <span class="content">Proposal 2: Assertion Using Directives</span></a>
      <li><a href="#proposal-3-design"><span class="secno">3.3</span> <span class="content">Proposal 3: Assertion-Combination Operator</span></a>
      <li><a href="#proposal-4-design"><span class="secno">3.4</span> <span class="content">Proposal 4: Access-Control Object on Violation</span></a>
      <li><a href="#proposal-5-design"><span class="secno">3.5</span> <span class="content">Proposal 5: Ambient-Control Objects</span></a>
      <li><a href="#controllable-properties"><span class="secno">3.6</span> <span class="content">Controllable Properties</span></a>
      <li><a href="#possible-issues"><span class="secno">3.7</span> <span class="content">Possible Issues</span></a>
     </ol>
    <li><a href="#suggestions"><span class="secno">4</span> <span class="content">Suggestions</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <p>Contract labels (<a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>) are one of the most important extensions proposed to C++26 Contracts, providing the ability to control the behavior of specific contract assertions. This proposal argues that instead of inventing a new syntax for parameterizing contract assertions, the labels should utilize the existing feature in the standard that permits this parameterization with defined semantics, namely annotations (<a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a>).</p>
   <h2 class="heading settled" data-level="1" id="revisions"><span class="secno">1. </span><span class="content">Revision History</span><a class="self-link" href="#revisions"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="r0"><span class="secno">1.1. </span><span class="content">R0 (2025-09 Mailing)</span><a class="self-link" href="#r0"></a></h3>
   <ul>
    <li data-md>
     <p>Initial revision.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="background"><span class="secno">2. </span><span class="content">Background and Motivation</span><a class="self-link" href="#background"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="background-labels"><span class="secno">2.1. </span><span class="content">Contract Labels</span><a class="self-link" href="#background-labels"></a></h3>
   <p>Contracts (<a data-link-type="biblio" href="#biblio-p2900r14" title="Contracts for C++">[P2900R14]</a>) were voted in as one of the most important features for C++26 back in Hagenberg (2025-02); however, several features are still missing from the MVP that are present in the standard. One of the most important addon features is the ability to control the flexibility of Contracts in source code, such as controlling the available evaluation semantics of a particular contract assertion. The proposal <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> tries to address this lack of functionality by introducing the concept of <em>contract labels</em>, which includes a way of using <em>assertion-control objects</em> with the syntax <code class="highlight"><c- n>pre</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>expression</c-><c- p>)</c-></code> to control the behavior of contract assertions. To use the examples present in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>:</p>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_label_t</c-> <c- p>{};</c->

<c- k>constexpr</c-> <c- n>my_label_t</c-> <c- n>my_label</c-><c- p>;</c->

<c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
    <c- n>post</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- o>:</c-> <c- n>r</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
<c- p>{</c->
    <c- n>contract_assert</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
    <c- c1>// ...</c->
<c- p>}</c->
</pre>
   <p><code class="highlight"><c- n>my_label</c-></code> would then be used to customize the properties of the contract assertion.</p>
   <p>The initial motivation for this syntax is to simulate the template type parameter specification syntax, as the labels are also a way of parameterizing contract assertions, exactly like template type parameters are a way of parameterizing template functions or classes. The assertion-control objects are also required to be produced by constant expressions to further enforce this similarity. However, the author of this proposal identifies several problems with this piggyback syntax approach:</p>
   <ul>
    <li data-md>
     <p>The above declaration looks very much like a function call to a function declared with signature <code class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>auto</c-> <c- n>V</c-><c- o>></c-> <c- b>void</c-> <c- n>pre</c-><c- p>(</c-><c- b>bool</c-> <c- n>b</c-><c- p>)</c-></code> (with proper constraints), which is presumably the design intent of contract labels. However, such a function call will require the type of the assertion-control objects to be structural in order for them to be passable as constant template parameters, which is clearly not the case in contract labels. In the latter scenario, the only requirements for these objects are that their type is a class type (the concept <code class="highlight"><c- n>assertion_control_object</c-></code> in Section 2.1.1 of <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>). Using the same syntax for both while having different requirements on types will be very confusing for the users:</p>
   </ul>
<pre class="language-cpp highlight"><c- k>template</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>contracts</c-><c- o>::</c-><c- n>labels</c-><c- o>::</c-><c- n>assertion_control_object</c-> <c- k>auto</c-> <c- n>V</c-><c- o>></c->
<c- b>void</c-> <c- n>pre</c-><c- p>(</c-><c- b>bool</c-> <c- n>b</c-><c- p>);</c->

<c- k>struct</c-> <c- nc>A</c-> <c- p>{</c-> <c- k>constexpr</c-> <c- n>A</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c-> <c- p>};</c->
<c- k>struct</c-> <c- nc>B</c-> <c- o>:</c-> <c- k>private</c-> <c- n>A</c-> <c- p>{</c-> <c- k>constexpr</c-> <c- n>B</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c-> <c- p>};</c-> <c- c1>// literal, but not structural</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <c- n>B</c-> <c- n>b</c-><c- p>;</c->

<c- b>void</c-> <c- nf>use</c-><c- p>()</c->
<c- p>{</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>b</c-><c- o>></c-><c- p>(</c->true<c- p>);</c-> <c- c1>// ill-formed: not structural</c->
<c- p>}</c->
<c- b>void</c-> <c- nf>fun</c-><c- p>()</c-> <c- n>pre</c-><c- o>&lt;</c-><c- n>b</c-><c- o>></c-><c- p>(</c->true<c- p>);</c-> <c- c1>// well-formed?</c->
</pre>
   <ul>
    <li data-md>
     <p>The exact semantics of this new syntax will need to be manually defined. For example, <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> explicitly leaves unspecified whether the same assertion-control object is used for all instances of the same contract assertions, and requires them not to be in the immediate context (not subject to SFINAE). This in itself is not a problem, but it can be a burden to maintain a separate list of semantics for this narrowly utilized new syntax and fully explore its interaction with the rest of the language.</p>
    <li data-md>
     <p>The API design for fetching the assertion-control objects attached to a contract assertion (Proposal 4) is very clumsy; <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> provides the <code class="highlight"><c- b>void</c-><c- o>*</c-> <c- n>contract_violation</c-><c- o>::</c-><c- n>control_object</c-><c- p>()</c-></code> function that fetches a pointer to the object, but also admits that such a pointer is basically useless and highly dangerous due to the lack of type information. The proposal tries to mitigate this issue by requiring that this function only return a non-<code class="highlight"><c- k>nullptr</c-></code> pointer when the control object is polymorphic, and relying on <code class="highlight"><c- k>dynamic_cast</c-></code>s to recover the correct types. However, the proposal fails to provide an actual use case of polymorphic control objects. Since they are required to be constant objects, polymorphism will be of very limited usefulness. (To that end, why is this function not marked <code class="highlight"><c- k>constexpr</c-></code> or even <code class="highlight"><c- k>consteval</c-></code>?)</p>
    <li data-md>
     <p>The concept of <em>ambient-control objects</em> (Proposal 5) intends to automatically attach the same label to (for example) all contract assertions on functions declared within a particular namespace. This is intended to be achieved through a kind of implicit control-object declaration syntax invoked via <code class="highlight"><c- n>contract_assert</c-> <c- n>implicit</c-> <c- o>&lt;</c-><c- n>expression</c-><c- o>></c-><c- p>;</c-></code> that injects the label to all declarations in the same scope. However, several important design decisions remain unanswered for such declarations. See the sections below for more on this.</p>
   </ul>
   <p>In the end, contract labels at their core are yet another way to come up with a syntax to annotate declarations in a program-detectable manner to adjust the behavior of the program, in other words, a non-ignorable attribute syntax. Such experiments have been proposed several times ever since attributes were introduced in C++11 and immediately failed to be the supposed solution to the decoration problem (see <a data-link-type="biblio" href="#biblio-attribute-critics" title="On the Ignorability of Attributes">[attribute-critics]</a> for more on this topic). However, the standard now has a solution to this problem.</p>
   <h3 class="heading settled" data-level="2.2" id="background-annotations"><span class="secno">2.2. </span><span class="content">Annotations</span><a class="self-link" href="#background-annotations"></a></h3>
   <p>Annotations, proposed by <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a>, were initially intended as a complement to the reflection proposal (<a data-link-type="biblio" href="#biblio-p2996r13" title="Reflection for C++26">[P2996R13]</a>) to provide a way to annotate declarations such that they can be read by reflection queries. Such an annotation has significant usefulness, such as providing parser arguments in a command-line argument parser, providing test case parameterization, and providing a general way of customizing class derivations similar to the Rust <code class="highlight"><c- cp>#[derive]</c-></code> macro.</p>
   <p>Initially, in the early days of reflection, people were trying to achieve this functionality with the same means that contract labels are trying to imitate: template arguments. Specifically, the workaround was to try to use a template parameter pack to provide the additional annotations:</p>
<pre class="language-cpp highlight"><c- k>template</c-> <c- o>&lt;</c-><c- k>typename</c-> <c- nc>T</c-><c- p>,</c-> <c- k>auto</c-><c- p>...</c-> <c- n>Annotations</c-><c- o>></c->
<c- k>using</c-> <c- n>Noted</c-> <c- o>=</c-> <c- n>T</c-><c- p>;</c->

<c- k>struct</c-> <c- nc>C</c->
<c- p>{</c->
    <c- n>Noted</c-><c- o>&lt;</c-><c- b>int</c-><c- p>,</c-> <c- mi>1</c-><c- o>></c-> <c- n>a</c-><c- p>;</c->
    <c- n>Noted</c-><c- o>&lt;</c-><c- b>int</c-><c- o>*</c-><c- p>,</c-> <c- n>some</c-><c- p>,</c-> <c- n>thing</c-><c- o>></c-> <c- n>b</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>However, it is quickly realized that annotation can be much more useful than just annotating template classes or functions, coupled with the difficulties encountered by trying to design a reflection API to retrieve the <code class="highlight"><c- n>Annotations</c-></code> (also an obstacle to the contract labels design, as shown above), leading to the invention of a new syntax for annotation: <code class="highlight"><c- p>[[</c-><c- o>=</c-><c- n>expr</c-><c- p>]]</c-></code>:</p>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>C</c->
<c- p>{</c->
    <c- p>[[</c-><c- o>=</c-><c- mi>1</c-><c- p>]]</c-> <c- b>int</c-> <c- n>a</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>Such an approach leverages the syntax space left behind in the attribute syntax instead and has significant advantages over the workaround:</p>
   <ul>
    <li data-md>
     <p>Since the attribute syntax is reused, a lot of the places where annotations can be placed are already defined by the standard for attributes, eliminating the need to manually define them again.</p>
    <li data-md>
     <p>Annotations are conceptually a non-ignorable attribute, so using similar syntax makes sense.</p>
    <li data-md>
     <p>Designing a reflection query to retrieve annotations is significantly easier, and can also be coordinated with attribute reflection efforts (<a data-link-type="biblio" href="#biblio-p3385r5" title="Attributes reflection">[P3385R5]</a>) to provide a more consistent API overall.</p>
   </ul>
   <p>After <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a>’s adoption into the C++26 standard in Sofia (2025-06), we finally have a ready-made solution to the decoration problem. Therefore, to avoid duplication of efforts, contract labels should also utilize annotations instead of inventing yet another new syntax.</p>
   <h3 class="heading settled" data-level="2.3" id="prior-arts"><span class="secno">2.3. </span><span class="content">Prior Arts</span><a class="self-link" href="#prior-arts"></a></h3>
   <p>The idea of adding a label to contracts is not new. For instance, C++20 Contracts (<a data-link-type="biblio" href="#biblio-p0542r5" title="Support for contract based programming in C++">[P0542R5]</a>) use the concept of <em>modifiers</em> to specify contract assertions' assertion levels, which can be seen as a more narrow form of contract labels. The syntax for modifiers also utilizes the syntax space left over by the attribute syntax:</p>
<pre class="language-cpp highlight"><c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- b>int</c-> <c- n>x</c-><c- p>)</c->
    <c- p>[[</c-><c- n>expects</c-> <c- n>audit</c-><c- o>:</c-> <c- n>x</c-> <c- o>></c-> <c- mi>0</c-><c- p>]]</c->
    <c- p>[[</c-><c- n>ensures</c-> <c- n>axiom</c-> <c- n>res</c-><c- o>:</c-> <c- n>res</c-> <c- o>></c-> <c- mi>1</c-><c- p>]];</c->
</pre>
   <p>This proves that the idea of treating such annotations as a kind of attributes is already present back in the C++20 Contracts design cycle, and thus, utilizing new annotation syntax can be seen as a continuation of this thinking.</p>
   <p>The similarities between several "annotation-like" proposals have also been highlighted by <a data-link-type="biblio" href="#biblio-p3661r0" title="Attributes, annotations, labels">[P3661R0]</a>, which tries to unify the syntax of Profiles (<a data-link-type="biblio" href="#biblio-p3589r2" title="C++ Profiles: The Framework">[P3589R2]</a>), contract labels, and reflection annotations by pointing out their core similarities. This proposal can be seen as a concrete and actionable version of suggestions regarding contract labels in <a data-link-type="biblio" href="#biblio-p3661r0" title="Attributes, annotations, labels">[P3661R0]</a>.</p>
   <h2 class="heading settled" data-level="3" id="design"><span class="secno">3. </span><span class="content">Design</span><a class="self-link" href="#design"></a></h2>
   <p>The overall design proposed by this proposal is to replace the <code class="highlight"><c- n>pre</c-><c- o>&lt;</c-><c- n>object</c-><c- o>></c-><c- p>(</c-><c- n>expr</c-><c- p>)</c-></code> syntax proposed by <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> with the annotation syntax, i.e., <code class="highlight"><c- n>pre</c-> <c- p>[[</c-><c- o>=</c-><c- n>object</c-><c- p>]]</c-> <c- p>(</c-><c- n>expr</c-><c- p>)</c-></code>. See the table below for a comparison of two syntaxes:</p>
   <table>
    <thead>
     <tr>
      <td><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> syntax
      <td>This Proposal
    <tbody>
     <tr>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_label_t</c-> <c- p>{};</c->

<c- k>constexpr</c-> <c- n>my_label_t</c-> <c- n>my_label</c-><c- p>;</c->

<c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
    <c- n>post</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>r</c-><c- o>:</c-> <c- n>r</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
<c- p>{</c->
    <c- n>contract_assert</c-><c- o>&lt;</c-><c- n>my_label</c-><c- o>></c-><c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
    <c- c1>// ...</c->
<c- p>}</c->
</pre>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_label_t</c-> <c- p>{};</c->

<c- k>constexpr</c-> <c- n>my_label_t</c-> <c- n>my_label</c-><c- p>;</c->

<c- b>int</c-> <c- nf>f</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c->
    <c- n>pre</c-> <c- p>[[</c-><c- o>=</c-><c- n>my_label</c-><c- p>]]</c-> <c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
    <c- n>post</c-> <c- p>[[</c-><c- o>=</c-><c- n>my_label</c-><c- p>]]</c-> <c- p>(</c-><c- n>r</c-><c- o>:</c-> <c- n>r</c-> <c- o>></c-> <c- mi>0</c-><c- p>)</c->
<c- p>{</c->
    <c- n>contract_assert</c-> <c- p>[[</c-><c- o>=</c-><c- n>my_label</c-><c- p>]]</c-> <c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
    <c- c1>// ...</c->
<c- p>}</c->
</pre>
     <tr>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_label_2_t</c-> <c- p>{};</c->
<c- k>constexpr</c-> <c- n>my_label_2_t</c-> <c- n>my_label_2</c-><c- p>;</c->

<c- b>void</c-> <c- nf>g</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>my_label</c-> <c- o>|</c-> <c- n>my_label_2</c-><c- o>></c-><c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
</pre>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_label_2_t</c-> <c- p>{};</c->
<c- k>constexpr</c-> <c- n>my_label_2_t</c-> <c- n>my_label_2</c-><c- p>;</c->

<c- b>void</c-> <c- nf>g</c-><c- p>(</c-><c- b>int</c-> <c- n>i</c-><c- p>)</c->
    <c- n>pre</c-> <c- p>[[</c-><c- o>=</c-><c- n>my_label</c-> <c- o>|</c-> <c- n>my_label_2</c-><c- p>]]</c-> <c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
<c- c1>// or, optionally</c->
    <c- n>pre</c-> <c- p>[[</c-><c- o>=</c-><c- n>my_label</c-><c- p>,</c-> <c- o>=</c-><c- n>my_label_2</c-><c- p>]]</c-> <c- p>(</c-><c- n>i</c-> <c- o>></c-> <c- mi>0</c-><c- p>);</c->
</pre>
   </table>
   <p>The rest of this section will discuss each proposal in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>, and how they should be redesigned with the introduction of annotations.</p>
   <h3 class="heading settled" data-level="3.1" id="#proposal-1-design"><span class="secno">3.1. </span><span class="content">Proposal 1: Assertion-Control Objects</span><a class="self-link" href="#%23proposal-1-design"></a></h3>
   <p>The grammar for the new <em>assertion-control-specifier</em>s actually occupies the same syntax as the attributes, directly prepending the latter. Since <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a> treated annotations as a kind of attributes, we automatically get the ability to use annotations in <code class="highlight"><c- n>pre</c-></code>, <code class="highlight"><c- n>post</c-></code>, and <code class="highlight"><c- n>contract_assert</c-></code> for free due to the existence of <em>attribute-specified-seq</em>s in their grammar (introduced by <a data-link-type="biblio" href="#biblio-p3088r1" title="Attributes for contract assertions">[P3088R1]</a>), thus eliminating the need to modify their grammar tree at all. However, several design decisions inherited from the annotation design are worth highlighting:</p>
   <ul>
    <li data-md>
     <p>A last-minute change made in Sofia (2025-06) to <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a> required that annotations and attributes must be specified separately; mixing them like <code class="highlight"><c- p>[[</c-><c- n>nodiscard</c-><c- p>,</c-> <c- o>=</c-><c- mi>2</c-><c- p>]]</c-></code> is no longer allowed.</p>
    <li data-md>
     <p>For <code class="highlight"><c- n>contract_assert</c-></code> only, <a data-link-type="biblio" href="#biblio-p3088r1" title="Attributes for contract assertions">[P3088R1]</a> made the distinction between attributes that are specific to assertion statements (such as vendor-specific labels) and attributes that can pertain to any statement (such as <code class="highlight"><c- p>[[</c-><c- n>likely</c-><c- p>]]</c-></code>). The former is required to be in the infix position after the <code class="highlight"><c- n>contract_assert</c-></code> keyword, and the latter is required to be in the prefix position before the keyword, just like any other statements. This coincides nicely with the annotation design, as vendor-specific attributes that modify the contract assertion semantics can also be seen as a kind of contract labels. Making them occupy the same grammatical position seems desirable and natural.</p>
    <li data-md>
     <p>Due to the need to reflect on annotations, their type is required to be structural. This is <strong>not</strong> true for contract labels in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>, but the author believes that this is a reasonable restriction, as the control objects being suggested as examples in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> all have structural types anyway.</p>
    <li data-md>
     <p><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> further proposes that the type of controlling objects must satisfy the <code class="highlight"><c- n>assertion_control_object</c-></code> concept, for which annotations are not required. However, this can be mitigated by requiring all annotations appearing in a contract assertion to satisfy this concept, too.</p>
    <li data-md>
     <p>The design decisions made in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> regarding name mangling and immediate context are also no longer relevant, as annotations already do not participate in name mangling and SFINAE.</p>
   </ul>
   <h3 class="heading settled" data-level="3.2" id="#proposal-2-design"><span class="secno">3.2. </span><span class="content">Proposal 2: Assertion Using Directives</span><a class="self-link" href="#%23proposal-2-design"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> went on to propose a new kind of using declaration and directive, the <code class="highlight"><c- n>contract_assert</c-> <c- k>using</c-></code> declaration and directives, aiming to be a way to minimize redundant namespaces for labels. Basically, prepending the <code class="highlight"><c- n>contract_assert</c-></code> keyword to any using declaration/directive makes them only apply to contract labels, and does not introduce the relevant names to other usages in the scope.</p>
   <p>Annotations actually used to have a similar functionality inherited from attributes: the attributes <code class="highlight"><c- k>using</c-></code> prefix (<a data-link-type="biblio" href="#biblio-p0028r4" title="Using attribute namespaces without repetition">[P0028R4]</a>).</p>
<pre class="language-cpp highlight"><c- p>[[</c-><c- k>using</c-> <c- n>clang</c-><c- o>:</c-> <c- n>A</c-><c- p>,</c-> <c- n>B</c-><c- p>,</c-> <c- n>C</c-><c- p>]]</c->
<c- c1>// equivalent to</c->
<c- p>[[</c-><c- n>clang</c-><c- o>::</c-><c- n>A</c-><c- p>,</c-> <c- n>clang</c-><c- o>::</c-><c- n>B</c-><c- p>,</c-> <c- n>clang</c-><c- o>::</c-><c- n>C</c-><c- p>]]</c->
</pre>
   <p>Essentially, the existence of <code class="highlight"><c- k>using</c-> <c- n>N</c-><c- o>:</c-></code> before the attribute list makes every attribute following implicitly adopt the <code class="highlight"><c- n>N</c-><c- o>::</c-></code> prefix, as a way to ease the attachment of multiple vendor-specific attributes. However, this prefix is not permitted to be used with annotations, which seems to the author of this proposal to be a design oversight. Originally, this exclusion is a must in <a data-link-type="biblio" href="#biblio-p3394r3" title="Annotations for Reflection">[P3394R3]</a> or earlier since attribute prefixes and annotation namespace prefixes are entirely different, and mixing them is nonsensical:</p>
<pre class="language-cpp highlight"><c- p>[[</c-><c- k>using</c-> <c- n>clang</c-><c- o>:</c-> <c- n>amdgpu_waves_per_eu</c-><c- p>,</c-> <c- o>=</c-><c- n>nick</c-><c- p>(</c-><c- s>"weapon"</c-><c- p>)]]</c->
<c- c1>// does this refer to clang::nick?</c->
</pre>
   <p>However, after the last-minute decision to separate attributes and annotations, the possibility of confusion was eliminated, but this design decision was not revisited. The author of this proposal thinks that allowing a <code class="highlight"><c- k>using</c-></code> prefix here (that functions as if a using directive is used) will also solve the contract label problem partially:</p>
<pre class="language-cpp highlight"><c- p>[[</c-><c- k>using</c-> <c- n>std</c-><c- o>::</c-><c- n>contracts</c-><c- o>::</c-><c- n>labels</c-><c- o>:</c-> <c- o>=</c-><c- n>label_a</c-><c- p>,</c-> <c- o>=</c-><c- n>label_b</c-><c- p>]]</c->
</pre>
   <p>The author does admit that this is not a full solution, as this syntax requires a separate <code class="highlight"><c- k>using</c-></code> prefix before each contract assertion. Therefore, no changes are proposed in this regard for now. However, the author still has reservations about the usefulness of introducing a new kind of using declarations just for such a narrow context.</p>
   <h3 class="heading settled" data-level="3.3" id="proposal-3-design"><span class="secno">3.3. </span><span class="content">Proposal 3: Assertion-Combination Operator</span><a class="self-link" href="#proposal-3-design"></a></h3>
   <p>To allow combining labels with orthogonal purposes, <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> introduced the concept of using <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> to create new combined labels. This in itself is fine, and can be directly ported to the annotation syntax, as the syntax allows arbitrary constant expressions too:</p>
<pre class="language-cpp highlight"><c- o>&lt;</c-><c- n>my_label</c-> <c- o>|</c-> <c- n>my_label_2</c-><c- o>></c->
<c- p>[[</c-><c- o>=</c-><c- n>my_label</c-> <c- o>|</c-> <c- n>my_label_2</c-><c- p>]]</c->
</pre>
   <p>However, the author of this proposal would like to point out that allowing only one argument in the template argument-like syntax is a bit odd, as template arguments are naturally multi-argument. Furthermore, the annotations API assumes that multiple annotations can be used, similar to attributes. Therefore, the author also suggests allowing multiple annotations here and letting the violation handler decide how to combine them. The default implementation of the handler can do an <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> on all the arguments implicitly, while custom handlers have the freedom to interpret them differently, such as logging all the labels involved.</p>
   <p>As a further note, <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a> also listed standard functions combining annotations as a future direction worth pursuing; perhaps <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> can be delayed to wait for a more general facility to combine all kinds of annotations, instead of just contract labels.</p>
   <h3 class="heading settled" data-level="3.4" id="proposal-4-design"><span class="secno">3.4. </span><span class="content">Proposal 4: Access-Control Object on Violation</span><a class="self-link" href="#proposal-4-design"></a></h3>
   <p>The API proposed in <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> for retrieving access-control objects has several limitations as argued above: they are untyped, and can only work with polymorphic types. Moreover, they assume that there is only one object specified for each contract assertion.</p>
   <p>Fortunately, by adopting the annotation syntax, we no longer need to come up with a new API design; we can directly reuse the reflection API to retrieve annotations. Originally, the author considered extending the <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>annotations_of</c-></code> function such that it can be applied to the reflection of the contract violation object, and the usage will be:</p>
<pre class="language-cpp highlight"><c- b>void</c-> <c- nf>handle_contract_violation</c-><c- p>(</c-><c- k>const</c-> <c- n>contract_violation</c-> <c- o>&amp;</c-><c- n>violation</c-><c- p>)</c->
<c- p>{</c->
    <c- k>constexpr</c-> <c- k>auto</c-> <c- n>annotations</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>define_static_array</c-><c- p>(</c->
        <c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>annotations_of</c-><c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>reflect_constant</c-><c- p>(</c-><c- n>violation</c-><c- p>))</c->
    <c- p>);</c->
    <c- c1>// Use annotations...</c->
<c- p>}</c->
</pre>
   <p>However, this is both incredibly verbose and also requires <code class="highlight"><c- n>contract_violation</c-></code> to be a structural type. On its own, this is not a problem since the only APIs specified for that type are several member functions; however, this prohibits the implementation from providing private members to store the location and comments, etc.. Therefore, for ease of use and to permit more flexibility, the author suggests providing a new magic member function <code class="highlight"><c- k>consteval</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-><c- o>></c-> <c- n>annotations</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-></code> to the contract violation class, with the return value magically filled with the annotations' reflections.</p>
   <p>The following table showcases the new API design:</p>
   <table>
    <thead>
     <tr>
      <td><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> API Design
      <td>Proposed API Design
    <tbody>
     <tr>
      <td>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>contracts</c->
<c- p>{</c->
    <c- k>class</c-> <c- nc>contract_violation</c->
    <c- p>{</c->
    <c- k>public</c-><c- o>:</c->
        <c- c1>// ...</c->
        <c- b>void</c-> <c- o>*</c-><c- n>control_object</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
        <c- c1>// ...</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
      <td>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>contracts</c->
<c- p>{</c->
    <c- k>class</c-> <c- nc>contract_violation</c->
    <c- p>{</c->
    <c- k>public</c-><c- o>:</c->
        <c- c1>// ...</c->
        <c- k>consteval</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-><c- o>></c-> <c- n>annotations</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
        <c- c1>// ...</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
     <tr>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_dynamic_tag</c->
<c- p>{</c->
    <c- k>constexpr</c-> <c- n>my_dynamic_tag</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>constexpr</c-> <c- k>virtual</c-> <c- o>~</c-><c- n>my_dynamic_tag</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
<c- p>};</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <c- n>my_dynamic_tag</c-> <c- n>my_dynamic_label</c-><c- p>;</c->

<c- b>void</c-> <c- nf>handle_contract_violation</c-><c- p>(</c-><c- k>const</c-> <c- n>contract_violation</c-><c- o>&amp;</c-> <c- n>violation</c-><c- p>)</c->
<c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><c- k>auto</c-><c- o>*</c-> <c- n>dynamic_tag</c-> <c- o>=</c->
        <c- k>dynamic_cast</c-><c- o>&lt;</c-><c- n>my_dynamic_tag</c-><c- o>*></c-><c- p>(</c-><c- n>violation</c-><c- p>.</c-><c- n>control_object</c-><c- p>())</c-> <c- o>!=</c-> <c- k>nullptr</c-><c- p>)</c->
    <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Dynamic Tag!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
    <c- p>}</c->
    <c- k>else</c->
    <c- p>{</c->
        <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"No Dynamic Tag</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
    <c- p>}</c->
<c- p>}</c->
<c- b>void</c-> <c- n>f</c-><c- p>()</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>my_dynamic_label</c-><c- o>></c-><c- p>(</c->false<c- p>)</c-> <c- c1>// prints "Dynamic Tag!"</c->
    <c- n>pre</c-><c- p>(</c->false<c- p>);</c-> <c- c1>// prints "No Dynamic Tag"</c->
</pre>
      <td>
<pre class="language-cpp highlight"><c- k>struct</c-> <c- nc>my_dynamic_tag</c->
<c- p>{</c->
    <c- k>constexpr</c-> <c- n>my_dynamic_tag</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
<c- p>};</c->
<c- kr>inline</c-> <c- k>constexpr</c-> <c- n>my_dynamic_tag</c-> <c- n>my_dynamic_label</c-><c- p>;</c->

<c- b>void</c-> <c- nf>handle_contract_violation</c-><c- p>(</c-><c- k>const</c-> <c- n>contract_violation</c-><c- o>&amp;</c-> <c- n>violation</c-><c- p>)</c->
<c- p>{</c->
    <c- k>constexpr</c-> <c- k>auto</c-> <c- n>annotations</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>define_static_array</c-><c- p>(</c-><c- n>violation</c-><c- p>.</c-><c- n>annotations</c-><c- p>());</c->
    <c- k>template</c-> <c- k>for</c-> <c- p>(</c-><c- k>constexpr</c-> <c- k>auto</c-> <c- n>annotation</c-> <c- o>:</c-> <c- n>annotations</c-><c- p>)</c->
    <c- p>{</c->
        <c- k>if</c-> <c- k>constexpr</c-> <c- p>(</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>is_same_type</c-><c- p>(</c->
            <c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>type_of</c-><c- p>(</c-><c- n>annotation</c-><c- p>),</c-> <c- o>^^</c-><c- n>my_dynamic_tag</c->
        <c- p>))</c->
        <c- p>{</c->
            <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"Dynamic Tag!</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
            <c- k>return</c-><c- p>;</c->
        <c- p>}</c->
    <c- p>}</c->
    <c- n>std</c-><c- o>::</c-><c- n>cout</c-> <c- o>&lt;&lt;</c-> <c- s>"No Dynamic Tag</c-><c- se>\n</c-><c- s>"</c-><c- p>;</c->
<c- p>}</c->
<c- b>void</c-> <c- n>f</c-><c- p>()</c->
    <c- n>pre</c-><c- o>&lt;</c-><c- n>my_dynamic_label</c-><c- o>></c-><c- p>(</c->false<c- p>)</c-> <c- c1>// prints "Dynamic Tag!"</c->
    <c- n>pre</c-><c- p>(</c->false<c- p>);</c-> <c- c1>// prints "No Dynamic Tag"</c->
</pre>
     <tr>
      <td>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>contracts</c->
<c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>typename</c-> <c- nc>T</c-><c- o>></c->
    <c- n>T</c-><c- o>*</c-> <c- n>get_constituent_label</c-><c- p>(</c-><c- b>void</c-><c- o>*</c-> <c- n>control_object</c-><c- p>);</c->
<c- p>}</c->
</pre>
      <td>
<pre class="language-cpp highlight"><c- k>namespace</c-> <c- nn>std</c-><c- o>::</c-><c- nn>contracts</c->
<c- p>{</c->
    <c- k>consteval</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-><c- o>></c-> <c- n>get_constituent_label</c-><c- p>(</c->
        <c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-> <c- n>label</c-><c- p>);</c->
    <c- c1>// for convenience, similar to annotations_of_with_type</c->
    <c- k>template</c-> <c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>reflection_range</c-> <c- n>R</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>initializer_list</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-><c- o>>></c->
    <c- k>consteval</c-> <c- n>std</c-><c- o>::</c-><c- n>vector</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-><c- o>></c-> <c- n>get_label_with_type</c-><c- p>(</c->
        <c- n>R</c-><c- o>&amp;&amp;</c-> <c- n>labels</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>meta</c-><c- o>::</c-><c- n>info</c-> <c- n>type</c-><c- p>);</c->
<c- p>}</c->
</pre>
   </table>
   <h3 class="heading settled" data-level="3.5" id="proposal-5-design"><span class="secno">3.5. </span><span class="content">Proposal 5: Ambient-Control Objects</span><a class="self-link" href="#proposal-5-design"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> identifies that often, all declarations in a scope may want to attach the same contract labels. To achieve this, the proposal introduces implicit control-object declarations in the form of <code class="highlight"><c- n>contract_assert</c-> <c- n>implicit</c-> <c- o>&lt;</c-><c- n>label</c-><c- o>></c-><c- p>;</c-></code> (we can change <code class="highlight"><c- o>&lt;</c-><c- n>label</c-><c- o>></c-></code> to <code class="highlight"><c- p>[[</c-><c- o>=</c-><c- n>label</c-><c- p>]]</c-></code> for consistency) that automatically add <code class="highlight"><c- n>label</c-></code> to all the contract assertions in the same scope. However, there are several design decisions unanswered for this facility:</p>
   <ul>
    <li data-md>
     <p>Is the label prepended to all contract assertions' label list, or appended to it? This can be significant if <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> is not symmetric.</p>
    <li data-md>
     <p>Why are multiple declarations prohibited? Injecting multiple labels is clearly useful.</p>
    <li data-md>
     <p>Is it possible to "inherit" base class/enclosing namespace’s implicit contract labels?</p>
   </ul>
   <p>Moreover, <a data-link-type="biblio" href="#biblio-p3394r4" title="Annotations for Reflection">[P3394R4]</a> pointed out that a more general facility to let annotations have callbacks that are invoked by the declaration has great usefulness. Such a facility, combined with advanced code generation functionalities, can actually give us the implicit labels for free; just attach an annotation to the namespace/class that automatically goes through all the declarations and modifies them to add the labels. The correct way to achieve implicit labels is thus perhaps providing a <code class="highlight"><c- p>[[</c-><c- o>=</c-><c- n>attach</c-><c- p>(</c-><c- n>label1</c-><c- p>,</c-> <c- n>label2</c-><c- p>)]]</c-></code> instead of a new kind of statement. As a result, the author recommends delaying the adoption of implicit label statements in anticipation of a more general annotation callback facility.</p>
   <h3 class="heading settled" data-level="3.6" id="controllable-properties"><span class="secno">3.6. </span><span class="content">Controllable Properties</span><a class="self-link" href="#controllable-properties"></a></h3>
   <p>The rest of <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a> is not directly relevant to this proposal, as they do not touch the syntax of labels. However, SG21 may want to consider changing to a design based on metafunctions instead for things like identification labels; although using the proposed concept with a splicer is possible, doing it directly may be more beneficial.</p>
   <h3 class="heading settled" data-level="3.7" id="possible-issues"><span class="secno">3.7. </span><span class="content">Possible Issues</span><a class="self-link" href="#possible-issues"></a></h3>
   <p>The main issue that the author foresees with this proposal is the fact that relying on annotation syntax puts a hard dependency on reflection for Contracts; <code class="highlight"><c- o>&lt;</c-><c- n>contracts</c-><c- o>></c-></code> may even need to include <code class="highlight"><c- o>&lt;</c-><c- n>meta</c-><c- o>></c-></code> (or move the proposed metafunctions there?), and fetching annotations will become very template/reflection-heavy. However, labels are conceptually the same as annotations, and annotations are inherently a reflection-based feature, so such dependency is probably inevitable.</p>
   <h2 class="heading settled" data-level="4" id="suggestions"><span class="secno">4. </span><span class="content">Suggestions</span><a class="self-link" href="#suggestions"></a></h2>
   <p>In conclusion, this proposal suggests the following changes to <a data-link-type="biblio" href="#biblio-p3400r1" title="Specifying Contract Assertion Properties with Labels">[P3400R1]</a>:</p>
   <ol>
    <li data-md>
     <p>Use annotation syntax <code class="highlight"><c- n>pre</c-> <c- p>[[</c-><c- o>=</c-><c- n>label</c-><c- p>]]</c-> <c- p>(</c-><c- n>expr</c-><c- p>)</c-></code> instead of <code class="highlight"><c- n>pre</c-><c- o>&lt;</c-><c- n>label</c-><c- o>></c-><c- p>(</c-><c- n>expr</c-><c- p>)</c-></code>.</p>
    <li data-md>
     <p>Allow multiple annotations to attach to a contract assertion, and optionally remove <code class="highlight"><c- k>operator</c-><c- o>|</c-></code> while waiting for a more general annotation combination facility. The combination logic can instead be represented in the default implementation of the contract violation handler.</p>
    <li data-md>
     <p>Adopt the <code class="highlight"><c- k>using</c-></code> prefix for annotations, and remove the <code class="highlight"><c- n>contract_assert</c-> <c- k>using</c-></code> declarations.</p>
    <li data-md>
     <p>Provide a <code class="highlight"><c- k>consteval</c-> <c- n>vector</c-><c- o>&lt;</c-><c- n>info</c-><c- o>></c-> <c- n>annotations</c-><c- p>()</c-></code> member function instead of the unsafe <code class="highlight"><c- b>void</c-><c- o>*</c-></code>-returning member function, and optionally provide metafunctions to get labels with a specific type.</p>
    <li data-md>
     <p>Remove implicit label statements, and wait for a more general annotation callback facility.</p>
   </ol>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

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

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

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

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

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

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


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

    tocNav.appendChild(toggle);
  }

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

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

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

})();
</script>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
  <dl>
   <dt id="biblio-p2900r14">[P2900R14]
   <dd>Joshua Berne, Timur Doumler, Andrzej Krzemieński. <a href="https://wg21.link/p2900r14"><cite>Contracts for C++</cite></a>. 14 February 2025. URL: <a href="https://wg21.link/p2900r14">https://wg21.link/p2900r14</a>
   <dt id="biblio-p3394r4">[P3394R4]
   <dd>Daveed Vandevoorde, Wyatt Childers, Dan Katz, Barry Revzin. <a href="https://wg21.link/p3394r4"><cite>Annotations for Reflection</cite></a>. 20 June 2025. URL: <a href="https://wg21.link/p3394r4">https://wg21.link/p3394r4</a>
   <dt id="biblio-p3400r1">[P3400R1]
   <dd>Joshua Berne. <a href="https://wg21.link/p3400r1"><cite>Specifying Contract Assertion Properties with Labels</cite></a>. 28 February 2025. URL: <a href="https://wg21.link/p3400r1">https://wg21.link/p3400r1</a>
  </dl>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-attribute-critics">[ATTRIBUTE-CRITICS]
   <dd>Barry Revzin. <a href="https://brevzin.github.io/c++/2025/03/25/attributes/"><cite>On the Ignorability of Attributes</cite></a>. URL: <a href="https://brevzin.github.io/c++/2025/03/25/attributes/">https://brevzin.github.io/c++/2025/03/25/attributes/</a>
   <dt id="biblio-p0028r4">[P0028R4]
   <dd>J. Daniel Garcia, Daveed Vandevoorde. <a href="https://wg21.link/p0028r4"><cite>Using attribute namespaces without repetition</cite></a>. 22 June 2016. URL: <a href="https://wg21.link/p0028r4">https://wg21.link/p0028r4</a>
   <dt id="biblio-p0542r5">[P0542R5]
   <dd>J. Daniel Garcia. <a href="https://wg21.link/p0542r5"><cite>Support for contract based programming in C++</cite></a>. 8 June 2018. URL: <a href="https://wg21.link/p0542r5">https://wg21.link/p0542r5</a>
   <dt id="biblio-p2996r13">[P2996R13]
   <dd>Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton, Faisal Vali, Daveed Vandevoorde, Dan Katz. <a href="https://wg21.link/p2996r13"><cite>Reflection for C++26</cite></a>. 20 June 2025. URL: <a href="https://wg21.link/p2996r13">https://wg21.link/p2996r13</a>
   <dt id="biblio-p3088r1">[P3088R1]
   <dd>Timur Doumler, Joshua Berne. <a href="https://wg21.link/p3088r1"><cite>Attributes for contract assertions</cite></a>. 13 February 2024. URL: <a href="https://wg21.link/p3088r1">https://wg21.link/p3088r1</a>
   <dt id="biblio-p3385r5">[P3385R5]
   <dd>Aurelien Cassagnes. <a href="https://wg21.link/p3385r5"><cite>Attributes reflection</cite></a>. 19 May 2025. URL: <a href="https://wg21.link/p3385r5">https://wg21.link/p3385r5</a>
   <dt id="biblio-p3394r3">[P3394R3]
   <dd>Daveed Vandevoorde, Wyatt Childers, Dan Katz, Barry Revzin. <a href="https://wg21.link/p3394r3"><cite>Annotations for Reflection</cite></a>. 17 May 2025. URL: <a href="https://wg21.link/p3394r3">https://wg21.link/p3394r3</a>
   <dt id="biblio-p3589r2">[P3589R2]
   <dd>Gabriel Dos Reis. <a href="https://wg21.link/p3589r2"><cite>C++ Profiles: The Framework</cite></a>. 19 May 2025. URL: <a href="https://wg21.link/p3589r2">https://wg21.link/p3589r2</a>
   <dt id="biblio-p3661r0">[P3661R0]
   <dd>Andrzej Krzemieński. <a href="https://wg21.link/p3661r0"><cite>Attributes, annotations, labels</cite></a>. 15 March 2025. URL: <a href="https://wg21.link/p3661r0">https://wg21.link/p3661r0</a>
  </dl>