<!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>p0873R0: A plea for a consistent, terse and intuitive declaration 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
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

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

	body {
		counter-reset: example figure issue;

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	p {
		margin: 1em 0;
	}

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

  /* Do something nice. */

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

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

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

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

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

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

	img {
		border-style: none;
	}

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

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

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

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

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

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

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

	blockquote {
		border-color: silver;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


/*
Alternate table alignment rules

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

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

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

Possible extra rowspan handling

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

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

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


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

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

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

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

	.toc > li             { margin: 1.5rem 0;    }
	.toc > li li          { margin: 0.3rem 0;    }
	.toc > li li li       { margin-left: 2rem;   }

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

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

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

	.toc li {
		clear: both;
	}


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

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

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

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

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

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

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

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

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

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

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



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

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

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

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
  <meta content="Bikeshed version 67155cabad72a8ab669a7d4421c90e2999a29b68" name="generator">
  <link href="https://cor3ntin.github.io/CPPProposals/unified_concept_declaration_syntax/concepts.html" rel="canonical">
  <meta content="deec88bcdb627d8cb89047e73b50d54eb08c1898" name="document-revision">
<style>

.table1-decls table {
    table-layout: fixed;
    width:100%;

}

.table1-decls th {
    text-align: center;
    padding-right:20px;
}

.table1-decls  td {
height:110px;
vertical-align:top;
padding-right:20px;
}

.table1-decls pre {
height:100%;
display:block;
}

</style>
<style>/* style-md-lists */

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

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

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

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

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
.highlight .c { color: #708090 } /* Comment */
.highlight .k { color: #990055 } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #0077aa } /* Name */
.highlight .o { color: #999999 } /* Operator */
.highlight .p { color: #999999 } /* Punctuation */
.highlight .cm { color: #708090 } /* Comment.Multiline */
.highlight .cp { color: #708090 } /* Comment.Preproc */
.highlight .c1 { color: #708090 } /* Comment.Single */
.highlight .cs { color: #708090 } /* Comment.Special */
.highlight .kc { color: #990055 } /* Keyword.Constant */
.highlight .kd { color: #990055 } /* Keyword.Declaration */
.highlight .kn { color: #990055 } /* Keyword.Namespace */
.highlight .kp { color: #990055 } /* Keyword.Pseudo */
.highlight .kr { color: #990055 } /* Keyword.Reserved */
.highlight .kt { color: #990055 } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #000000 } /* Literal.Number */
.highlight .s { color: #a67f59 } /* Literal.String */
.highlight .na { color: #0077aa } /* Name.Attribute */
.highlight .nc { color: #0077aa } /* Name.Class */
.highlight .no { color: #0077aa } /* Name.Constant */
.highlight .nd { color: #0077aa } /* Name.Decorator */
.highlight .ni { color: #0077aa } /* Name.Entity */
.highlight .ne { color: #0077aa } /* Name.Exception */
.highlight .nf { color: #0077aa } /* Name.Function */
.highlight .nl { color: #0077aa } /* Name.Label */
.highlight .nn { color: #0077aa } /* Name.Namespace */
.highlight .py { color: #0077aa } /* Name.Property */
.highlight .nt { color: #669900 } /* Name.Tag */
.highlight .nv { color: #222222 } /* Name.Variable */
.highlight .ow { color: #999999 } /* Operator.Word */
.highlight .mb { color: #000000 } /* Literal.Number.Bin */
.highlight .mf { color: #000000 } /* Literal.Number.Float */
.highlight .mh { color: #000000 } /* Literal.Number.Hex */
.highlight .mi { color: #000000 } /* Literal.Number.Integer */
.highlight .mo { color: #000000 } /* Literal.Number.Oct */
.highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
.highlight .sc { color: #a67f59 } /* Literal.String.Char */
.highlight .sd { color: #a67f59 } /* Literal.String.Doc */
.highlight .s2 { color: #a67f59 } /* Literal.String.Double */
.highlight .se { color: #a67f59 } /* Literal.String.Escape */
.highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
.highlight .si { color: #a67f59 } /* Literal.String.Interpol */
.highlight .sx { color: #a67f59 } /* Literal.String.Other */
.highlight .sr { color: #a67f59 } /* Literal.String.Regex */
.highlight .s1 { color: #a67f59 } /* Literal.String.Single */
.highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
.highlight .vc { color: #0077aa } /* Name.Variable.Class */
.highlight .vg { color: #0077aa } /* Name.Variable.Global */
.highlight .vi { color: #0077aa } /* Name.Variable.Instance */
.highlight .il { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-selflinks */

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

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

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

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

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

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">p0873R0<br>A plea for a consistent, terse and intuitive declaration syntax</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2017-11-27">2017-11-27</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://cor3ntin.github.io/CPPProposals/unified_concept_declaration_syntax/concepts.html">https://cor3ntin.github.io/CPPProposals/unified_concept_declaration_syntax/concepts.html</a>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:corentin.jabot@gmail.com">Corentin jabot</a>
     <dt>Audience:
     <dd>EWG, SG8
     <dt>Project:
     <dd>ISO JTC1/SC22/WG21: Programming Language C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>A unified variables and parameters declaration syntax for concepts</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#existing-declaration-syntaxes-in-c17"><span class="secno">1.1</span> <span class="content">Existing declaration syntaxes in C++17</span></a>
      <li><a href="#inconsistencies-and-confusing-syntax"><span class="secno">1.2</span> <span class="content">Inconsistencies and confusing syntax</span></a>
     </ol>
    <li>
     <a href="#proposed-solution"><span class="secno">2</span> <span class="content">Proposed Solution</span></a>
     <ol class="toc">
      <li><a href="#allow-auto-as-a-parameter-in-functions"><span class="secno">2.1</span> <span class="content">Allow auto as a parameter in functions</span></a>
      <li><a href="#consistent-use-of-auto-and-typename"><span class="secno">2.2</span> <span class="content">Consistent use of auto and typename</span></a>
      <li><a href="#allow-multiple-constraints-for-each-type"><span class="secno">2.3</span> <span class="content">Allow Multiple constraints for each type</span></a>
      <li>
       <a href="#allow-use-of-concepts-consistently-and-uniformly"><span class="secno">2.4</span> <span class="content">Allow use of concepts consistently and uniformly.</span></a>
       <ol class="toc">
        <li><a href="#function-parameters"><span class="secno">2.4.1</span> <span class="content">Function parameters</span></a>
        <li><a href="#function-return-type"><span class="secno">2.4.2</span> <span class="content">Function return type</span></a>
        <li>
         <a href="#variable-declaration"><span class="secno">2.4.3</span> <span class="content">Variable declaration</span></a>
         <ol class="toc">
          <li><a href="#a-note-on-usage-of-concepts-constraints-in-non-template-context"><span class="secno">2.4.3.1</span> <span class="content">A note on usage of concepts constraints in non-template context.</span></a>
         </ol>
        <li><a href="#dependant-names"><span class="secno">2.4.4</span> <span class="content">Dependant names</span></a>
        <li><a href="#type-id-alias-declarations"><span class="secno">2.4.5</span> <span class="content">type-id alias declarations</span></a>
        <li><a href="#dont-allow-constraints-everywhere"><span class="secno">2.4.6</span> <span class="content">Don’t allow Constraints everywhere</span></a>
       </ol>
      <li>
       <a href="#grammar"><span class="secno">2.5</span> <span class="content">Grammar</span></a>
       <ol class="toc">
        <li><a href="#summary"><span class="secno">2.5.1</span> <span class="content">Summary</span></a>
       </ol>
     </ol>
    <li><a href="#multiple-parameters-constrained-by-the-same-concept"><span class="secno">3</span> <span class="content">Multiple Parameters constrained by the same concept</span></a>
    <li>
     <a href="#on-whether-auto-should-be-optional"><span class="secno">4</span> <span class="content">On whether <code class="highlight"><span class="k">auto</span></code> should be optional.</span></a>
     <ol class="toc">
      <li><a href="#auto-in-functions"><span class="secno">4.1</span> <span class="content">As the type of a callable template parameter ( <code class="highlight"><span class="k">auto</span></code> means generic )</span></a>
      <li><a href="#as-the-type-of-a-return-type-or-variable-declaration-auto-means-inferred"><span class="secno">4.2</span> <span class="content">As the type of a return type or variable declaration ( <code class="highlight"><span class="k">auto</span></code> means inferred )</span></a>
     </ol>
    <li><a href="#acknowledgments-and-thanks"><span class="secno">5</span> <span class="content">Acknowledgments and Thanks</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>This paper aims to provide a uniform and intuitive syntax to declare function
parameters, template parameters,
lambda parameters and variables,  principally with regard to the concept TS.</p>
   <p>In particular, using function template parameters is often needlessly
ceremonious, and inconsistencies have started to appear in in the language. For
example, lambdas can have inferred auto parameters while functions can’t.</p>
   <p>These factors contribute to make C++ harder to teach and encourage juniors
developers to mindlessly
add token until “it compiles”, regardless of whether the final program is
semantically correct.</p>
   <h3 class="heading settled" data-level="1.1" id="existing-declaration-syntaxes-in-c17"><span class="secno">1.1. </span><span class="content">Existing declaration syntaxes in C++17</span><a class="self-link" href="#existing-declaration-syntaxes-in-c17"></a></h3>
   <p>Qualifiers notwithstanding, here is a list of existing way to refer to a type
in declarations</p>
   <table class="table1-decls">
    <tbody>
     <tr>
      <th> Template parameters 
      <th> Function parameters 
      <th> Lambda parameters 
      <th> Variable declaration 
     <tr>
      <td>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="o">|</span><span class="k">class</span> <span class="nc">T</span><span class="o">></span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">auto</span> <span class="n">T</span><span class="o">></span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">literal</span> <span class="n">T</span><span class="o">></span>
</pre>
      <td>
<pre class="highlight"><span class="n">Type</span>
</pre>
      <td>
<pre class="highlight"><span class="n">Type</span>
<span class="k">auto</span>
</pre>
      <td>
<pre class="highlight"><span class="n">Type</span>
<span class="k">auto</span>
</pre>
   </table>
   <p>The concept proposal in its current form ( <a data-link-type="biblio" href="#biblio-p0734r0">[P0734R0]</a> would add for template parameters:</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">constraint</span> <span class="n">T</span><span class="o">></span>
</pre>
   <h3 class="heading settled" data-level="1.2" id="inconsistencies-and-confusing-syntax"><span class="secno">1.2. </span><span class="content">Inconsistencies and confusing syntax</span><a class="self-link" href="#inconsistencies-and-confusing-syntax"></a></h3>
   <p>As things stands, we notice a number of inconsistencies:</p>
   <ul>
    <li data-md="">
     <p>Lambdas can be made generic with <code class="highlight"><span class="k">auto</span></code> parameters, while functions can not.
a side effect of that is that function template declaration is needlessly
ceremonious</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Regular</span> <span class="n">R</span><span class="o">></span>
<span class="kt">void</span> <span class="n">foo</span><span class="p">(</span><span class="n">R</span> <span class="o">&amp;</span> <span class="n">r</span><span class="p">);</span>
</pre>
    <li data-md="">
     <p>A single constraint can be applied to a template parameter, while variables
declaration and lambda cannot be constrained.</p>
    <li data-md="">
     <p>It is not possible to specify multiple constraints.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="proposed-solution"><span class="secno">2. </span><span class="content">Proposed Solution</span><a class="self-link" href="#proposed-solution"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="allow-auto-as-a-parameter-in-functions"><span class="secno">2.1. </span><span class="content">Allow auto as a parameter in functions</span><a class="self-link" href="#allow-auto-as-a-parameter-in-functions"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p0587r0">[P0587r0]</a> argue against allowing <code class="highlight"><span class="k">auto</span></code> in function. However, in order to be
consistent with lambdas and for the sake of being terse, the declaration of <code class="highlight"><span class="n">f</span><span class="p">(</span><span class="k">auto</span> <span class="n">a</span><span class="p">)</span></code> should be valid.</p>
   <p>Note that the presence of <code class="highlight"><span class="k">auto</span></code> is enough to inform the reader that the
function is in fact a function template.</p>
   <p><code class="highlight"><span class="k">template</span><span class="o">&lt;</span><span class="p">...</span><span class="o">></span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="k">auto</span> <span class="n">a</span><span class="p">)</span></code> (as proposed by <a data-link-type="biblio" href="#biblio-p0587r0">[P0587r0]</a>) does not offer any
extra information to the user of the function ( nor the compiler ).</p>
   <p>Lambda now accepts either a template parameters list, auto parameters or any combination of the
two, with great effect. It’s a syntax that developers are already familiar with and it would only
be natural for it to be used for functions too, for consistency and simplicity.</p>
   <p>There is a wording inconsistency between <code class="highlight"><span class="n">function</span> <span class="k">template</span></code> and <code class="highlight"><span class="n">generic</span> <span class="n">lambda</span></code>. That may need to
be addressed. I would suggest that <code class="highlight"><span class="n">lambda</span> <span class="k">template</span></code> would be a more accurate and consistent
wording.</p>
   <h3 class="heading settled" data-level="2.2" id="consistent-use-of-auto-and-typename"><span class="secno">2.2. </span><span class="content">Consistent use of auto and typename</span><a class="self-link" href="#consistent-use-of-auto-and-typename"></a></h3>
   <ul>
    <li data-md="">
     <p>As it is already the case, <code class="highlight"><span class="k">typename</span></code> is a placeholder for a type, while <code class="highlight"><span class="k">auto</span></code> is the placeholder of a value of an inferred type. This behaviour
 should remain consistent.</p>
    <li data-md="">
     <p>Moreover, <code class="highlight"><span class="k">typename</span></code> or <code class="highlight"><span class="k">auto</span></code> should <em>always</em> be usable where they are usable today, even in the
presence of a concept declaration.</p>
   </ul>
   <p>However they are not required in a template parameter declaration. For
example, <code class="highlight"><span class="n">Even</span> <span class="n">T</span></code> and <code class="highlight"><span class="n">Even</span> <span class="k">auto</span> <span class="n">T</span></code> are unambiguous declarations and the latter
can be deduced from the former. Therefore, both declaration are
well-formed.
A set of concepts can be defined or provided by the standard library to further constrain the
nature of the non-type non-template template parameters a template accepts. <code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Pointer</span> <span class="n">P</span><span class="o">></span></code>, <code class="highlight"><span class="k">template</span><span class="o">&lt;</span><span class="n">Reference</span> <span class="n">R</span><span class="o">></span></code>, <code class="highlight"><span class="k">template</span><span class="o">&lt;</span><span class="n">Integral</span> <span class="n">I</span><span class="o">></span></code> ...</p>
   <p>It is important to note that a given concept can not be applied to both a type
and a value, so there is never any ambiguity between <code class="highlight"><span class="k">typename</span></code> and <code class="highlight"><span class="k">auto</span></code> in a
template parameter declaration.</p>
   <p>Notably:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Regular</span> <span class="k">typename</span> <span class="n">T</span><span class="o">></span></code> and <code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Regular</span> <span class="n">T</span><span class="o">></span></code> are both valid,
equivalent declarations</p>
    <li data-md="">
     <p><code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Even</span> <span class="k">auto</span> <span class="n">T</span><span class="o">></span></code> and <code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Even</span> <span class="n">T</span><span class="o">></span></code> are both valid,
equivalent declarations</p>
    <li data-md="">
     <p><code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">Even</span> <span class="kt">int</span> <span class="n">N</span><span class="o">></span></code> can be used in the same fashion to restrict a
literal on its value while specifying its type.  In this context <code class="highlight"><span class="kt">int</span></code> can be thought of as a
constraint on the type the value <code class="highlight"><span class="n">N</span></code> can have.</p>
   </ul>
   <h3 class="heading settled" data-level="2.3" id="allow-multiple-constraints-for-each-type"><span class="secno">2.3. </span><span class="content">Allow Multiple constraints for each type</span><a class="self-link" href="#allow-multiple-constraints-for-each-type"></a></h3>
   <ul>
    <li data-md="">
     <p>As proposed by both <a data-link-type="biblio" href="#biblio-p0807r0">[p0807r0]</a> and <a data-link-type="biblio" href="#biblio-p0791r0">[p0791r0]</a>, a declaration can be constrained by multiple
concepts in conjunction, such that the following declarations are semantically equivalent.</p>
   </ul>
   <p>A template instantiation must satisfy each and every constrained to be well-formed.</p>
   <p>For example:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="n">C1</span> <span class="n">C2</span> <span class="n">Foo</span><span class="o">></span></code> and <code class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Foo</span><span class="o">></span> <span class="n">requires</span> <span class="n">C1</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span> <span class="o">&amp;&amp;</span> <span class="n">C2</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span></code> are semantically
equivalent.</p>
   </ul>
   <p><a data-link-type="biblio" href="#biblio-p0791r0">[p0791r0]</a> further suggests to allow passing concepts as parameters to templates in order to
compose various logic constructs, in addition to the existing <code class="highlight"><span class="n">requires</span></code> clause. However this is a
separate issue that probably needs its own paper, as it is an orthogonal consideration.</p>
   <p>I don’t think however that allowing complex concept-based logic constructs in abbreviated function
templates or variable declarations would lead to more readable code.</p>
   <p>Consider <code class="highlight"><span class="n">Iterable</span> <span class="o">!</span><span class="n">ForwardIterable</span> <span class="k">auto</span> <span class="n">f</span><span class="p">(</span><span class="n">Movable</span><span class="o">&amp;&amp;</span><span class="p">(</span><span class="n">CopyConstructible</span><span class="o">||</span><span class="n">Swappable</span><span class="p">)</span> <span class="n">foo</span><span class="p">);</span></code></p>
   <p>I would argue that this declaration is <em>less</em> readable. The terse, "abbreviated function
template" form should handle simple cases. If a type needs to be constrained on complex
requirements, then it is certainly better to either introduce a new concept for these specific
requirements or to write a proper requires-clause.</p>
   <h3 class="heading settled" data-level="2.4" id="allow-use-of-concepts-consistently-and-uniformly"><span class="secno">2.4. </span><span class="content">Allow use of concepts consistently and uniformly.</span><a class="self-link" href="#allow-use-of-concepts-consistently-and-uniformly"></a></h3>
   <h4 class="heading settled" data-level="2.4.1" id="function-parameters"><span class="secno">2.4.1. </span><span class="content">Function parameters</span><a class="self-link" href="#function-parameters"></a></h4>
   <p>Of course, template functions and lambdas can be constrained.</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">Sortable</span> <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">foo</span><span class="p">)</span></code> : A template function with a
constrained parameter</p>
    <li data-md="">
     <p><code class="highlight"><span class="p">[](</span><span class="n">Dividable</span> <span class="n">Multipliable</span> <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">foo</span><span class="p">);</span></code> : A template lambda with a
constrained parameter</p>
   </ul>
   <p>In both function templates and lambda templates, the keyword auto is required to denote that the
callable entity is a template and will need to be instantiated. This is explained more further
in : <a href="#auto-in-functions">§4.1 As the type of a callable template parameter ( auto means generic )</a> .</p>
   <h4 class="heading settled" data-level="2.4.2" id="function-return-type"><span class="secno">2.4.2. </span><span class="content">Function return type</span><a class="self-link" href="#function-return-type"></a></h4>
   <p>The following declaration declare a non-template function with an
automatically deduced type which satisfies the <code class="highlight"><span class="n">Sortable</span></code> constraint:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">Sortable</span> <span class="k">auto</span> <span class="nf">f</span><span class="p">();</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="n">Sortable</span> <span class="k">auto</span> <span class="nf">f</span><span class="p">();</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="k">auto</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="n">Sortable</span> <span class="k">auto</span><span class="p">;</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="k">auto</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="n">Sortable</span><span class="p">;</span></code></p>
   </ul>
   <p>A program is ill-formed if the deduced type of the function does not satisfies
one of the constraints declared in the return type.
For the sake of sanity, specifying different concepts in both the return type and the trailing
return type should be ill-formed.</p>
   <p><code class="highlight"><span class="n">Sortable</span> <span class="k">auto</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="n">Iterable</span> <span class="k">auto</span> <span class="p">{};</span> <span class="c1">// ill-formed</span></code></p>
   <h4 class="heading settled" data-level="2.4.3" id="variable-declaration"><span class="secno">2.4.3. </span><span class="content">Variable declaration</span><a class="self-link" href="#variable-declaration"></a></h4>
   <p>Constraints can be used to refine the type of a variable declaration.</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">AssociativeContainer</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="kt">int</span><span class="o">></span> <span class="k">auto</span> <span class="n">map</span> <span class="o">=</span> <span class="n">getMap</span><span class="p">();</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="n">Iterable</span> <span class="n">AssociativeContainer</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="kt">int</span><span class="o">></span> <span class="n">map</span> <span class="o">=</span> <span class="n">getMap</span><span class="p">();</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="k">constexpr</span> <span class="n">Even</span> <span class="kt">int</span> <span class="n">answer</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span></code></p>
    <li data-md="">
     <p><code class="highlight"><span class="k">constexpr</span> <span class="n">Even</span> <span class="n">answer</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span></code></p>
   </ul>
   <p>The program is ill-formed if one of the constraint is not satisfied.</p>
   <p>As a generalization, and maybe as a mean to generate better diagnostic, I
propose that constraints can be applied to non-template or instantiated type.
It would serve as a sort of static_assert ensuring that a type keeps the
properties the user is expecting.</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">Iterable</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span></code></p>
   </ul>
   <h5 class="heading settled" data-level="2.4.3.1" id="a-note-on-usage-of-concepts-constraints-in-non-template-context"><span class="secno">2.4.3.1. </span><span class="content">A note on usage of concepts constraints in non-template context.</span><a class="self-link" href="#a-note-on-usage-of-concepts-constraints-in-non-template-context"></a></h5>
   <p><code class="highlight"><span class="n">Iterable</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span></code> mays seems odd in first approach, but, it’s a nice way
to ensure that library and client code remain compatible, and to easily diagnostic what may have
been modified and what why the type’s expected properties changed.</p>
   <p>It also provides documentation about what the type is going to be used for.</p>
   <p>And most importantly, it allow to generalize the notion of constraint and make
it consistent through the language.</p>
   <p>Specifying concepts that a concrete type is expected to satisfy is not
something that I expect to see often, but it could be useful in code
bases that are fast changing.</p>
   <h4 class="heading settled" data-level="2.4.4" id="dependant-names"><span class="secno">2.4.4. </span><span class="content">Dependant names</span><a class="self-link" href="#dependant-names"></a></h4>
   <p>Constraints could be used to better document the use of a dependant names in
definition of a template, instead of in addition to <code class="highlight"><span class="k">typename</span></code></p>
   <p>consider the following code</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="k">constexpr</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">Bar</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">struct</span> <span class="n">S</span> <span class="p">{</span>
    <span class="k">using</span> <span class="n">Bar</span> <span class="o">=</span> <span class="kt">unsigned</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">constexpr</span> <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">S</span><span class="p">{});</span>
</pre>
   <p>We can replace <code class="highlight"><span class="k">typename</span></code> by a constraint.</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="k">constexpr</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">Unsigned</span> <span class="n">T</span><span class="o">::</span><span class="n">Bar</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <p>Of course, <code class="highlight"><span class="k">typename</span></code> is a valid optional extra token, meaning the following
construct is valid too. Note that we refer to the type <code class="highlight"><span class="n">T</span><span class="o">::</span><span class="n">Bar</span></code> and not to an
instance of <code class="highlight"><span class="n">T</span><span class="o">::</span><span class="n">Bar</span></code>, so the valid token is <code class="highlight"><span class="k">typename</span></code> and not <code class="highlight"><span class="k">auto</span></code>.</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="k">auto</span> <span class="k">constexpr</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">Unsigned</span> <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">Bar</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <p>Both these declarations have identical semantics <code class="highlight"><span class="k">using</span> <span class="n">Foo</span> <span class="o">=</span> <span class="n">Unsigned</span> <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">Bar</span></code> <code class="highlight"><span class="k">using</span> <span class="n">Foo</span> <span class="o">=</span> <span class="n">Unsigned</span> <span class="n">T</span><span class="o">::</span><span class="n">Bar</span></code></p>
   <p>The program is ill-formed if the dependant type does not respect the
constraint(s).
We can, and probably should, convey the same requirements in a requires-clause.
A constraint that cannot be satisfied in the body of a template
instantiation causes the program to be ill-formed, SFINAE is not engaged.</p>
   <h4 class="heading settled" data-level="2.4.5" id="type-id-alias-declarations"><span class="secno">2.4.5. </span><span class="content">type-id alias declarations</span><a class="self-link" href="#type-id-alias-declarations"></a></h4>
   <p>Allow the use of Constraints in using directives, in the same manner:</p>
   <p><code class="highlight"><span class="k">using</span> <span class="n">CopyConstructible</span> <span class="n">Foo</span> <span class="o">=</span> <span class="n">Bar</span><span class="p">;</span></code></p>
   <p><code class="highlight"><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="k">using</span> <span class="n">Swappable</span> <span class="n">Foo</span> <span class="o">=</span> <span class="n">Bar</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="p">;</span></code></p>
   <p>The program is ill-formed if the constraints can not be satisfied.</p>
   <p>Additionally, it may be interesting to constraints parameters of template
using-directives</p>
   <p><code class="highlight"><span class="k">template</span><span class="o">&lt;</span><span class="n">Serializable</span> <span class="n">T</span><span class="o">></span> <span class="k">using</span> <span class="n">Stream</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span> <span class="o">=</span> <span class="n">Iterable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="p">;</span></code></p>
   <p>Here, the <code class="highlight"><span class="n">Stream</span></code> type can only be specialized using types that satisfy the <code class="highlight"><span class="n">Serializable</span></code> constraint.
We use the alias syntax to create a type alias more constrained than the original type.
An alias created in this way is neither a specialization nor a new type. <code class="highlight"><span class="n">Stream</span></code> is exactly of the
type <code class="highlight"><span class="n">Iterable</span></code>, aka <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Stream</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Iterable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span> <span class="o">==</span> true</code>.
However, the alias has additional constraints that are checked upon instantiation.
The constraits on the alias are checked before the constraints on the type it is created from.</p>
   <p>This system would allow the creation of fine-tuned constrained type alias without having to
introduce new types, factories or inheritance.</p>
   <h4 class="heading settled" data-level="2.4.6" id="dont-allow-constraints-everywhere"><span class="secno">2.4.6. </span><span class="content">Don’t allow Constraints everywhere</span><a class="self-link" href="#dont-allow-constraints-everywhere"></a></h4>
   <p>There is a number of places where allowing concepts in front of a type would
either make no sense or be actually harmful.</p>
   <ul>
    <li data-md="">
     <p>sizeof and cast expression : It doesn’t make a lot of sense</p>
    <li data-md="">
     <p>class/struct/union/enum definition</p>
   </ul>
   <h3 class="heading settled" data-level="2.5" id="grammar"><span class="secno">2.5. </span><span class="content">Grammar</span><a class="self-link" href="#grammar"></a></h3>
   <p>In the situations illustrated above, the type-id can be preceded by one or more
qualified-concept-name
The sequence of concept-names and type form the entities to which attributes,
and qualifiers are applied.</p>
<pre class="highlight"><span class="n">Swappable</span> <span class="n">Sortable</span> <span class="n">Writable</span> <span class="n">foo</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">const</span> <span class="n">Swappable</span> <span class="n">Sortable</span> <span class="n">Writable</span> <span class="o">&amp;</span> <span class="n">foo</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">volatile</span> <span class="n">Swappable</span> <span class="n">Sortable</span> <span class="n">Writable</span> <span class="k">auto</span><span class="o">*</span> <span class="n">foo</span> <span class="o">=</span> <span class="p">{};</span>
<span class="n">Swappable</span> <span class="n">Sortable</span> <span class="n">Writable</span> <span class="k">auto</span><span class="o">*</span> <span class="k">const</span><span class="o">*</span> <span class="n">foo</span> <span class="o">=</span> <span class="p">{};</span>
<span class="n">Swappable</span> <span class="n">Sortable</span> <span class="n">Writable</span> <span class="o">&amp;&amp;</span> <span class="n">foo</span><span class="p">;</span>
<span class="k">extern</span> <span class="n">std</span><span class="o">::</span><span class="n">EquallyComparable</span> <span class="n">boost</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">baz</span><span class="p">;</span>
</pre>
   <p><a data-link-type="biblio" href="#biblio-p0791r0">[p0791r0]</a> gives a good justification for this order, in that constraints are like adjectives
applied to a type.</p>
   <p>A simpler explanation is that constraints are applied to an unqualified type-id. And qualifiers
are applied to a constrained type.
Beside the parallel with English grammar rules, putting the concept-names after the type-id would
create ambiguities as to whether the constraints are applied on the type or on a value.</p>
   <p><code class="highlight"><span class="k">auto</span> <span class="n">Sortable</span> <span class="n">v</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code> this would create ambiguity as to whether the type or the value is
qualified by "Sortable".</p>
   <p>Note that, as specified by <a data-link-type="biblio" href="#biblio-p0734r0">[P0734R0]</a> (§17.1), concepts can have template
arguments beside the type of which we are checking the constraints.</p>
<pre class="highlight"><span class="n">Container</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">i</span> <span class="o">=</span> <span class="p">{</span> <span class="cm">/*...*/</span> <span class="p">};</span>
<span class="n">Callable</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="o">></span> <span class="n">f</span> <span class="o">=</span> <span class="p">{</span> <span class="cm">/*...*/</span> <span class="p">};</span>
</pre>
   <h4 class="heading settled" data-level="2.5.1" id="summary"><span class="secno">2.5.1. </span><span class="content">Summary</span><a class="self-link" href="#summary"></a></h4>
   <ul>
    <li data-md="">
     <p>Variable declaration : <code class="highlight"><span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="n">type</span><span class="o">-</span><span class="n">id</span><span class="o">|</span><span class="k">auto</span><span class="o">|</span><span class="k">decltype</span><span class="o">-</span><span class="n">expression</span></code></p>
    <li data-md="">
     <p>Function and lambda parameters  : <code class="highlight"><span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="n">type</span><span class="o">-</span><span class="n">id</span><span class="o">|</span><span class="k">auto</span><span class="o">|</span><span class="k">decltype</span><span class="o">-</span><span class="n">expression</span></code></p>
    <li data-md="">
     <p>Function and lambda return type : <code class="highlight"><span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="n">type</span><span class="o">-</span><span class="n">id</span><span class="o">|</span><span class="p">[</span><span class="k">auto</span><span class="p">]</span><span class="o">|</span><span class="k">decltype</span><span class="o">-</span><span class="n">expression</span></code></p>
    <li data-md="">
     <p>Template parameter: <code class="highlight"><span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="p">[</span><span class="k">typename</span><span class="o">|</span><span class="k">auto</span><span class="p">]</span><span class="o">|</span><span class="n">literal</span><span class="o">-</span><span class="n">type</span><span class="o">-</span><span class="n">id</span> <span class="n">name</span></code></p>
    <li data-md="">
     <p>Alias declaration : <code class="highlight"><span class="k">using</span> <span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="n">name</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code></p>
    <li data-md="">
     <p>Disambiguation in template definition : <code class="highlight"><span class="p">[</span><span class="n">concept</span><span class="o">-</span><span class="n">name</span><span class="p">]</span><span class="o">*</span> <span class="p">[</span><span class="k">typename</span><span class="p">]</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code></p>
   </ul>
   <h2 class="heading settled" data-level="3" id="multiple-parameters-constrained-by-the-same-concept"><span class="secno">3. </span><span class="content">Multiple Parameters constrained by the same concept</span><a class="self-link" href="#multiple-parameters-constrained-by-the-same-concept"></a></h2>
   <p>The meaning of <code class="highlight"><span class="kt">void</span> <span class="n">foo</span><span class="p">(</span><span class="n">ConceptName</span> <span class="k">auto</span><span class="p">,</span> <span class="n">ConceptName</span> <span class="k">auto</span><span class="p">)</span></code> has been the
subject of numerous paper and arguments.
I’m strongly in favor of considering the multiple parameters as different types. <a data-link-type="biblio" href="#biblio-p0464r2">[p0464r2]</a> exposes the arguments in favor of that semantic better that I ever
could.</p>
   <p><code class="highlight"><span class="kt">void</span> <span class="n">foo</span><span class="p">(</span><span class="n">ConceptName</span> <span class="k">auto</span> <span class="n">a</span><span class="p">,</span> <span class="k">decltype</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="n">b</span><span class="p">)</span></code> is probably the
best solution in the general case.</p>
   <p>The following concept can be added to the stl to allow each types to have
different qualifiers.
In fact, the Ranges TS provides a similar utility called <code class="highlight"><span class="n">CommonReference</span></code> <a data-link-type="biblio" href="#biblio-n4651">[N4651]</a> 7.3.5</p>
<pre class="highlight"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">></span>
<span class="n">concept</span> <span class="kt">bool</span> <span class="n">SameType</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">U</span><span class="o">></span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">T</span><span class="o">>></span><span class="p">;</span>

<span class="c1">//</span>
<span class="c1"></span><span class="kt">void</span> <span class="nf">f</span><span class="p">(</span><span class="n">Concept</span> <span class="k">auto</span> <span class="n">a</span><span class="p">,</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="o">></span> <span class="k">auto</span> <span class="n">b</span><span class="p">);</span>
</pre>
   <p>This syntax makes it clear that we want identic types and is, in fact, self documenting.</p>
   <p>It is not strictly identic to the non-terse form in regards to how overloads are resolved. If
we strictly want the behavior of the non-terse syntax in complex overloads sets, then the non-terse
syntaxe should be used.
The terse syntax aims at making the simple case simple, not at replacing all existing forms of
function template declaration.</p>
   <p>Finally, all of these reasons aside, we described how constraints could be used outside of template
parameters. In all of these contexts, concepts apply to the type they immediately prefix. If
functions parameters were to be treated differently that would create inconsistencies and would
ultimately lead to confusion and bugs.</p>
   <p>Beside, if the "same type" semantic is used, it won’t be easy, or even possible to express that the
function allow different parameter types.</p>
   <h2 class="heading settled" data-level="4" id="on-whether-auto-should-be-optional"><span class="secno">4. </span><span class="content">On whether <code class="highlight"><span class="k">auto</span></code> should be optional.</span><a class="self-link" href="#on-whether-auto-should-be-optional"></a></h2>
   <p>As described above, in functions ( and lambdas ) parameters templates are
introduced by the <code class="highlight"><span class="k">auto</span></code> keyword. <code class="highlight"><span class="k">auto</span></code> also lets the compiler infer the type of a declaration
or a function return type.</p>
   <p>When in presence of one or more concepts names, <code class="highlight"><span class="k">auto</span></code> is not necessary in that it does not add any
semantically significant information for the statement/expression to be parsed correctly and
unambiguously.</p>
   <p><code class="highlight"><span class="k">auto</span></code> may either signify generic/template parameter or deduced/inferred type depending on the
context. The two scenarios should be analysed separately.</p>
   <h3 class="heading settled" data-level="4.1" id="auto-in-functions"><span class="secno">4.1. </span><span class="content">As the type of a callable template parameter ( <code class="highlight"><span class="k">auto</span></code> means generic )</span><a class="self-link" href="#auto-in-functions"></a></h3>
   <p>People expressed a strong desire to differentiate function templates from regular non-template
functions. One of the reasons is that functions and functions templates don’t behave identically.</p>
   <p>This argument lead to the abbreviated functions being removed from the current Concept TS <a data-link-type="biblio" href="#biblio-p0696r1">[P0696R1]</a>.</p>
   <p>Given these concerns, it’s reasonable to expect <code class="highlight"><span class="k">auto</span></code> <em>not</em> to be optional in the declaration of
a function template parameter.</p>
   <p><code class="highlight"><span class="kt">void</span> <span class="nf">f</span><span class="p">(</span><span class="n">ConceptName</span> <span class="k">auto</span> <span class="n">foo</span><span class="p">);</span></code> is a terse enough syntax, that conveys that <code class="highlight"><span class="n">f</span></code> is a function
template and that <code class="highlight"><span class="n">foo</span></code> expect to satisfies a concept.</p>
   <h3 class="heading settled" data-level="4.2" id="as-the-type-of-a-return-type-or-variable-declaration-auto-means-inferred"><span class="secno">4.2. </span><span class="content">As the type of a return type or variable declaration ( <code class="highlight"><span class="k">auto</span></code> means inferred )</span><a class="self-link" href="#as-the-type-of-a-return-type-or-variable-declaration-auto-means-inferred"></a></h3>
   <p>Consider <code class="highlight"><span class="n">ConceptName</span> <span class="k">auto</span> <span class="n">foo</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code> and <code class="highlight"><span class="n">ConceptName</span> <span class="n">foo</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code> Both statements are
semantically identical as far as the compiler is concerned.</p>
   <p>But, for the reader, they convey slightly different meanings.</p>
   <p>In the first case, <code class="highlight"><span class="n">ConceptName</span> <span class="k">auto</span> <span class="n">foo</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code> , our attention is attracted to the fact that
the type of <code class="highlight"><span class="n">foo</span></code> is inferred from the RHS expression, and we should probably be mindful of what
that expression’s type is.</p>
   <p>In the second case <code class="highlight"><span class="n">ConceptName</span> <span class="n">foo</span> <span class="o">=</span> <span class="cm">/*...*/</span><span class="p">;</span></code> however, what matters is that <code class="highlight"><span class="n">foo</span></code> has the
behaviour of <code class="highlight"><span class="n">ConceptName</span></code>.  Here <code class="highlight"><span class="n">ConceptName</span></code> is seen not as a constraint of the type of <code class="highlight"><span class="n">foo</span></code> but rather as a polymorphic type which exposes a known set of behaviours. The actual type of <code class="highlight"><span class="n">foo</span></code> does not matter. This is why there is no need in that scenario to distinguish concepts from
concrete types, as they have the same expected properties.</p>
   <p>A developer may wish to express either of these intents and so I think that both constructs should
be well-formed, and therefore <code class="highlight"><span class="k">auto</span></code> should be optional when declaring a variable or return type.</p>
   <p>It also make teaching either as both inference and concepts can be introduced independently of each
other. Ultimately, some people may expect <code class="highlight"><span class="k">auto</span></code> to be required while some may not. Making it
optional makes the language more intuitive for all.</p>
   <h2 class="heading settled" data-level="5" id="acknowledgments-and-thanks"><span class="secno">5. </span><span class="content">Acknowledgments and Thanks</span><a class="self-link" href="#acknowledgments-and-thanks"></a></h2>
   <p>This proposal was inspired by Jakob Riedle’s <a data-link-type="biblio" href="#biblio-p0791r0">[p0791r0]</a> proposal.
Valuable feedbacks from Michael Caisse, Arthur O’Dwyer, Adi Shavit, Simon Brand.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

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

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

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

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

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

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


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

    tocNav.appendChild(toggle);
  }

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

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

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

})();
</script>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-n4651">[N4651]
   <dd>Eric Niebler, Casey Carter. <a href="https://wg21.link/n4651">Working Draft, C++ Extensions for Ranges</a>. URL: <a href="https://wg21.link/n4651">https://wg21.link/n4651</a>
   <dt id="biblio-p0464r2">[P0464R2]
   <dd>Tony Van Eerd, Botond Ballo. <a href="https://wg21.link/p0464r2">Revisiting the meaning of "foo(ConceptName,ConceptName)"</a>. URL: <a href="https://wg21.link/p0464r2">https://wg21.link/p0464r2</a>
   <dt id="biblio-p0587r0">[P0587r0]
   <dd>Richard Smith, James Dennett. <a href="https://wg21.link/p0587r0">Concepts TS revisited</a>. 5 February 2017. URL: <a href="https://wg21.link/p0587r0">https://wg21.link/p0587r0</a>
   <dt id="biblio-p0696r1">[P0696R1]
   <dd>Tom Honermann. <a href="https://wg21.link/p0696r1">Remove abbreviated functions and template-introduction syntax from the Concepts TS</a>. URL: <a href="https://wg21.link/p0696r1">https://wg21.link/p0696r1</a>
   <dt id="biblio-p0734r0">[P0734R0]
   <dd>Andrew Sutton. <a href="https://wg21.link/p0734r0">Wording Paper, C++ extensions for Concepts</a>. URL: <a href="https://wg21.link/p0734r0">https://wg21.link/p0734r0</a>
   <dt id="biblio-p0791r0">[P0791R0]
   <dd>Jakob Riedle. <a href="https://wg21.link/p0791r0">Concepts are Adjectives, not Nouns</a>. URL: <a href="https://wg21.link/p0791r0">https://wg21.link/p0791r0</a>
   <dt id="biblio-p0807r0">[P0807R0]
   <dd>Thomas Köppe. <a href="https://wg21.link/p0807r0">An Adjective Syntax for Concepts</a>. URL: <a href="https://wg21.link/p0807r0">https://wg21.link/p0807r0</a>
  </dl>