<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-02-15" />
  <title>Headless Template Template Parameters</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
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;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <style type="text/css">code ins { border: 1px solid #B3EBB3; padding-bottom: 1px; }
code del { border: 1px solid #ECB3C7; }
div.std blockquote { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
div.std.ins blockquote { text-decoration: underline;
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3; }
div.std.del blockquote { text-decoration: line-through;
color: #000000; background-color: #FFC8EB;
border: 1px solid #ECB3C7; }
div.std blockquote ins { text-decoration: underline;
color: #000000; background-color: #C8FFC8;
border: none; }
div.std blockquote del { text-decoration: line-through;
color: #000000; background-color: #FFC8EB;
border: none; }
div.std div.ins { text-decoration: underline;
color: #000000; background-color: #C8FFC8; }
div.std div.del { text-decoration: line-through;
color: #000000; background-color: #FFC8EB; }
div.std blockquote code * { color: #000000; }
div.std div.sourceCode { background-color: inherit; margin-left: 1em; }
div.std div.ins div.sourceCode * { text-decoration: underline; }
div.std div.del div.sourceCode * { text-decoration: line-through; }
div.std.ins div.sourceCode * { text-decoration: underline; }
div.std.del div.sourceCode * { text-decoration: line-through; }

.footnote { font-size: inherit;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
}
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Headless Template Template
Parameters</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3158R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-02-15</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      James Touton<br>&lt;<a href="mailto:bekenn@gmail.com" class="email">bekenn@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h2 id="toctitle">Contents</h2>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a>
<ul>
<li><a href="#universal-template-parameter-syntax" id="toc-universal-template-parameter-syntax"><span class="toc-section-number">1.1</span> Universal Template Parameter
Syntax<span></span></a></li>
<li><a href="#universal-template-parameter-semantics" id="toc-universal-template-parameter-semantics"><span class="toc-section-number">1.2</span> Universal Template Parameter
Semantics<span></span></a></li>
<li><a href="#universal-template-parameter-topics-not-covered" id="toc-universal-template-parameter-topics-not-covered"><span class="toc-section-number">1.3</span> Universal Template Parameter
Topics Not Covered<span></span></a></li>
</ul></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation<span></span></a>
<ul>
<li><a href="#template-template-argument-matching" id="toc-template-template-argument-matching"><span class="toc-section-number">2.1</span> Template Template Argument
Matching<span></span></a></li>
<li><a href="#universal-template-parameters" id="toc-universal-template-parameters"><span class="toc-section-number">2.2</span> Universal Template
Parameters<span></span></a></li>
</ul></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">3</span> Design<span></span></a>
<ul>
<li><a href="#constrained-template-template-parameters" id="toc-constrained-template-template-parameters"><span class="toc-section-number">3.1</span> Constrained template template
parameters<span></span></a></li>
</ul></li>
<li><a href="#examples" id="toc-examples"><span class="toc-section-number">4</span> Examples<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">5</span> Wording<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h2 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h2>
<p>This paper introduces a new flavor of template template parameter
that matches any template template argument, herein referred to as
<em>headless</em> template template parameters because they are declared
without a <em>template-head</em>. This feature is intended to be used
with universal template parameters (<span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span>, <span class="citation" data-cites="P2989R0">[<a href="#ref-P2989R0" role="doc-biblioref">P2989R0</a>]</span>), but may be adopted
separately. This feature obsoletes a form of template argument matching
that allows a template template parameter with a template parameter pack
to match a template template argument without a template parameter pack
(violating the contract implied by the form of the template template
parameter). This paper also introduces constrained template template
parameter declarations, as constraints are expected to be used
frequently in combination with headless template template
parameters.</p>
<h3 data-number="1.1" id="universal-template-parameter-syntax"><span class="header-section-number">1.1</span> Universal Template Parameter
Syntax<a href="#universal-template-parameter-syntax" class="self-link"></a></h3>
<p>The syntax for the declaration of a universal template parameter is
as yet undecided. <span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span> and <span class="citation" data-cites="P2989R0">[<a href="#ref-P2989R0" role="doc-biblioref">P2989R0</a>]</span> offer several possibilities,
each of which has drawbacks associated with introducing a new keyword,
repurposing an old keyword, designating an identifier as a contextual
keyword, or some combination of the above. The examples in those papers
are not consistent in their choice of syntax; for internal consistency,
and to avoid the issues mentioned above, this paper will use
<code class="sourceCode default">?</code> to declare a universal
template parameter:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Example from P2989R0</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>universal <span class="kw">template</span><span class="op">&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_variable <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> a<span class="op">&gt;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_variable<span class="op">&lt;</span>a<span class="op">&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Same example, rewritten with <span class="tcode">?</span></span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_variable <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> a<span class="op">&gt;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_variable<span class="op">&lt;</span>a<span class="op">&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span></code></pre></div>
<h3 data-number="1.2" id="universal-template-parameter-semantics"><span class="header-section-number">1.2</span> Universal Template Parameter
Semantics<a href="#universal-template-parameter-semantics" class="self-link"></a></h3>
<p>Taken together, <span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span> and <span class="citation" data-cites="P2989R0">[<a href="#ref-P2989R0" role="doc-biblioref">P2989R0</a>]</span> present several different
models of universal template parameter semantics. For the purposes of
this paper, we’ll assume the semantics presented in <span class="citation" data-cites="P2989R0">[<a href="#ref-P2989R0" role="doc-biblioref">P2989R0</a>]</span>; that is:</p>
<ul>
<li>A universal template parameter binds to any template argument of any
kind.</li>
<li>A template that uses universal parameters may have partial
specializations that refine the kind of a universal parameter.</li>
<li>A universal template parameter may be used as a template argument
for a template parameter of any kind; if, during instantiation, the
substituted value is of a kind incompatible with the template parameter,
the program is ill-formed.</li>
<li>A universal template parameter may not be used in any other
context.</li>
</ul>
<h3 data-number="1.3" id="universal-template-parameter-topics-not-covered"><span class="header-section-number">1.3</span> Universal Template Parameter
Topics Not Covered<a href="#universal-template-parameter-topics-not-covered" class="self-link"></a></h3>
<p><span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span> discusses a number of
additional hypothetical language features that would have interactions
with universal template parameters where they to be adopted. As these
are not currently part of C++, this paper will not discuss them. The
features are:</p>
<ul>
<li>Concept template parameters</li>
<li>Variable template parameters</li>
<li>Universal aliases</li>
</ul>
<h2 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h2>
<p>The primary motivation for this feature is to make universal template
parameters useful without backsliding on one of the key principles of
<span class="citation" data-cites="P0522R0">[<a href="#ref-P0522R0" role="doc-biblioref">P0522R0</a>]</span>, which is that the form of a
template template parameter should be indicative of its proper use
within its scope. A secondary motivation is to provide an alternative to
an existing rule that violates this principle. These two issues are
closely related.</p>
<h3 data-number="2.1" id="template-template-argument-matching"><span class="header-section-number">2.1</span> Template Template Argument
Matching<a href="#template-template-argument-matching" class="self-link"></a></h3>
<p><span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span> introduced a change to template
template argument matching that allows a template template parameter
with a template parameter pack to match a template template argument
without a template parameter pack. This was done to grant the ability to
write a metafunction that could accept a template and an arbitrary
number of template arguments, and then apply the arguments to the
template:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> F, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> apply <span class="op">=</span> F<span class="op">&lt;</span>Args<span class="op">...&gt;</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1<span class="op">&gt;</span>           <span class="kw">struct</span> A;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1, <span class="kw">class</span> T2<span class="op">&gt;</span> <span class="kw">struct</span> B;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span>        <span class="kw">struct</span> C;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">struct</span> X <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>apply<span class="op">&lt;</span>A, <span class="dt">int</span><span class="op">&gt;&gt;</span> xa;                              <span class="co">// OK</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>apply<span class="op">&lt;</span>B, <span class="dt">int</span>, <span class="dt">float</span><span class="op">&gt;&gt;</span> xb;                       <span class="co">// OK</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>apply<span class="op">&lt;</span>C, <span class="dt">int</span>, <span class="dt">float</span>, <span class="dt">int</span>, <span class="dt">short</span>, <span class="dt">unsigned</span><span class="op">&gt;&gt;</span> xc; <span class="co">// OK</span></span></code></pre></div>
<p>This addressed the immediate need, but it did so in a way that
undermines the contract implied by the <em>template-head</em> of the
template template parameter. In the above example, it would be
reasonable for the author of
<code class="sourceCode default">apply</code> to expect that
<code class="sourceCode default">F</code> is a template that can accept
any number of type arguments, as is the case for
<code class="sourceCode default">C</code>. However,
<code class="sourceCode default">A</code> can only accept one argument,
and <code class="sourceCode default">B</code> can only accept two
arguments. The contract implied by the declaration of
<code class="sourceCode default">F</code> is violated, but the parameter
is allowed to bind anyway. If a metafunction actually does require that
the template accept any number of arguments, then there is no longer any
space in the existing syntax to express that constraint. We’ve taken
syntax that ought to mean one thing and assigned an entirely different
meaning to it.</p>
<p><span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span> was a reasonable compromise for
its time. It addressed a very real need at the cost of a small syntactic
carve-out in a feature that nobody had seen before (variadic templates).
Today, variadic templates are everywhere, template constraints permit us
to make fine-grained decisions based on the content of a template
declaration, and with reflection on the horizon, the ability to
accurately express intent is more important than ever. If universal
template parameters take an approach similar to <span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span>, the damage will be much
worse.</p>
<h3 data-number="2.2" id="universal-template-parameters"><span class="header-section-number">2.2</span> Universal Template Parameters<a href="#universal-template-parameters" class="self-link"></a></h3>
<p>In the example above, <code class="sourceCode default">apply</code>
can only operate on templates taking some number of type arguments. If
you wish to <code class="sourceCode default">apply</code> non-type or
template arguments to a template that can accept them, you’re out of
luck. There are two reasons for this. The first is that
<code class="sourceCode default">F</code> is specified in such a way
that it cannot bind to a template that can accept template or non-type
arguments. The second is that
<code class="sourceCode default">apply</code> itself is unable to accept
template or non-type arguments in
<code class="sourceCode default">Args</code>. Universal template
parameters are an essential feature well-suited to solving <em>one</em>
of those problems, but <span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span> attempts to
solve both of those issues with the same feature by abusing template
template parameter matching in much the same way that <span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span> did:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;?...&gt;</span> <span class="kw">typename</span> F, <span class="op">?...</span> Args<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> apply <span class="op">=</span> F<span class="op">&lt;</span>Args<span class="op">...&gt;</span>; <span class="co">// easy peasy!</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ok, r1 is std::array&lt;int, 3&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> r1 <span class="op">=</span> apply<span class="op">&lt;</span>std<span class="op">::</span>array, <span class="dt">int</span>, <span class="dv">3</span><span class="op">&gt;</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co">// ok, r2 is std::vector&lt;int, std::pmr::allocator&gt;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> r2 <span class="op">=</span> apply<span class="op">&lt;</span>std<span class="op">::</span>vector, <span class="dt">int</span>, std<span class="op">::</span>pmr<span class="op">::</span>allocator<span class="op">&gt;</span>;</span></code></pre></div>
<p>As with <span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span>, the parameter
pack in the <em>template-head</em> of
<code class="sourceCode default">F</code> is misleading. This much
follows from the rules established by <span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span>; it is not a new problem, and we
can’t change the meaning of the parameter pack without a lengthy
deprecation period (assuming there’s any appetite to try; more on this
later). Unlike <span class="citation" data-cites="N2555">[<a href="#ref-N2555" role="doc-biblioref">N2555</a>]</span>, the parameter
kind (the pattern of the parameter pack) is <em>also</em>
misleading.</p>
<p>A naïve reading of the declaration of
<code class="sourceCode default">F</code> would interpret it as a
template capable of taking any number of arguments, <em>each of any
kind</em>. However, <code class="sourceCode default">F</code> will bind
to <em>any</em> template template argument whatsoever, irrespective of
the number or kinds of template parameters or even any associated
constraints on the argument template.</p>
<h2 data-number="3" id="design"><span class="header-section-number">3</span> Design<a href="#design" class="self-link"></a></h2>
<p>In the case of <code class="sourceCode default">apply</code>, what’s
actually desired is a form of template template parameter that does not
suggest a capability that expresses our lack of knowledge about the
bound template template argument. In each of the prior formulations of
<code class="sourceCode default">apply</code>, the
<em>template-head</em> of <code class="sourceCode default">F</code> has
conveyed misleading information about the properties of
<code class="sourceCode default">F</code>, when what we really want is a
way to say that we don’t know anything about
<code class="sourceCode default">F</code>. So let’s get rid of the
<em>template-head</em> entirely:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> F, <span class="op">?...</span> Args<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> apply <span class="op">=</span> F<span class="op">&lt;</span>Args<span class="op">...&gt;</span>; <span class="co">// easy peasy!</span></span></code></pre></div>
<p>Now, we can actually distinguish between a template that accepts any
arguments whatsoever and a template that we know nothing about. We now
have the tools we need to fully express intent.</p>
<h3 data-number="3.1" id="constrained-template-template-parameters"><span class="header-section-number">3.1</span> Constrained template template
parameters<a href="#constrained-template-template-parameters" class="self-link"></a></h3>
<p>Headless template template parameters are essentially free of
<em>any</em> constraints, as they are not constrained by parameter count
or kind. It seems likely that one of the first things a programmer will
want to do is to add some form of constraint on these parameters. The
most obvious constraint is a check for the validity of a set of template
arguments:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="kw">typename</span> T, <span class="op">?...</span> Args<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> specializable <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">typename</span> T<span class="op">&lt;</span>Args<span class="op">...&gt;</span>; <span class="op">}</span>;</span></code></pre></div>
<p>To ease the application of constraints, a concept name denoting a
template concept may be used to declare a headless template template
parameter. This works exactly as it does for type constraints, except
that the concept’s prototype parameter must be a template template
parameter rather than a type parameter.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>specializable<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">5</span><span class="op">&gt;</span> TT<span class="op">&gt;</span> <span class="dt">void</span> f<span class="op">()</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Same as:</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co">//   template &lt;template typename TT&gt; requires specializable&lt;TT, int, 5&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">//   void f();</span></span></code></pre></div>
<h2 data-number="4" id="examples"><span class="header-section-number">4</span> Examples<a href="#examples" class="self-link"></a></h2>
<p>Following are some examples copied from <span class="citation" data-cites="P1985R3">[<a href="#ref-P1985R3" role="doc-biblioref">P1985R3</a>]</span>. The examples have been updated
with diff marks showing the difference in syntax with the application of
headless template template parameters. In all cases, the semantics of
the example are unchanged. As the difference is entirely in the absence
of a <em>template-head</em>, headless template template parameters
result in simpler syntax that is also more representative of intent.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co">// is_specialization_of</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> Type<span class="op">&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_specialization_of_v <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?...</span> Params, <span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> Type<span class="op">&gt;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_specialization_of_v<span class="op">&lt;</span>Type<span class="op">&lt;</span>Params<span class="op">...&gt;</span>, Type<span class="op">&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> Type<span class="op">&gt;</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> specialization_of <span class="op">=</span> is_specialization_of_v<span class="op">&lt;</span>T, Type<span class="op">&gt;</span>;</span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Type, <span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> Templ<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_specialization_of_v <span class="op">=</span> <span class="op">(</span>template_of<span class="op">(^</span>Type<span class="op">)</span> <span class="op">==</span> <span class="op">^</span>Templ<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?&gt;</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_typename_v             <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_typename_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?&gt;</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_value_v                <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_value_v<span class="op">&lt;</span>V<span class="op">&gt;</span>        <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?&gt;</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_template_v             <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> A<span class="op">&gt;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> is_template_v<span class="op">&lt;</span>A<span class="op">&gt;</span>                       <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="co">// The associated type for each trait:</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?</span> X<span class="op">&gt;</span> <span class="kw">struct</span> is_typename <span class="op">:</span> std<span class="op">::</span>bool_constant<span class="op">&lt;</span>is_typename_v<span class="op">&lt;</span>X<span class="op">&gt;&gt;</span> <span class="op">{}</span>;</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?</span> X<span class="op">&gt;</span> <span class="kw">struct</span> is_value    <span class="op">:</span> std<span class="op">::</span>bool_constant<span class="op">&lt;</span>is_value_v<span class="op">&lt;</span>X<span class="op">&gt;&gt;</span> <span class="op">{}</span>;</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?</span> X<span class="op">&gt;</span> <span class="kw">struct</span> is_template <span class="op">:</span> std<span class="op">::</span>bool_constant<span class="op">&lt;</span>is_template_v<span class="op">&lt;</span>X<span class="op">&gt;&gt;</span> <span class="op">{}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?&gt;</span> <span class="kw">struct</span> box; <span class="co">// impossible to define body</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span> X<span class="op">&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> box<span class="op">&lt;</span>X<span class="op">&gt;</span> <span class="op">{</span> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span>X<span class="op">)</span> result <span class="op">=</span> X; <span class="op">}</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> X<span class="op">&gt;</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> box<span class="op">&lt;</span>X<span class="op">&gt;</span> <span class="op">{</span> <span class="kw">using</span> result <span class="op">=</span> X; <span class="op">}</span>;</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> X<span class="op">&gt;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> box<span class="op">&lt;</span>X<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;?...</span> Args<span class="op">&gt;</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> result <span class="op">=</span> X<span class="op">&lt;</span>Args<span class="op">...&gt;</span>;</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?&gt;</code></span></del></span> <span class="kw">typename</span> Map,</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>          <span class="kw">template</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">&lt;?...&gt;</code></span></del></span> <span class="kw">typename</span> Reduce,</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>          <span class="op">?...</span> Args<span class="op">&gt;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> map_reduce <span class="op">=</span> Reduce<span class="op">&lt;</span>Map<span class="op">&lt;</span>Args<span class="op">&gt;::</span>result<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span><span class="op">...</span> xs<span class="op">&gt;</span> <span class="kw">using</span> sum <span class="op">=</span> box<span class="op">&lt;(</span><span class="dv">0</span> <span class="op">+</span> <span class="op">...</span> <span class="op">+</span> xs<span class="op">)&gt;</span>;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;?</span> X<span class="op">&gt;</span> <span class="kw">using</span> boxed_is_typename <span class="op">=</span> box<span class="op">&lt;</span>is_typename_v<span class="op">&lt;</span>X<span class="op">&gt;&gt;</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="dv">2</span> <span class="op">==</span> map_reduce<span class="op">&lt;</span>boxed_is_typename, sum, <span class="dt">int</span>, <span class="dv">1</span>, <span class="dt">long</span>, std<span class="op">::</span>vector<span class="op">&gt;::</span>result<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> unwrap</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> result <span class="op">=</span> T;</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, T t<span class="op">&gt;</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> unwrap<span class="op">&lt;</span>std<span class="op">::</span>integral_constant<span class="op">&lt;</span>T, t<span class="op">&gt;&gt;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> T result <span class="op">=</span> t;</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del>&lt;?…&gt;</del></span> <span class="kw">typename</span> T, <span class="kw">typename</span><span class="op">...</span> Params<span class="op">&gt;</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> apply_unwrap <span class="op">=</span> T<span class="op">&lt;</span>unwrap<span class="op">&lt;</span>Params<span class="op">&gt;::</span>result<span class="op">...&gt;</span>;</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>apply_unwrap<span class="op">&lt;</span>std<span class="op">::</span>array, <span class="dt">int</span>, std<span class="op">::</span>integral_constant<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="dv">5</span><span class="op">&gt;&gt;</span> arr;</span></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="rm" style="color: #bf0303"><del>&lt;?…&gt;</del></span> <span class="kw">typename</span> F,</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>          <span class="op">?</span> <span class="op">...</span> Args1<span class="op">&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> curry <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;?...</span> Args2<span class="op">&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> func <span class="op">=</span> F<span class="op">&lt;</span>Args1<span class="op">...</span>, Args2<span class="op">...&gt;</span>;</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>template<span class="rm" style="color: #bf0303"><del>&lt;?…&gt;</del></span> <span class="kw">class</span> C, <span class="kw">typename</span><span class="op">...</span> Ps<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> make_unique<span class="op">(</span>Ps<span class="op">&amp;&amp;...</span> ps<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> unique_ptr<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>C<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Ps<span class="op">&gt;(</span>ps<span class="op">)...))&gt;(</span><span class="kw">new</span> C<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Ps<span class="op">&gt;(</span>ps<span class="op">)...))</span>;</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5" id="wording"><span class="header-section-number">5</span> Wording<a href="#wording" class="self-link"></a></h2>
<p>§<span>7.5.5.2
<a href="https://wg21.link/expr.prim.lambda.closure#8">[expr.prim.lambda.closure]/8</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span></p>
<div class="note">
<p><span>[ <em>Note:</em> </span>The function call operator or operator
template can be constrained (<span>13.5.3
<a href="https://wg21.link/temp.constr.decl">[temp.constr.decl]</a></span>)
by a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
(<span>13.2
<a href="https://wg21.link/temp.param">[temp.param]</a></span>), a
<em>requires-clause</em> (<span>13.1
<a href="https://wg21.link/temp.pre">[temp.pre]</a></span>), or a
trailing <em>requires-clause</em> (<span>9.3
<a href="https://wg21.link/dcl.decl">[dcl.decl]</a></span>).</p>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">concept</span> C1 <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span> N<span class="op">&gt;</span> <span class="kw">concept</span> C2 <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> A, <span class="kw">typename</span> B<span class="op">&gt;</span> <span class="kw">concept</span> C3 <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> f <span class="op">=</span> <span class="op">[]&lt;</span><span class="kw">typename</span> T1, C1 T2<span class="op">&gt;</span> <span class="kw">requires</span> C2<span class="op">&lt;</span><span class="kw">sizeof</span><span class="op">(</span>T1<span class="op">)</span> <span class="op">+</span> <span class="kw">sizeof</span><span class="op">(</span>T2<span class="op">)&gt;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>         <span class="op">(</span>T1 a1, T1 b1, T2 a2, <span class="kw">auto</span> a3, <span class="kw">auto</span> a4<span class="op">)</span> <span class="kw">requires</span> C3<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>a4<span class="op">)</span>, T2<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <span class="tcode">T2</span> is constrained by a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>.</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <span class="tcode">T1</span> and <span class="tcode">T2</span> are constrained by a <em>requires-clause</em>, and</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// <span class="tcode">T2</span> and the type of <span class="tcode">a4</span> are constrained by a trailing *requires-clause*.</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<span> — <em>end note</em> ]</span>
</div>
</blockquote>
</div>
<p>§<span>7.5.7.4
<a href="https://wg21.link/expr.prim.req.compound">[expr.prim.req.compound]</a></span></p>
<div class="std">
<blockquote>
<div class="line-block">        <em>compound-requirement</em>:<br />
                <code class="sourceCode default">{</code>
<em>expression</em> <code class="sourceCode default">}</code>
<code class="sourceCode default">noexcept</code><sub><em>opt</em></sub>
<em>return-type-requirement</em><sub><em>opt</em></sub>
<code class="sourceCode default">;</code><br />
<br />
        <em>return-type-requirement</em>:<br />
                <code class="sourceCode default">-&gt;</code> <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span></div>
</blockquote>
</div>
<p>§<span>7.5.7.4
<a href="https://wg21.link/expr.prim.req.compound#1">[expr.prim.req.compound]/1</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
A <em>compound-requirement</em> asserts properties of the
<em>expression</em> <em>E</em>. Substitution of template arguments (if
any) and verification of semantic properties proceed in the following
order:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span>
Substitution of template arguments (if any) into the <em>expression</em>
is performed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span> If
the <code class="sourceCode default">noexcept</code> specifier is
present, <em>E</em> shall not be a potentially-throwing expression
(<span>14.5
<a href="https://wg21.link/except.spec">[except.spec]</a></span>).</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span> If
the <em>return-type-requirement</em> is present, then:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(1.3.1)</a></span>
Substitution of template arguments (if any) into the
<em>return-type-requirement</em> is performed.</li>
<li><span class="add" style="color: #006e28"><ins>The
<em>constraint-specifier</em> shall name a type
concept.</ins></span></li>
<li><span class="marginalizedparent"><a class="marginalized">(1.3.2)</a></span>
The immediately-declared constraint (<span>13.2
<a href="https://wg21.link/temp.param">[temp.param]</a></span>) of the
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
for
<code class="sourceCode default">decltype((</code><em>E</em><code class="sourceCode default">))</code>
shall be satisfied.</li>
</ul>
<p><em>[…]</em></p></li>
</ul>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>9.2.9.3
<a href="https://wg21.link/dcl.type.simple#2">[dcl.type.simple]/2</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The component names of a <em>simple-type-specifier</em> are those of its
<em>nested-name-specifier</em>, <em>type-name</em>,
<em>simple-template-id</em>, <em>template-name</em>, and/or <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
(if it is a <em>placeholder-type-specifier</em>). The component name of
a <em>type-name</em> is the first name in it.</p>
</blockquote>
</div>
<p>§<span>9.2.9.7.1
<a href="https://wg21.link/dcl.spec.auto.general">[dcl.spec.auto.general]</a></span></p>
<div class="std">
<blockquote>
<div class="line-block">        <em>placeholder-type-specifier</em>:<br />
                <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">auto</code><br />
                <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">decltype</code>
<code class="sourceCode default">(</code>
<code class="sourceCode default">auto</code>
<code class="sourceCode default">)</code></div>
</blockquote>
</div>
<p>§<span>9.2.9.7.1
<a href="https://wg21.link/dcl.spec.auto.general#2">[dcl.spec.auto.general]/2</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
A <em>placeholder-type-specifier</em> of the form <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">auto</code> can be used as a
<em>decl-specifier</em> of the <em>decl-specifier-seq</em> of a
<em>parameter-declaration</em> of a function declaration or
<em>lambda-expression</em> and, if it is not the
<code class="sourceCode default">auto</code> <em>type-specifier</em>
introducing a <em>trailing-return-type</em> (see below), is a
<em>generic parameter type placeholder</em> of the function declaration
or <em>lambda-expression</em>.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>9.2.9.7.2
<a href="https://wg21.link/dcl.type.auto.deduct#2.1">[dcl.type.auto.deduct]/2.1</a></span></p>
<div class="std">
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span> For
a non-discarded <code class="sourceCode default">return</code> statement
that occurs in a function declared with a return type that contains a
placeholder type, <code class="sourceCode default">T</code> is the
declared return type.</p>
<p><em>[…]</em></p>
<p>If <em>E</em> has type <code class="sourceCode default">void</code>,
<code class="sourceCode default">T</code> shall be either <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">decltype(auto)</code> or <em>cv</em>
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">auto</code>.</p></li>
</ul>
</blockquote>
</div>
<p>§<span>9.2.9.7.2
<a href="https://wg21.link/dcl.type.auto.deduct#3">[dcl.type.auto.deduct]/3</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
If the <em>placeholder-type-specifier</em> is of the form <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">auto</code>, the deduced type
<code class="sourceCode default">T</code>′ replacing
<code class="sourceCode default">T</code> is determined using the rules
for template argument deduction. If the initialization is
copy-list-initialization, a declaration of
<code class="sourceCode default">std::initializer_list</code> shall
precede (<span>6.5.1
<a href="https://wg21.link/basic.lookup.general">[basic.lookup.general]</a></span>)
the <em>placeholder-type-specifier</em>. Obtain
<code class="sourceCode default">P</code> from
<code class="sourceCode default">T</code> by replacing the occurrences
of <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">auto</code> either with a new invented
type template parameter <code class="sourceCode default">U</code> or, if
the initialization is copy-list-initialization, with
<code class="sourceCode default">std::initializer_list&lt;U&gt;</code>.
Deduce a value for <code class="sourceCode default">U</code> using the
rules of template argument deduction from a function call
(<span>13.10.3.2
<a href="https://wg21.link/temp.deduct.call">[temp.deduct.call]</a></span>),
where <code class="sourceCode default">P</code> is a function template
parameter type and the corresponding argument is <em>E</em>. If the
deduction fails, the declaration is ill-formed. Otherwise,
<code class="sourceCode default">T</code>′ is obtained by substituting
the deduced <code class="sourceCode default">U</code> into
<code class="sourceCode default">P</code>.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>9.2.9.7.2
<a href="https://wg21.link/dcl.type.auto.deduct#4">[dcl.type.auto.deduct]/4</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
If the <em>placeholder-type-specifier</em> is of the form <span class="rm" style="color: #bf0303"><del><em>type-constraint</em><sub><em>opt</em></sub></del></span>
<span class="add" style="color: #006e28"><ins><em>constraint-specifier</em><sub><em>opt</em></sub></ins></span>
<code class="sourceCode default">decltype(auto)</code>,
<code class="sourceCode default">T</code> shall be the placeholder
alone. The type deduced for <code class="sourceCode default">T</code> is
determined as described in <span>9.2.9.6
<a href="https://wg21.link/dcl.type.decltype">[dcl.type.decltype]</a></span>,
as though <em>E</em> had been the operand of the
<code class="sourceCode default">decltype</code>.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>9.2.9.7.2
<a href="https://wg21.link/dcl.type.auto.deduct#5">[dcl.type.auto.deduct]/5</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
For a <em>placeholder-type-specifier</em> with a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>,
<span class="add" style="color: #006e28"><ins>the
<em>constraint-specifier</em> shall name a type concept (<span>13.7.9
<a href="https://wg21.link/temp.concept">[temp.concept]</a></span>)
and</ins></span> the immediately-declared constraint (<span>13.2
<a href="https://wg21.link/temp.param">[temp.param]</a></span>) of the
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
for the type deduced for the placeholder shall be satisfied.</p>
</blockquote>
</div>
<p>§<span>9.3.4.6
<a href="https://wg21.link/dcl.fct#22">[dcl.fct]/22</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">22</a></span> An
<em>abbreviated function template</em> is a function declaration that
has one or more generic parameter type placeholders (<span>9.2.9.7
<a href="https://wg21.link/dcl.spec.auto">[dcl.spec.auto]</a></span>).
An abbreviated function template is equivalent to a function template
(<span>13.7.7
<a href="https://wg21.link/temp.fct">[temp.fct]</a></span>) whose
<em>template-parameter-list</em> includes one invented type
<em>template-parameter</em> for each generic parameter type placeholder
of the function declaration, in order of appearance. For a
<em>placeholder-type-specifier</em> of the form
<code class="sourceCode default">auto</code>, the invented parameter is
an unconstrained <em>type-parameter</em>. For a
<em>placeholder-type-specifier</em> of the form <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
<code class="sourceCode default">auto</code>, the invented parameter is
a <em>type-parameter</em> with that <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>.
The invented type <em>template-parameter</em> is a template parameter
pack if the corresponding <em>parameter-declaration</em> declares a
function parameter pack. If the placeholder contains
<code class="sourceCode default">decltype(auto)</code>, the program is
ill-formed. The adjusted function parameters of an abbreviated function
template are derived from the <em>parameter-declaration-clause</em> by
replacing each occurrence of a placeholder with the name of the
corresponding invented <em>template-parameter</em>.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.2
<a href="https://wg21.link/temp.param#1">[temp.param]/1</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The syntax for <em>template-parameter</em>s is:</p>
<div class="line-block">        <em>template-parameter</em>:<br />
                <em>type-parameter</em><br />
                <em>parameter-declaration</em><br />
<br />
        <em>type-parameter</em>:<br />
                <em>type-parameter-key</em>
<code class="sourceCode default">...</code><sub><em>opt</em></sub>
<em>identifier</em><sub><em>opt</em></sub><br />
                <em>type-parameter-key</em>
<em>identifier</em><sub><em>opt</em></sub>
<code class="sourceCode default">=</code> <em>type-id</em><br />
                <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
<code class="sourceCode default">...</code><sub><em>opt</em></sub>
<em>identifier</em><sub><em>opt</em></sub><br />
                <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
<em>identifier</em><sub><em>opt</em></sub>
<code class="sourceCode default">=</code> <em>type-id</em><br />
                <em>template-head</em> <em>type-parameter-key</em>
<code class="sourceCode default">...</code><sub><em>opt</em></sub>
<em>identifier</em><sub><em>opt</em></sub><br />
                <em>template-head</em> <em>type-parameter-key</em>
<em>identifier</em><sub><em>opt</em></sub>
<code class="sourceCode default">=</code> <em>id-expression</em><br />
                <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template</code></span>
<em>type-parameter-key</em>
<span><code class="sourceCode default">...</code></span><sub><em>opt</em></sub>
<em>identifier</em><sub><em>opt</em></sub></ins></span><br />
                <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template</code></span>
<em>type-parameter-key</em> <em>identifier</em><sub><em>opt</em></sub>
<span><code class="sourceCode default">=</code></span>
<em>id-expression</em></ins></span><br />
<br />
        <em>type-parameter-key</em>:<br />
                <code class="sourceCode default">class</code><br />
                <code class="sourceCode default">typename</code><br />
<br />
        <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>:<br />
                <em>nested-name-specifier</em><sub><em>opt</em></sub>
<em>concept-name</em><br />
                <em>nested-name-specifier</em><sub><em>opt</em></sub>
<em>concept-name</em> <code class="sourceCode default">&lt;</code>
<em>template-argument-list</em><sub><em>opt</em></sub>
<code class="sourceCode default">&gt;</code></div>
<p>The component names of a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
are its <em>concept-name</em> and those of its
<em>nested-name-specifier</em> (if any).</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<!--
&sect;[temp.param/2]{.sref}

::: std
> [2]{.pnum}
> There is no semantic difference between `class` and `typename`
> in a *type-parameter-key*.
> `typename` followed by an *unqualified-id*
> names a [template type parameter]{.rm} [*template type parameter*]{.add}.
>
> [\[ *Note:*]{.add}
> `typename` followed by a *qualified-id*
> denotes the type in a non-type
> [Since template *template-parameter*s
> and template *template-argument*s
> are treated as types for descriptive purposes, the terms
> *non-type parameter* and *non-type argument*
> are used to refer to non-type, non-template parameters and arguments.]{.footnote}
> *parameter-declaration*.
> A *template-parameter* of the form
> `class` *identifier* is a *type-parameter*.
> [&mdash; *end note* \]]{.add}
>
> ::: example
>
> ```c++
> class T { /* ... */ };
> int i;
>
> template<class T, T i> void f(T t) {
>   T t1 = i;         // template-parameters @[T]{.tcode}@ and @[i]{.tcode}@
>   ::T t2 = ::i;     // global namespace members @[T]{.tcode}@ and @[i]{.tcode}@
> }
> ```
>
> Here, the template `f` has a *type-parameter*
> called `T`, rather than an unnamed non-type
> *template-parameter* of class `T`.
> :::
>
> A *template-parameter* declaration shall not
> have a *storage-class-specifier*.
> Types shall not be defined in a *template-parameter*
> declaration.
:::
-->
<p>§<span>13.2
<a href="https://wg21.link/temp.param#3">[temp.param]/3</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The <em>identifier</em> in a <em>type-parameter</em> is not looked up. A
<em>type-parameter</em> whose <em>identifier</em> does not follow an
ellipsis defines its <em>identifier</em> to be a <em>typedef-name</em>
<span class="rm" style="color: #bf0303"><del>(if declared without
<span><code class="sourceCode default">template</code></span>)</del></span>
or <em>template-name</em> <span class="rm" style="color: #bf0303"><del>(if declared with
<span><code class="sourceCode default">template</code></span>)</del></span>
in the scope of the template declaration. <span class="add" style="color: #006e28"><ins>The <em>identifier</em> is a
<em>template-name</em> if it is declared with
<span><code class="sourceCode default">template</code></span> or with a
<em>constraint-specifier</em> naming a template concept (<span>13.7.9
<a href="https://wg21.link/temp.concept">[temp.concept]</a></span>);
otherwise, it is a <em>typedef-name</em>.</ins></span></p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.2
<a href="https://wg21.link/temp.param#4">[temp.param]/4</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
A <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
<code class="sourceCode default">Q</code> that designates a concept
<code class="sourceCode default">C</code> can be used to constrain a
contextually-determined type<span class="add" style="color: #006e28"><ins>, template,</ins></span> or template <span class="rm" style="color: #bf0303"><del>type</del></span> parameter pack
<code class="sourceCode default">T</code> with a
<em>constraint-expression</em> <code class="sourceCode default">E</code>
defined as follows. If <code class="sourceCode default">Q</code> is of
the form
<code class="sourceCode default">C&lt;A</code><sub>1</sub><code class="sourceCode default">,</code>
⋯<code class="sourceCode default">, A</code><sub><em>n</em></sub><code class="sourceCode default">&gt;</code>,
then let <code class="sourceCode default">E</code>′ be
<code class="sourceCode default">C&lt;T, A</code><sub>1</sub><code class="sourceCode default">,</code>
⋯<code class="sourceCode default">, A</code><sub><em>n</em></sub><code class="sourceCode default">&gt;</code>.
Otherwise, let <code class="sourceCode default">E</code>′ be
<code class="sourceCode default">C&lt;T&gt;</code>. If
<code class="sourceCode default">T</code> is not a pack, then
<code class="sourceCode default">E</code> is
<code class="sourceCode default">E</code>′<span class="rm" style="color: #bf0303"><del>,</del></span><span class="add" style="color: #006e28"><ins>;</ins></span> otherwise<span class="add" style="color: #006e28"><ins>,</ins></span>
<code class="sourceCode default">E</code> is
<code class="sourceCode default">(E</code>′<code class="sourceCode default"> &amp;&amp; ...)</code>.
This <em>constraint-expression</em>
<code class="sourceCode default">E</code> is called the
<em>immediately-declared constraint</em> of
<code class="sourceCode default">Q</code> for
<code class="sourceCode default">T</code>. The concept designated by a
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
shall be a type concept <span class="add" style="color: #006e28"><ins>or
a template concept</ins></span> (<span>13.7.9
<a href="https://wg21.link/temp.concept">[temp.concept]</a></span>).</p>
</blockquote>
</div>
<p>§<span>13.2
<a href="https://wg21.link/temp.param#5">[temp.param]/5</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
A <em>type-parameter</em> that starts with a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
introduces the immediately-declared constraint of the <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
for the parameter.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.2
<a href="https://wg21.link/temp.param#11">[temp.param]/11</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span> A
non-type template parameter declared with a type that contains a
placeholder type with a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
introduces the immediately-declared constraint of the <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
for the invented type corresponding to the placeholder (<span>9.3.4.6
<a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>).</p>
</blockquote>
</div>
<p>§<span>13.2
<a href="https://wg21.link/temp.param#17">[temp.param]/17</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span> If a
<em>template-parameter</em> is a <em>type-parameter</em> with an
ellipsis prior to its optional <em>identifier</em> or is a
<em>parameter-declaration</em> that declares a pack (<span>9.3.4.6
<a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>), then the
<em>template-parameter</em> is a template parameter pack (<span>13.7.4
<a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>). A
template parameter pack that is a <em>parameter-declaration</em> whose
type contains one or more unexpanded packs is a pack expansion.
Similarly, a template parameter pack that is a <em>type-parameter</em>
with a <em>template-parameter-list</em> containing one or more
unexpanded packs is a pack expansion. A <span class="rm" style="color: #bf0303"><del>type</del></span> <span class="add" style="color: #006e28"><ins>template</ins></span> parameter pack <span class="add" style="color: #006e28"><ins>declared</ins></span> with a
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
that contains an unexpanded parameter pack is a pack expansion. A
template parameter pack that is a pack expansion shall not expand a
template parameter pack declared in the same
<em>template-parameter-list</em>.</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.3
<a href="https://wg21.link/temp.names#7">[temp.names]/7</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
A <em>template-id</em> is <em>valid</em> if <span class="add" style="color: #006e28"><ins>the named template is a template
<em>template-parameter</em> declared without a <em>template-head</em> or
if</ins></span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(7.1)</a></span>
there are at most as many arguments as there are parameters or a
parameter is a template parameter pack (<span>13.7.4
<a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>),</li>
<li><span class="marginalizedparent"><a class="marginalized">(7.2)</a></span>
there is an argument for each non-deducible non-pack parameter that does
not have a default <em>template-argument</em>,</li>
<li><span class="marginalizedparent"><a class="marginalized">(7.3)</a></span> each
<em>template-argument</em> matches the corresponding
<em>template-parameter</em> (<span>13.4
<a href="https://wg21.link/temp.arg">[temp.arg]</a></span>),</li>
<li><span class="marginalizedparent"><a class="marginalized">(7.4)</a></span>
substitution of each template argument into the following template
parameters (if any) succeeds, and</li>
<li><span class="marginalizedparent"><a class="marginalized">(7.5)</a></span> if
the <em>template-id</em> is non-dependent, the associated constraints
are satisfied as specified in the next paragraph.</li>
</ul>
<p>A <em>simple-template-id</em> shall be valid unless it names a
function template specialization (<span>13.10.3
<a href="https://wg21.link/temp.deduct">[temp.deduct]</a></span>).</p>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.4.4
<a href="https://wg21.link/temp.arg.template#3">[temp.arg.template]/3</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
A <em>template-argument</em> <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">A</code></span></ins></span>
matches a template <em>template-parameter</em>
<code class="sourceCode default">P</code> when <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">P</code></span>
is declared without a <em>template-head</em>,
<span><code class="sourceCode default">A</code></span> is the name of a
template <em>template-parameter</em> declared without a
<em>template-head</em>, or when</ins></span>
<code class="sourceCode default">P</code> is at least as specialized as
<span class="rm" style="color: #bf0303"><del>the
<em>template-argument</em></del></span>
<code class="sourceCode default">A</code><span class="add" style="color: #006e28"><ins>, ignoring constraints on
<span><code class="sourceCode default">A</code></span> if
<span><code class="sourceCode default">P</code></span> is
unconstrained</ins></span>. <span class="rm" style="color: #bf0303"><del>In this comparison, if
<span><code class="sourceCode default">P</code></span> is unconstrained,
the constraints on
<span><code class="sourceCode default">A</code></span> are not
considered.</del></span> If <code class="sourceCode default">P</code>
<span class="rm" style="color: #bf0303"><del>contains</del></span> <span class="add" style="color: #006e28"><ins>is declared with a
<em>template-head</em> containing</ins></span> a template parameter pack
<span class="add" style="color: #006e28"><ins>(<span>13.7.4
<a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>)</ins></span>,
then <code class="sourceCode default">A</code> also matches
<code class="sourceCode default">P</code> if each of
<code class="sourceCode default">A</code>’s template parameters matches
the corresponding template parameter in the <em>template-head</em> of
<code class="sourceCode default">P</code> <span class="add" style="color: #006e28"><ins>(this behavior is deprecated; see D.# <a href="#depr.temp.match">[depr.temp.match]</a>)</ins></span>. Two
template parameters match if they are of the same kind (type, non-type,
template), for non-type <em>template-parameter</em>s, their types are
equivalent (<span>13.7.7.2
<a href="https://wg21.link/temp.over.link">[temp.over.link]</a></span>),
and for template <em>template-parameter</em>s, each of their
corresponding <em>template-parameter</em>s matches, recursively. <span class="rm" style="color: #bf0303"><del>When
<span><code class="sourceCode default">P</code></span>’s
<em>template-head</em> contains a template parameter pack (<span>13.7.4
<a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>),
the template parameter pack</del></span> <span class="add" style="color: #006e28"><ins>A template parameter pack in the
<em>template-head</em> of
<span><code class="sourceCode default">P</code></span></ins></span> will
match zero or more template parameters or template parameter packs in
the <em>template-head</em> of <code class="sourceCode default">A</code>
with the same type and form as the template parameter pack in
<code class="sourceCode default">P</code> (ignoring whether those
template parameters are template parameter packs).</p>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">class</span> A <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> U <span class="op">=</span> T<span class="op">&gt;</span> <span class="kw">class</span> B <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> <span class="op">...</span> Types<span class="op">&gt;</span> <span class="kw">class</span> C <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> n<span class="op">&gt;</span> <span class="kw">class</span> D <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;template class P&gt; class W { /* ... */ };</code></span></ins></span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">class</span> <span class="rm" style="color: #bf0303"><del>P</del></span> <span class="add" style="color: #006e28"><ins>Q</ins></span><span class="op">&gt;</span> <span class="kw">class</span> X <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> <span class="op">...&gt;</span> <span class="kw">class</span> <span class="rm" style="color: #bf0303"><del>Q</del></span> <span class="add" style="color: #006e28"><ins>R</ins></span><span class="op">&gt;</span> <span class="kw">class</span> Y <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="kw">class</span> <span class="rm" style="color: #bf0303"><del>R</del></span> <span class="add" style="color: #006e28"><ins>S</ins></span><span class="op">&gt;</span> <span class="kw">class</span> Z <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span>;</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">W&lt;A&gt; wa;            // OK</code></span></ins></span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">W&lt;B&gt; wb;            // OK</code></span></ins></span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">W&lt;C&gt; wc;            // OK</code></span></ins></span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">W&lt;D&gt; wd;            // OK</code></span></ins></span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>A<span class="op">&gt;</span> xa;            <span class="co">// OK</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>B<span class="op">&gt;</span> xb;            <span class="co">// OK</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>C<span class="op">&gt;</span> xc;            <span class="co">// OK</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>Y<span class="op">&lt;</span>A<span class="op">&gt;</span> ya;            <span class="co">// OK</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>Y<span class="op">&lt;</span>B<span class="op">&gt;</span> yb;            <span class="co">// OK</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>Y<span class="op">&lt;</span>C<span class="op">&gt;</span> yc;            <span class="co">// OK</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>Z<span class="op">&lt;</span>D<span class="op">&gt;</span> zd;            <span class="co">// OK</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">struct</span> <span class="rm" style="color: #bf0303"><del>eval</del></span> <span class="add" style="color: #006e28"><ins>X { }</ins></span>;</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span>, <span class="kw">class</span><span class="op">...&gt;</span> <span class="kw">class</span> TT, <span class="kw">class</span> T1, <span class="kw">class</span><span class="op">...</span> Rest<span class="op">&gt;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">struct eval&lt;TT&lt;T1, Rest...&gt;&gt; { };</code></span></del></span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">using eval1 = TT&lt;T1, Rest...&gt;;</code></span></ins></span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template &lt;template class TT, class T1, class... Rest&gt;</code></span></ins></span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">using eval2 = TT&lt;T1, Rest...&gt;;</code></span></ins></span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1<span class="op">&gt;</span> <span class="kw">struct</span> A;</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1, <span class="kw">class</span> T2<span class="op">&gt;</span> <span class="kw">struct</span> B;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">int</span> N<span class="op">&gt;</span> <span class="kw">struct</span> C;</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1, <span class="dt">int</span> N<span class="op">&gt;</span> <span class="kw">struct</span> D;</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T1, <span class="kw">class</span> T2, <span class="dt">int</span> N <span class="op">=</span> <span class="dv">17</span><span class="op">&gt;</span> <span class="kw">struct</span> E;</span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>X&lt;</ins></span>eval<span class="add" style="color: #006e28"><ins>1</ins></span><span class="op">&lt;</span>A<span class="rm" style="color: #bf0303"><del>&lt;</del></span><span class="add" style="color: #006e28"><ins>, </ins></span>int<span class="op">&gt;&gt;</span> e<span class="add" style="color: #006e28"><ins>1</ins></span>A;          <span class="co">// OK<span class="rm" style="color: #bf0303"><del>, matches partial specialization of <span class="tcode">eval</span></del></span></span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>X&lt;</ins></span>eval<span class="add" style="color: #006e28"><ins>1</ins></span><span class="op">&lt;</span>B<span class="rm" style="color: #bf0303"><del>&lt;</del></span><span class="add" style="color: #006e28"><ins>, </ins></span>int, <span class="dt">float</span><span class="op">&gt;&gt;</span> e<span class="add" style="color: #006e28"><ins>1</ins></span>B;   <span class="co">// OK<span class="rm" style="color: #bf0303"><del>, matches partial specialization of <span class="tcode">eval</span></del></span></span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>X&lt;</ins></span>eval<span class="add" style="color: #006e28"><ins>1</ins></span><span class="op">&lt;</span>C<span class="rm" style="color: #bf0303"><del>&lt;</del></span><span class="add" style="color: #006e28"><ins>, </ins></span><span class="dv">17</span><span class="op">&gt;&gt;</span> e<span class="add" style="color: #006e28"><ins>1</ins></span>C;           <span class="co">// error: <span class="tcode">C</span> does not match <span class="tcode">TT</span> in <span class="rm" style="color: #bf0303"><del>partial specialization</del></span> <span class="tcode add" style="color: #006e28"><ins>eval1</ins></span></span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>X&lt;</ins></span>eval<span class="add" style="color: #006e28"><ins>1</ins></span><span class="op">&lt;</span>D<span class="rm" style="color: #bf0303"><del>&lt;</del></span><span class="add" style="color: #006e28"><ins>, </ins></span>int, <span class="dv">17</span><span class="op">&gt;&gt;</span> e<span class="add" style="color: #006e28"><ins>1</ins></span>D;      <span class="co">// error: <span class="tcode">D</span> does not match <span class="tcode">TT</span> in <span class="rm" style="color: #bf0303"><del>partial specialization</del></span> <span class="tcode add" style="color: #006e28"><ins>eval1</ins></span></span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>X&lt;</ins></span>eval<span class="add" style="color: #006e28"><ins>1</ins></span><span class="op">&lt;</span>E<span class="rm" style="color: #bf0303"><del>&lt;</del></span><span class="add" style="color: #006e28"><ins>, </ins></span>int, <span class="dt">float</span><span class="op">&gt;&gt;</span> e<span class="add" style="color: #006e28"><ins>1</ins></span>E;   <span class="co">// error: <span class="tcode">E</span> does not match <span class="tcode">TT</span> in <span class="rm" style="color: #bf0303"><del>partial specialization</del></span> <span class="tcode add" style="color: #006e28"><ins>eval1</ins></span></span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">X&lt;eval2&lt;A, int&gt;&gt; e2A;           //</code></span></ins></span><span class="add" style="color: #006e28"><ins> <em>OK</em></ins></span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">X&lt;eval2&lt;B, int, float&gt;&gt; e2B;    //</code></span></ins></span><span class="add" style="color: #006e28"><ins> <em>OK</em></ins></span></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">X&lt;eval2&lt;C, 17&gt;&gt; e2C;            //</code></span></ins></span><span class="add" style="color: #006e28"><ins> <em>error: non-type argument provided for</em> <span><code class="sourceCode default">T1</code></span> <em>in</em> <span><code class="sourceCode default">eval2</code></span></ins></span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">X&lt;eval2&lt;D, int, 17&gt;&gt; e2D;       //</code></span></ins></span><span class="add" style="color: #006e28"><ins> <em>error: non-type argument provided for</em> <span><code class="sourceCode default">Rest</code></span> <em>in</em> <span><code class="sourceCode default">eval2</code></span></ins></span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">X&lt;eval2&lt;E, int, float&gt;&gt; e2E;    //</code></span></ins></span><span class="add" style="color: #006e28"><ins> <em>OK</em></ins></span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">concept</span> C <span class="op">=</span> <span class="kw">requires</span> <span class="op">(</span>T t<span class="op">)</span> <span class="op">{</span> t<span class="op">.</span>f<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">concept</span> D <span class="op">=</span> C<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="kw">requires</span> <span class="op">(</span>T t<span class="op">)</span> <span class="op">{</span> t<span class="op">.</span>g<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span>C<span class="op">&gt;</span> <span class="kw">class</span> P<span class="op">&gt;</span> <span class="kw">struct</span> S <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>C<span class="op">&gt;</span> <span class="kw">struct</span> X <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="kw">struct</span> Y <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">struct</span> Z <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>X<span class="op">&gt;</span> s1;            <span class="co">// OK, <span class="tcode">X</span> and <span class="tcode">P</span> have equivalent constraints</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>Y<span class="op">&gt;</span> s2;            <span class="co">// error: <span class="tcode">P</span> is not at least as specialized as <span class="tcode">Y</span></span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>S<span class="op">&lt;</span>Z<span class="op">&gt;</span> s3;            <span class="co">// OK, <span class="tcode">P</span> is at least as specialized as <span class="tcode">Z</span></span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<p>§<span>13.5.3
<a href="https://wg21.link/temp.constr.decl#2">[temp.constr.decl]/2</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Constraints can also be associated with a declaration through the use of
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
in a <em>template-parameter-list</em> or <em>parameter-type-list</em>.
Each of these forms introduces additional
<em>constraint-expression</em>s that are used to constrain the
declaration.</p>
</blockquote>
</div>
<p>§<span>13.5.3
<a href="https://wg21.link/temp.constr.decl#3.3">[temp.constr.decl]/3.3</a></span></p>
<div class="std">
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.3)</a></span>
Otherwise, the associated constraints are the normal form of a logical
<span class="smallcaps">and</span> expression (<span>7.6.14
<a href="https://wg21.link/expr.log.and">[expr.log.and]</a></span>)
whose operands are in the following order:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(3.3.1)</a></span>
the <em>constraint-expression</em> introduced by each <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
(<span>13.2
<a href="https://wg21.link/temp.param">[temp.param]</a></span>) in the
declaration’s <em>template-parameter-list</em>, in order of appearance,
and</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.3.2)</a></span>
the <em>constraint-expression</em> introduced by a
<em>requires-clause</em> following a <em>template-parameter-list</em>
(<span>13.1
<a href="https://wg21.link/temp.pre">[temp.pre]</a></span>), and</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.3.3)</a></span>
the <em>constraint-expression</em> introduced by each <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>
in the parameter-type-list of a function declaration, and</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.3.4)</a></span>
the <em>constraint-expression</em> introduced by a trailing
<em>requires-clause</em> (<span>9.3
<a href="https://wg21.link/dcl.decl">[dcl.decl]</a></span>) of a
function declaration (<span>9.3.4.6
<a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>).</li>
</ul></li>
</ul>
</blockquote>
</div>
<p>§<span>13.7.1
<a href="https://wg21.link/temp.decls.general#3">[temp.decls.general]/3</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
For purposes of name lookup and instantiation, default arguments, <span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>,
<em>requires-clause</em>s (<span>13.1
<a href="https://wg21.link/temp.pre">[temp.pre]</a></span>), and
<em>noexcept-specifier</em>s of function templates and of member
functions of class templates are considered definitions; each default
argument, <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>,
<em>requires-clause</em>, or <em>noexcept-specifier</em> is a separate
definition which is unrelated to the templated function definition or to
any other default arguments, <span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>,
<em>requires-clause</em>s, or <em>noexcept-specifier</em>s. For the
purpose of instantiation, the substatements of a constexpr if statement
(<span>8.5.2
<a href="https://wg21.link/stmt.if">[stmt.if]</a></span>) are considered
definitions.</p>
</blockquote>
</div>
<p>§<span>13.7.7.2
<a href="https://wg21.link/temp.over.link#6">[temp.over.link]/6</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
Two <em>template-head</em>s are <em>equivalent</em> if their
<em>template-parameter-list</em>s have the same length, corresponding
<em>template-parameter</em>s are equivalent and are both declared with
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
that are equivalent if either <em>template-parameter</em> is declared
with a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>,
and if either <em>template-head</em> has a <em>requires-clause</em>,
they both have <em>requires-clause</em>s and the corresponding
<em>constraint-expression</em>s are equivalent. Two
<em>template-parameter</em>s are <em>equivalent</em> under the following
conditions:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span> they
declare template parameters of the same kind,</li>
<li><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span> if
either declares a template parameter pack, they both do,</li>
<li><span class="marginalizedparent"><a class="marginalized">(6.3)</a></span> if
they declare non-type template parameters, they have equivalent types
ignoring the use of <span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
for placeholder types, and</li>
<li><span class="marginalizedparent"><a class="marginalized">(6.4)</a></span> if
they declare template template parameters, <span class="add" style="color: #006e28"><ins>either neither has a <em>template-head</em>
or they both do and</ins></span> their <span class="rm" style="color: #bf0303"><del>template parameters</del></span> <span class="add" style="color: #006e28"><ins><em>template-head</em>s</ins></span> are
equivalent.</li>
</ul>
<p>When determining whether types or <span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
are equivalent, the rules above are used to compare expressions
involving template parameters. Two <em>template-head</em>s are
<em>functionally equivalent</em> if they accept and are satisfied by
(<span>13.5.2
<a href="https://wg21.link/temp.constr.constr">[temp.constr.constr]</a></span>)
the same set of template argument lists.</p>
</blockquote>
</div>
<p>§<span>13.7.7.3
<a href="https://wg21.link/temp.func.order#3">[temp.func.order]/3</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
To produce the transformed template, for each type, non-type, or
template template parameter (including template parameter packs
(<span>13.7.4
<a href="https://wg21.link/temp.variadic">[temp.variadic]</a></span>)
thereof) synthesize a unique type, value, or class template respectively
and substitute it for each occurrence of that parameter in the function
type of the template<span class="rm" style="color: #bf0303"><del>.</del></span><span class="add" style="color: #006e28"><ins>:</ins></span></p>
<ul>
<li><p><span class="add" style="color: #006e28"><ins><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span> For
a non-type template parameter, the type of the synthesized value is the
type of the parameter after substitution of prior template
parameters.</ins></span></p>
<div class="note">
<p><span>[ <em>Note:</em> </span>The type replacing the placeholder in
the type of the value synthesized for a non-type template parameter is
also a unique synthesized type.<span> — <em>end note</em> ]</span></p>
</div></li>
<li><p><span class="add" style="color: #006e28"><ins><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span> For
a template template parameter declared with a <em>template-head</em>,
the <em>template-head</em> of the synthesized class template is the
result of substitution into the <em>template-head</em> of the template
template parameter. For a template template parameter declared without a
<em>template-head</em>, the synthesized class template does not match
(<span>13.4.4
<a href="https://wg21.link/temp.arg.template">[temp.arg.template]</a></span>)
any template <em>template-parameter</em> declared with a
<em>template-head</em>.</ins></span></p></li>
</ul>
<p><em>[…]</em></p>
</blockquote>
</div>
<p>§<span>13.7.9
<a href="https://wg21.link/temp.concept#2">[temp.concept]/2</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
A <em>concept-definition</em> declares a concept. Its
<em>identifier</em> becomes a <em>concept-name</em> referring to that
concept within its scope. The optional <em>attribute-specifier-seq</em>
appertains to the concept.</p>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> C <span class="op">=</span> <span class="kw">requires</span><span class="op">(</span>T x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span> x <span class="op">==</span> x <span class="op">}</span> <span class="op">-&gt;</span> std<span class="op">::</span>convertible_to<span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> C<span class="op">&lt;</span>T<span class="op">&gt;</span>     <span class="co">// <span class="tcode">C</span> constrains <span class="tcode">f1(T)</span> in <em>constraint-expression</em></span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>T f1<span class="op">(</span>T x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> x; <span class="op">}</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>C T<span class="op">&gt;</span>       <span class="co">// <span class="tcode">C</span>, as a <span class="rm" style="color: #bf0303"><del><em>type-constraint</em></del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em></ins></span>, constrains <span class="tcode">f2(T)</span></span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>T f2<span class="op">(</span>T x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> x; <span class="op">}</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<p>§<span>13.7.9
<a href="https://wg21.link/temp.concept#7">[temp.concept]/7</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
The first declared template parameter of a concept definition is its
<em>prototype parameter</em>. A <em>type concept</em> is a concept whose
prototype parameter is a type <em>template-parameter</em>. <span class="add" style="color: #006e28"><ins>A <em>template concept</em> is a
concept whose prototype parameter is a template
<em>template-parameter</em>.</ins></span></p>
</blockquote>
</div>
<p>§<span>13.9.2
<a href="https://wg21.link/temp.inst#2">[temp.inst]/2</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>[…]</em></p>
<div class="note">
<p><span>[ <em>Note:</em> </span>Within a template declaration, a local
class (<span>11.6
<a href="https://wg21.link/class.local">[class.local]</a></span>) or
enumeration and the members of a local class are never considered to be
entities that can be separately instantiated (this includes their
default arguments, <em>noexcept-specifier</em>s, and non-static data
member initializers, if any, but not their <span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
or <em>requires-clause</em>s). As a result, the dependent names are
looked up, the semantic constraints are checked, and any templates used
are instantiated as part of the instantiation of the entity within which
the local class or enumeration is declared.<span> — <em>end note</em>
]</span></p>
</div>
</blockquote>
</div>
<p>§<span>13.9.2
<a href="https://wg21.link/temp.inst#17">[temp.inst]/17</a></span></p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span> The
<span class="rm" style="color: #bf0303"><del><em>type-constraint</em>s</del></span> <span class="add" style="color: #006e28"><ins><em>constraint-specifier</em>s</ins></span>
and <em>requires-clause</em> of a template specialization or member
function are not instantiated along with the specialization or function
itself, even for a member function of a local class; substitution into
the atomic constraints formed from them is instead performed as
specified in <span>13.5.3
<a href="https://wg21.link/temp.constr.decl">[temp.constr.decl]</a></span>
and <span>13.5.2.3
<a href="https://wg21.link/temp.constr.atomic">[temp.constr.atomic]</a></span>
when determining whether the constraints are satisfied or as specified
in <span>13.5.3
<a href="https://wg21.link/temp.constr.decl">[temp.constr.decl]</a></span>
when comparing declarations.</p>
</blockquote>
</div>
<p>§<span>D
<a href="https://wg21.link/depr">[depr]</a></span></p>
<div class="std ins">
<blockquote>
<h3 id="depr.temp.match">D.# Matching template
<em>template-parameter</em>s with parameter packs
      [depr.temp.match]<a href="#depr.temp.match" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
A template parameter pack in the <em>template-head</em> of a template
<em>template-parameter</em> is permitted to match zero or more template
parameters in the <em>template-head</em> of a template
<em>template-argument</em> (<span>13.4.4
<a href="https://wg21.link/temp.arg.template">[temp.arg.template]</a></span>).
This behavior is deprecated.</p>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span> <span class="kw">class</span> TT<span class="op">&gt;</span> <span class="kw">class</span> X <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> A, <span class="kw">class</span> B<span class="op">&gt;</span> <span class="kw">class</span> Y;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>X<span class="op">&lt;</span>Y<span class="op">&gt;</span> x;       <span class="co">// deprecated, TT matches A and B</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> A, <span class="kw">class</span> B<span class="op">&gt;</span> <span class="kw">class</span> TT<span class="op">&gt;</span> <span class="kw">class</span> P <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span> <span class="kw">class</span> Q;</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>P<span class="op">&lt;</span>Q<span class="op">&gt;</span> p;       <span class="co">// OK</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
</blockquote>
</div>
<h2 data-number="6" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h2>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-N2555" class="csl-entry" role="doc-biblioentry">
[N2555] D. Gregor, E. Niebler. 2008-02-29. Extending Variadic Template
Template Parameters (Revision 1). <a href="https://wg21.link/n2555"><div class="csl-block">https://wg21.link/n2555</div></a>
</div>
<div id="ref-P0522R0" class="csl-entry" role="doc-biblioentry">
[P0522R0] James Touton, Hubert Tong. 2016-11-11. DR: Matching of
template template-arguments excludes compatible templates. <a href="https://wg21.link/p0522r0"><div class="csl-block">https://wg21.link/p0522r0</div></a>
</div>
<div id="ref-P1985R3" class="csl-entry" role="doc-biblioentry">
[P1985R3] Gašper Ažman, Mateusz Pusz, Colin MacLean, Bengt Gustafsonn,
Corentin Jabot. 2022-09-17. Universal template parameters. <a href="https://wg21.link/p1985r3"><div class="csl-block">https://wg21.link/p1985r3</div></a>
</div>
<div id="ref-P2989R0" class="csl-entry" role="doc-biblioentry">
[P2989R0] Corentin Jabot, Gašper Ažman. 2023-10-14. A Simple Approach to
Universal Template Parameters. <a href="https://wg21.link/p2989r0"><div class="csl-block">https://wg21.link/p2989r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
