<!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="2023-03-15" />
  <title>Standardized Type Ordering</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>
  <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">Standardized Type
Ordering</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2830R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-03-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>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Nate Nichols<br>&lt;<a href="mailto:natenichols@cox.net" class="email">natenichols@cox.net</a>&gt;<br>
      Gašper Ažman<br>&lt;<a href="mailto:gasper.azman@gmail.com" class="email">gasper.azman@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">2</span> Revision
History<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">3</span> Motivation<span></span></a></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">4</span> Proposal<span></span></a>
<ul>
<li><a href="#approach-outline" id="toc-approach-outline"><span class="toc-section-number">4.1</span> Approach
outline<span></span></a></li>
<li><a href="#structure-of-key-tuples" id="toc-structure-of-key-tuples"><span class="toc-section-number">4.2</span> Structure of
key-tuples<span></span></a>
<ul>
<li><a href="#example" id="toc-example"><span class="toc-section-number">4.2.1</span> Example:<span></span></a></li>
</ul></li>
<li><a href="#atoms" id="toc-atoms"><span class="toc-section-number">4.3</span> Atoms<span></span></a>
<ul>
<li><a href="#kinds" id="toc-kinds"><span class="toc-section-number">4.3.1</span> Kinds<span></span></a></li>
</ul></li>
<li><a href="#identifiers" id="toc-identifiers"><span class="toc-section-number">4.4</span> Identifiers<span></span></a>
<ul>
<li><a href="#simple-names" id="toc-simple-names"><span class="toc-section-number">4.4.1</span> Simple
Names<span></span></a></li>
<li><a href="#anonymous-namespace" id="toc-anonymous-namespace"><span class="toc-section-number">4.4.2</span> Anonymous
Namespace<span></span></a></li>
<li><a href="#unnamed-entities" id="toc-unnamed-entities"><span class="toc-section-number">4.4.3</span> Unnamed
entities<span></span></a></li>
</ul></li>
<li><a href="#namespaces" id="toc-namespaces"><span class="toc-section-number">4.5</span> Namespaces<span></span></a></li>
<li><a href="#types" id="toc-types"><span class="toc-section-number">4.6</span> Types<span></span></a>
<ul>
<li><a href="#qualifiers" id="toc-qualifiers"><span class="toc-section-number">4.6.1</span> Qualifiers<span></span></a></li>
</ul></li>
<li><a href="#ordering-scalar-types" id="toc-ordering-scalar-types"><span class="toc-section-number">4.7</span> Ordering Scalar
Types<span></span></a></li>
<li><a href="#ordering-array-types" id="toc-ordering-array-types"><span class="toc-section-number">4.8</span> Ordering Array
Types<span></span></a></li>
<li><a href="#ordering-class-types" id="toc-ordering-class-types"><span class="toc-section-number">4.9</span> Ordering Class
Types<span></span></a>
<ul>
<li><a href="#ordering-simple-class-types" id="toc-ordering-simple-class-types"><span class="toc-section-number">4.9.1</span> Ordering Simple Class
Types<span></span></a></li>
<li><a href="#non-type-template-parameters" id="toc-non-type-template-parameters"><span class="toc-section-number">4.9.2</span> Non Type Template
Parameters<span></span></a></li>
<li><a href="#ordering-class-template-specializations" id="toc-ordering-class-template-specializations"><span class="toc-section-number">4.9.3</span> Ordering Class Template
Specializations<span></span></a></li>
<li><a href="#function-types" id="toc-function-types"><span class="toc-section-number">4.9.4</span> Function
Types<span></span></a></li>
<li><a href="#member-function-types" id="toc-member-function-types"><span class="toc-section-number">4.9.5</span> Member Function
Types<span></span></a></li>
<li><a href="#variadic-function-types" id="toc-variadic-function-types"><span class="toc-section-number">4.9.6</span> Variadic Function
Types<span></span></a></li>
<li><a href="#parameter-packs" id="toc-parameter-packs"><span class="toc-section-number">4.9.7</span> Parameter
Packs<span></span></a></li>
<li><a href="#ordering-class-templates" id="toc-ordering-class-templates"><span class="toc-section-number">4.9.8</span> Ordering Class
Templates<span></span></a></li>
<li><a href="#variable-templates" id="toc-variable-templates"><span class="toc-section-number">4.9.9</span> Variable
Templates<span></span></a></li>
<li><a href="#alias-templates" id="toc-alias-templates"><span class="toc-section-number">4.9.10</span> Alias
Templates<span></span></a></li>
<li><a href="#concepts" id="toc-concepts"><span class="toc-section-number">4.9.11</span> Concepts<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">5</span>
Acknowledgements<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>Currently, <code class="sourceCode default">std::type_info</code>
provides a stable but <em>implementation defined</em> order of types.
Despite being a compile-time property, the implementation defined
<code class="sourceCode default">type_info::before</code> is not marked
<code class="sourceCode default">constexpr</code>. This paper explores a
standardized ordering of types in C++, as well as the impact of marking
<code class="sourceCode default">type_info::before</code>
<code class="sourceCode default">constexpr</code>.</p>
<h1 data-number="2" id="revision-history"><span class="header-section-number">2</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<ol start="0" type="1">
<li>New Paper</li>
</ol>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>There is currently no way in C++ to sort types. Well-performing
typesets, required by various policy-based template libraries, require
<code class="sourceCode default">constexpr</code> evaluation of
order.</p>
<p>This presents unsolvable problems for libraries that provide types
whose behavior is configured using a set (not a list) of policies.</p>
<p>The inability to sort these policies into a canonical order results
in different types with the same behavior.</p>
<p>A consistent strong ordering of types would also allow such typesets
to produce the same symbol in different compilation units, thus allowing
consistent linking of such compilation units.</p>
<h1 data-number="4" id="proposal"><span class="header-section-number">4</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>This proposal only concerns itself with ordering types. However, it
has implications for the whole reflection space as it is a subset of
providing strong ordering on
<code class="sourceCode default">std::meta::info</code> objects.</p>
<p>Below, we propose a canonical way of sorting all types in c++, which
allows us to mark
<code class="sourceCode default">std::type_info::before</code>
<code class="sourceCode default">constexpr</code>.</p>
<p>This proposal does not propose marking type successor access as
<code class="sourceCode default">constexpr</code> (i.e.
<code class="sourceCode default">typeid(int).next()</code>), as the
result of that is by necessity compilation-unit specific.</p>
<h2 data-number="4.1" id="approach-outline"><span class="header-section-number">4.1</span> Approach outline<a href="#approach-outline" class="self-link"></a></h2>
<ol type="1">
<li>We define a <strong>lowering to a <em>key-tuple</em></strong> for
every type in the language.</li>
<li>The order is then defined on these <em>key-tuples</em>.</li>
</ol>
<h2 data-number="4.2" id="structure-of-key-tuples"><span class="header-section-number">4.2</span> Structure of key-tuples<a href="#structure-of-key-tuples" class="self-link"></a></h2>
<p>Every <em>key-tuple</em> is of the form
<code class="sourceCode default">($_element_$...)</code>.</p>
<p>where an element is one of:</p>
<ul>
<li><em>atom</em> (see <a href="#atoms">atoms</a>)</li>
<li><em>key-tuple</em></li>
</ul>
<p>These tuples are then ordered lexicographically (ties broken in favor
of shorter tuple), atoms before tuples.</p>
<p>Let us name this transformation as
<code class="sourceCode default">sort_key(entity)</code>.</p>
<p>The rest of the paper is concerned with defining this
transformation.</p>
<h3 data-number="4.2.1" id="example"><span class="header-section-number">4.2.1</span> Example:<a href="#example" class="self-link"></a></h3>
<p>Given</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="kw">namespace</span> foo<span class="op">::</span>bar <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> i;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> baz <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> j;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then:</p>
<ul>
<li><code class="sourceCode default">sort_key(foo::bar::i)</code> is
<code class="sourceCode default">((namespace, foo), (namespace, bar), (type, i))</code>.</li>
<li><code class="sourceCode default">sort_key(baz::j)</code> is
<code class="sourceCode default">((namespace, baz), (type, j))</code></li>
</ul>
<p>When compared, the result is that
<code class="sourceCode default">baz::j</code> &lt;
<code class="sourceCode default">foo::bar::i</code>, since
<code class="sourceCode default">namespace baz</code> precedes
<code class="sourceCode default">namespace foo</code>.</p>
<h2 data-number="4.3" id="atoms"><span class="header-section-number">4.3</span> Atoms<a href="#atoms" class="self-link"></a></h2>
<p>The atoms of <em>key-tuples</em> are ordered as follows:</p>
<ol type="1">
<li>kinds (see <a href="#kinds">kinds</a>)</li>
<li>simple names (including empty string) (see <a href="#names">names</a>)</li>
<li>qualifiers (see <a href="#qualifiers">qualifiers</a>)</li>
<li><code class="sourceCode default">[]</code> (array of unknown
bound)</li>
<li><code class="sourceCode default">[n]</code> (array of known bound n)
(ordered by <code class="sourceCode default">n</code> internally)</li>
<li><code class="sourceCode default">*</code> (pointer)</li>
<li>ellipsis (<code class="sourceCode default">...</code> in
<code class="sourceCode default">f(...)</code>)</li>
<li>parameter pack (<code class="sourceCode default">...</code> in
<code class="sourceCode default">typename...</code>)</li>
</ol>
<h3 data-number="4.3.1" id="kinds"><span class="header-section-number">4.3.1</span> Kinds<a href="#kinds" class="self-link"></a></h3>
<p>There are the following kind tokens that can appear in
<em>key-tuples</em>.</p>
<ol type="1">
<li>value</li>
<li>namespace</li>
<li>type</li>
<li>class template</li>
<li>type alias template</li>
<li>variable template</li>
<li>concept</li>
<li>function</li>
</ol>
<p>Note: everything but values is pretty simple, but we haven’t dealt
with values extensively yet with the R0 of this paper.</p>
<h2 data-number="4.4" id="identifiers"><span class="header-section-number">4.4</span> Identifiers<a href="#identifiers" class="self-link"></a></h2>
<h3 data-number="4.4.1" id="simple-names"><span class="header-section-number">4.4.1</span> Simple Names<a href="#simple-names" class="self-link"></a></h3>
<p>Most names are strings that are valid (atomic) identifiers. Those are
just themselves:</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">namespace</span> foo<span class="op">::</span>bar <span class="op">{</span> <span class="kw">struct</span> baz; <span class="op">}</span></span></code></pre></div>
<p><code class="sourceCode default">foo</code>,
<code class="sourceCode default">bar</code> and
<code class="sourceCode default">baz</code> are such atomic
identifiers.</p>
<h3 data-number="4.4.2" id="anonymous-namespace"><span class="header-section-number">4.4.2</span> Anonymous Namespace<a href="#anonymous-namespace" class="self-link"></a></h3>
<p>The identifier for the anonymous namespace is the empty string.</p>
<p>Example:</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">namespace</span> a <span class="op">{</span> <span class="kw">namespace</span> <span class="op">{</span> <span class="kw">struct</span> s; <span class="op">}</span> <span class="op">}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>sort_key<span class="op">(</span>a<span class="op">::</span>s<span class="op">)</span> <span class="op">=</span> <span class="op">((</span><span class="kw">namespace</span>, a<span class="op">)</span>, <span class="op">(</span><span class="kw">namespace</span>, <span class="st">&quot;&quot;</span><span class="op">)</span>, <span class="op">(</span>type, s, <span class="op">))</span></span></code></pre></div>
<h3 data-number="4.4.3" id="unnamed-entities"><span class="header-section-number">4.4.3</span> Unnamed entities<a href="#unnamed-entities" class="self-link"></a></h3>
<p>Unnamed entities are all given a name that is not an identifier (but
is, in fact, a tuple), and are then numbered consecutively, starting
with zero, based on their name-scope.</p>
<p>Name-scopes are namespaces, classes, unions, functions, and
enumerations.</p>
<p>Function declarations are name-scoped to the function itself.</p>
<p>Consider a lambda that appears as a default argument of a function
template:</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">typename</span> T<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>T x <span class="op">=</span> <span class="op">[]{</span> <span class="cf">return</span> T<span class="op">{</span><span class="dv">0</span><span class="op">}</span>; <span class="op">}())</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="co">//           ^^^^^^^^^^^^^^^^^^ this one</span></span></code></pre></div>
<p>The <em>key-tuple</em> for
<code class="sourceCode default">f&lt;int&gt;</code> is:</p>
<p><code class="sourceCode default">(function, (f, (type, int)), (type, void), ((type, int)))</code></p>
<p>The <em>key-tuple</em> for the lambda is:</p>
<p><code class="sourceCode default">((function, (f, (type, int)), (type, void), ((type, int))), (type, (lambda, 0), ))</code>.</p>
<p>Note: because of the regular structure of <em>key-tuples</em>, such
anonymous classes will compare greater than any entity that has a simple
identifier, due to tuples comparing greater than atoms (which simple
names are).</p>
<h4 data-number="4.4.3.1" id="lambda-types"><span class="header-section-number">4.4.3.1</span> Lambda types<a href="#lambda-types" class="self-link"></a></h4>
<p>Types of lambda objects are ordered first by where they are declared,
then by declaration order.</p>
<p>In effect, we assign them the name
<code class="sourceCode default">(lambda, #)</code> where
<code class="sourceCode default">#</code> is the count of other unnamed
entities in the name scope.</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">namespace</span> Banana <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">auto</span> i <span class="op">=</span> <span class="op">[](</span><span class="dt">int</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{}</span>; <span class="co">// 0th lambda instantiated in Banana</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> Apple <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> i <span class="op">=</span> <span class="op">[](</span><span class="dt">float</span><span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{}</span>; <span class="co">// 0th lambda instantiated in Apple</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> j <span class="op">=</span> <span class="op">[]()</span> <span class="op">-&gt;</span> std<span class="op">::</span>string <span class="op">{}</span>; <span class="co">// 1st lambda instantiated in Apple</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>These would produce the following tuples:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>sort_key(decltype(Banana::i)) = ((namespace, Banana), (type, (lambda, 0), ));</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>sort_key(decltype(Apple::i))  = ((namespace, Apple), (type, (lambda, 0), ));</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>sort_key(decltype(Apple::j))  = ((namespace, Apple), (type, (lambda, 1), ));</span></code></pre></div>
<p>Note: the empty bit after the identifier is the empty qualifier
pack.</p>
<h4 data-number="4.4.3.2" id="unnamed-struct-and-union-types"><span class="header-section-number">4.4.3.2</span> Unnamed
<code class="sourceCode default">struct</code> and
<code class="sourceCode default">union</code> types<a href="#unnamed-struct-and-union-types" class="self-link"></a></h4>
<p>They are named, respectively,
<code class="sourceCode default">(class, #)</code> and
<code class="sourceCode default">(union, #)</code>.</p>
<h2 data-number="4.5" id="namespaces"><span class="header-section-number">4.5</span> Namespaces<a href="#namespaces" class="self-link"></a></h2>
<p>The <code class="sourceCode default">sort_key(namespace-name)</code>
is <code class="sourceCode default">(namespace, identifier)</code>.</p>
<p>This means that namespaces are ordered alphabetically by comparing
namespace names at the same rank. A namespace comes before any of its
subnamespaces.</p>
<p>Example:</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="kw">namespace</span> outer1 <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> i;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</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">namespace</span> outer2 <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> inner1 <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> i;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> inner2 <span class="op">{</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> i;</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The order of the three structs w/ type
<code class="sourceCode default">i</code> types shall be</p>
<p><code class="sourceCode default">sort_key(outer1::i) &lt; sort_key(outer2::inner1::i) &lt; sort_key(outer2::inner2::i)</code>.</p>
<h2 data-number="4.6" id="types"><span class="header-section-number">4.6</span> Types<a href="#types" class="self-link"></a></h2>
<p>The <code class="sourceCode default">sort_key</code> of a type is
<code class="sourceCode default">(type, &lt;identifier&gt;, &lt;qualifiers&gt;)</code>.</p>
<p>The <code class="sourceCode default">&lt;identifier&gt;</code> bit is
a bit complicated, so let’s deal with the qualifiers first.</p>
<p>Note: any name-scopes the
<code class="sourceCode default">type</code> is declared in are part of
the parent <em>key-tuple</em>. The
<code class="sourceCode default">identifier</code> portion is
complicated because of possible template arguments for types that are
template specializations.</p>
<h3 data-number="4.6.1" id="qualifiers"><span class="header-section-number">4.6.1</span> Qualifiers<a href="#qualifiers" class="self-link"></a></h3>
<p>Qualifiers are each assigned a score</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>&amp;: 1</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>&amp;&amp;: 2</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>const: 3</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>volatile: 6</span></code></pre></div>
<p>and ordering lowest-first after summing them.</p>
<p>Therefore, for an unqualified type
<code class="sourceCode default">T</code>, the order of all possible
qualified types would be:</p>
<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="dv">0</span>  T</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span>  T <span class="op">&amp;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="dv">2</span>  T <span class="op">&amp;&amp;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span>  T <span class="kw">const</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="dv">4</span>  T <span class="kw">const</span> <span class="op">&amp;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="dv">5</span>  T <span class="kw">const</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="dv">6</span>  T <span class="kw">volatile</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="dv">7</span>  T <span class="kw">volatile</span> <span class="op">&amp;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="dv">8</span>  T <span class="kw">volatile</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="dv">9</span>  T <span class="kw">const</span> <span class="kw">volatile</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="dv">10</span> T <span class="kw">const</span> <span class="kw">volatile</span> <span class="op">&amp;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="dv">11</span> T <span class="kw">const</span> <span class="kw">volatile</span> <span class="op">&amp;&amp;</span></span></code></pre></div>
<p>The remainder of the paper concerns itself only with unqualified
types.</p>
<h2 data-number="4.7" id="ordering-scalar-types"><span class="header-section-number">4.7</span> Ordering Scalar Types<a href="#ordering-scalar-types" class="self-link"></a></h2>
<p>All scalar types are built-in types, except for enumerations, which
should be ordered according to their namespaced names.</p>
<p>Unfortunately, some of the built-in types do not have names, only
type aliases (such as
<code class="sourceCode default">decltype(nullptr)</code>).</p>
<p>The intention is for built-in scalar types to be ordered before any
compound types.</p>
<p>Built-in types with simple names should be ordered before any types
that reference other types.</p>
<p>In particular, scalar types shall be ordered as follows:</p>
<ol type="1">
<li><code class="sourceCode default">void</code> comes first because
it’s not reifiable,</li>
<li>the type of <code class="sourceCode default">std::nullptr_t</code>
as the first monostate</li>
<li>any other monostates, if added, sorted alphabetically by their
common names (to be specified explicitly if added)</li>
<li><code class="sourceCode default">bool</code> as the first
bi-state</li>
<li>any other bi-states, if added, sorted alphabetically.</li>
<li>Raw-memory types (<code class="sourceCode default">char</code>,
<code class="sourceCode default">signed char</code>,
<code class="sourceCode default">unsigned char</code>) (std::byte is an
enumeration in <code class="sourceCode default">std</code> so it falls
under different rules)</li>
<li>Integral types in order of size, signed before unsigned
(<code class="sourceCode default">short</code>,
<code class="sourceCode default">unsigned    short</code>,
<code class="sourceCode default">int</code>,
<code class="sourceCode default">unsigned int</code>,
<code class="sourceCode default">long</code>,
<code class="sourceCode default">unsigned long</code>,
<code class="sourceCode default">long long</code>,
<code class="sourceCode default">unsigned long long</code>, followed by
any implementation-defined wider integral types like
<code class="sourceCode default">__int128_t</code> etc.). Intersperse
any implementation-defined built-in integral types as needed between the
above.</li>
<li>Any remaining character types that are not type-aliases of any of
the above, including unicode, according to the following rules: smallest
first, unicode-specific variants after non-unicode variants.</li>
<li>Floating-point types, in order of size. In case of ties,
<code class="sourceCode default">float</code>,
<code class="sourceCode default">double</code> and
<code class="sourceCode default">long double</code> come before any
floating point types.</li>
<li>Function types (internally ordered by rules in section <a href="#function-types">Function Types</a>)</li>
<li>Pointer types (internally ordered by their pointee-type)</li>
<li>Pointer-to-member types (internally ordered by pointee-type)</li>
</ol>
<p>Class types shall be ordered according to the rules below, see
[Ordering Compound Types]</p>
<h2 data-number="4.8" id="ordering-array-types"><span class="header-section-number">4.8</span> Ordering Array Types<a href="#ordering-array-types" class="self-link"></a></h2>
<p>Array types shall be ordered after scalar types but before class
types.</p>
<p>The <code class="sourceCode default">sort_key(T[]) = ([], sort_key(T))</code> and
the <code class="sourceCode default">sort_key(T[n]) = ([n], sort_key(T))</code>.</p>
<p>The intention is to order arrays first internally by element type,
then by rank, then by rank bounds, lowest first. Arrays of unknown
bounds come before arrays of known bounds.</p>
<p>So the order of the following, for a given type T:</p>
<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>T<span class="op">[]</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>T<span class="op">[</span><span class="dv">10</span><span class="op">]</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>T<span class="op">[</span><span class="dv">11</span><span class="op">]</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>T<span class="op">[][</span><span class="dv">2</span><span class="op">]</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">[</span><span class="dv">10</span><span class="op">][</span><span class="dv">2</span><span class="op">]</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>T<span class="op">[</span><span class="dv">3</span><span class="op">][</span><span class="dv">2</span><span class="op">]</span></span></code></pre></div>
<p>shall be ordered <code class="sourceCode default">T[] &lt; T[10] &lt; T[11] &lt; T[][2] &lt; T[3][2] &lt; T[10][2]</code>,
and</p>
<p><code class="sourceCode default">sort_key(T[0]) = (type, ([], (type, T, )))</code></p>
<p><code class="sourceCode default">sort_key(T[10][2]) = (type, ([2], sort_key(T[10]))) = (type, ([2], (type, ([10], (type, T, ))))</code></p>
<h2 data-number="4.9" id="ordering-class-types"><span class="header-section-number">4.9</span> Ordering Class Types<a href="#ordering-class-types" class="self-link"></a></h2>
<h3 data-number="4.9.1" id="ordering-simple-class-types"><span class="header-section-number">4.9.1</span> Ordering Simple Class Types<a href="#ordering-simple-class-types" class="self-link"></a></h3>
<p>Class types shall be greater than scalar types.</p>
<p>Since we cannot redeclare two types with the same name, class types
shall be ordered alphabetically.</p>
<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">struct</span> Apple <span class="op">{}</span>;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Banana <span class="op">{}</span>;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Carrot <span class="op">{}</span>;</span></code></pre></div>
<p>Would be ordered as
<code class="sourceCode default">Apple &lt; Banana &lt; Carrot</code></p>
<p>As such, we define sort key as:</p>
<p><code class="sourceCode default">sort_key(Apple) = (type, Apple, )</code></p>
<p><code class="sourceCode default">sort_key(Banana) = (type, Banana, )</code></p>
<p><code class="sourceCode default">sort_key(Carrot) = (type, Carrot, )</code></p>
<h3 data-number="4.9.2" id="non-type-template-parameters"><span class="header-section-number">4.9.2</span> Non Type Template
Parameters<a href="#non-type-template-parameters" class="self-link"></a></h3>
<p>NTTPs shall first be ordered by their type, then their value.</p>
<p>Given:</p>
<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="kw">auto</span> T<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> s <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">decltype</span><span class="op">(</span>T<span class="op">)</span> i <span class="op">=</span> T;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>s<span class="op">&lt;</span><span class="dv">1</span><span class="bu">u</span><span class="op">&gt;</span> a;</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>s<span class="op">&lt;</span><span class="fl">1.0</span><span class="bu">f</span><span class="op">&gt;</span> b;</span></code></pre></div>
<p><code class="sourceCode default">sort_key(s&lt;1u&gt;) = ((type, (s, sort_key(1u))))</code></p>
<p>We can define sort_key of <code class="sourceCode default">1u</code>
as: <code class="sourceCode default">sort_key(1u) = ( sort_key(decltype(1u)), 1)</code></p>
<p><code class="sourceCode default">s&lt;1u&gt;</code> shall be ordered
before <code class="sourceCode default">s&lt;1.0f&gt;</code>, as
integral types come before floating point types.</p>
<p>NTTPs of the same type shall be lexicographically ordered by their
scalar subobjects.</p>
<p>NTTPs of the same pointer type shall be ordered by instantiation
order.</p>
<h3 data-number="4.9.3" id="ordering-class-template-specializations"><span class="header-section-number">4.9.3</span> Ordering Class Template
Specializations<a href="#ordering-class-template-specializations" class="self-link"></a></h3>
<p>Class templates shall be ordered by:</p>
<ol type="1">
<li>Class name, alphabetically.</li>
<li>Template arguments, applied lexicographically.</li>
</ol>
<p>For example, given:</p>
<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="kw">typename</span> U<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> Apple;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Banana;</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Carrot;</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>Apple<span class="op">&lt;</span>Banana, Carrot<span class="op">&gt;</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>Apple<span class="op">&lt;</span>Banana, Banana<span class="op">&gt;</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>Apple<span class="op">&lt;</span>Carrot, Carrot<span class="op">&gt;</span>;</span></code></pre></div>
<p>Note,
<code class="sourceCode default">sort_key(&lt;parameter&gt;)...</code>
will be used to denote a tuple where
<code class="sourceCode default">sort_key</code> has been applied to all
parameters.</p>
<p>For <code class="sourceCode default">void f(Foo, Bar)</code>
<code class="sourceCode default">sort_key(&lt;parameter&gt;)...</code>
would mean
<code class="sourceCode default">(sort_key(Foo), sort_key(Bar))</code></p>
<p><code class="sourceCode default">sort_key</code> of a class template
shall be defined as:</p>
<p><code class="sourceCode default">sort_key(&lt;class template&gt;) = (type, (&lt;name&gt;, (sort_key(&lt;parameter&gt;)...)))</code></p>
<p>So</p>
<p><code class="sourceCode default">sort_key(Apple&lt;Banana, Carrot&gt; = (type, (Apple, (sort_key(Banana), sort_key(Carrot)), )</code></p>
<p><code class="sourceCode default">sort_key(Apple&lt;Banana, Carrot&gt; = (type, (Apple, ((type, Banana, ), (type, Carrot, )), )</code></p>
<p>Note: the empty bit after the identifier is the empty qualifier
pack.</p>
<p>The above would be ordered <code class="sourceCode default">sort_key(Apple&lt;Banana, Banana&gt;)</code>,
<code class="sourceCode default">sort_key(Apple&lt;Banana, Carrot&gt;)</code>,
<code class="sourceCode default">sort_key(Apple&lt;Carrot, Carrot&gt;</code>.</p>
<h3 data-number="4.9.4" id="function-types"><span class="header-section-number">4.9.4</span> Function Types<a href="#function-types" class="self-link"></a></h3>
<p>Function types shall be ordered by</p>
<ol type="1">
<li>Return type</li>
<li>Parameters, lexicographically.</li>
</ol>
<p>The <code class="sourceCode default">sort_key</code> of a function
shall be defined as:</p>
<p><code class="sourceCode default">sort_key(&lt;function&gt;) = (function, &lt;name&gt;, sort_key(&lt;return type&gt;), (sort_key(&lt;parameter&gt;)...))</code></p>
<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="dt">void</span> foo<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span>;</span></code></pre></div>
<p>This function can be represented by: <code class="sourceCode default">(function, (foo, (type, void), ((type, int))))</code></p>
<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="dt">void</span> foo<span class="op">(</span><span class="dt">int</span><span class="op">)</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span><span class="dt">int</span>, <span class="dt">double</span><span class="op">)</span></span></code></pre></div>
<p><code class="sourceCode default">sort_key(void foo(int)) = (function, foo, (type, void), ((type, int)))</code></p>
<p><code class="sourceCode default">sort_key(void foo(int, double)) = (function, foo, (type, void), ((type, int), (type, double)))</code></p>
<p>So, the type of <code class="sourceCode default">void foo(int)</code>
would precede the type of
<code class="sourceCode default">void foo(int, double)</code></p>
<h3 data-number="4.9.5" id="member-function-types"><span class="header-section-number">4.9.5</span> Member Function Types<a href="#member-function-types" class="self-link"></a></h3>
<p>Function types shall be ordered by</p>
<ol type="1">
<li>Return type</li>
<li>The type of the class it is a member of.</li>
<li>Parameters, lexicographically.</li>
</ol>
<p>The sort key of a member function shall be defined as:</p>
<p><code class="sourceCode default">sort_key(&lt;member function&gt;) =</code></p>
<p><code class="sourceCode default">(function, (&lt;name&gt;, sort_key(&lt;class&gt;)), sort_key(&lt;return type&gt;), (sort_key(&lt;parameter&gt;)...))))</code></p>
<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">struct</span> Foo <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> bar<span class="op">(</span><span class="dt">int</span> i, <span class="dt">float</span> j<span class="op">)</span>;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><code class="sourceCode default">sort_key(Foo::bar) =</code></p>
<p><code class="sourceCode default">(type, Foo, ), (function, (bar, (type, Foo, )), (type, void), ((type, int, ), (type, float, ))))</code></p>
<h3 data-number="4.9.6" id="variadic-function-types"><span class="header-section-number">4.9.6</span> Variadic Function Types<a href="#variadic-function-types" class="self-link"></a></h3>
<p>Variadic function shall be ordered in a similar way. In a variadic
function, the last argument is a variadic argument. A variadic argument
shall be ordered immediately after its underlying type.</p>
<p>Given:</p>
<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="dt">void</span> foo<span class="op">(</span>Foo<span class="op">)</span>;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>Foo<span class="op">...)</span>;</span></code></pre></div>
<p>In this case, the type of
<code class="sourceCode default">void foo(Foo...)</code> is ordered
immediately after the type of
<code class="sourceCode default">void foo(Foo)</code>.</p>
<p>We can represent these as:</p>
<p><code class="sourceCode default">(function (type, void) (type, Foo, ))</code></p>
<p><code class="sourceCode default">(function (type, void) (type, Foo, ...))</code></p>
<h3 data-number="4.9.7" id="parameter-packs"><span class="header-section-number">4.9.7</span> Parameter Packs<a href="#parameter-packs" class="self-link"></a></h3>
<p>Parameter are ordered as class templates.</p>
<p>Given:</p>
<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><span class="op">...</span> Types<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Tuple <span class="op">{}</span>;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Foo <span class="op">{}</span>;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Bar <span class="op">{}</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>Tuple<span class="op">&lt;&gt;</span> t0;</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>Tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> t1;</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>Tuple<span class="op">&lt;</span>Foo<span class="op">&gt;</span> t2;</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>Tuple<span class="op">&lt;</span>Bar<span class="op">&gt;</span> t3;</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>Tuple<span class="op">&lt;</span>Foo, Bar<span class="op">&gt;</span> t4;</span></code></pre></div>
<p>would be ordered:
<code class="sourceCode default">Tuple&lt;&gt;</code> &lt;
<code class="sourceCode default">Tuple&lt;int&gt;</code> &lt;
<code class="sourceCode default">Tuple&lt;Bar&gt;</code> &lt;
<code class="sourceCode default">Tuple&lt;Foo&gt;</code> &lt;
<code class="sourceCode default">Tuple&lt;Foo, Bar&gt;</code></p>
<h3 data-number="4.9.8" id="ordering-class-templates"><span class="header-section-number">4.9.8</span> Ordering Class Templates<a href="#ordering-class-templates" class="self-link"></a></h3>
<p>Kinds of templates are ordered first by name, then by template
arguments.</p>
<p>Given:</p>
<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">template</span> <span class="op">&lt;</span><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span><span class="op">&gt;</span> <span class="kw">class</span><span class="op">&gt;</span> <span class="kw">class</span> Template<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> two<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><span class="kw">typename</span><span class="op">&gt;</span> <span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> one<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><span class="kw">typename</span><span class="op">&gt;</span> <span class="kw">struct</span> zero<span class="op">{}</span>;</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>zero<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> value0;</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>one<span class="op">&lt;</span>zero<span class="op">&gt;</span> value1;</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>two<span class="op">&lt;</span>one<span class="op">&gt;</span> value2;</span></code></pre></div>
<p>These are represented by tuples:</p>
<p><code class="sourceCode default">sort_key(zero&lt;int&gt;) = (type, (zero, (type, int)))</code></p>
<p><code class="sourceCode default">sort_key(one&lt;zero&gt;) = (type, (one, (class_template, zero))))</code></p>
<p><code class="sourceCode default">sort_key(two&lt;one&gt;) = (type, (two, (class_template, one))))</code></p>
<h3 data-number="4.9.9" id="variable-templates"><span class="header-section-number">4.9.9</span> Variable Templates<a href="#variable-templates" class="self-link"></a></h3>
<p>Variable templates are ordered by name, then by template
parameter.</p>
<p><code class="sourceCode default">sort_key(&lt;variable_template&gt;) = (variable_template, (&lt;name&gt;, (sort_key(&lt;template_parameter&gt;)...)))</code></p>
<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> F, <span class="kw">typename</span> S<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>pair<span class="op">&lt;</span>F, S<span class="op">&gt;</span> pair_one_two <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span>;</span></code></pre></div>
<p>the type of
<code class="sourceCode default">pair_one_two&lt;int, double&gt;</code>
can be represented as:</p>
<p><code class="sourceCode default">sort_key(pair_one_two&lt;int, double&gt;) = (variable_template, (pair_one_two, (type, int), (type, double)))</code></p>
<h3 data-number="4.9.10" id="alias-templates"><span class="header-section-number">4.9.10</span> Alias Templates<a href="#alias-templates" class="self-link"></a></h3>
<p>Alias templates are ordered alphabetically by name.</p>
<p><code class="sourceCode default">sort_key(&lt;alias_template&gt;) = (alias_template, &lt;name&gt;)</code></p>
<p>Given</p>
<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">class</span> T <span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> remove_cvref_t <span class="op">=</span> <span class="kw">typename</span> remove_cvref<span class="op">&lt;</span>T<span class="op">&gt;::</span>type;</span></code></pre></div>
<p><code class="sourceCode default">sort_key(remove_cvref_t) = (alias_template, remove_cvref_t)</code></p>
<h3 data-number="4.9.11" id="concepts"><span class="header-section-number">4.9.11</span> Concepts<a href="#concepts" class="self-link"></a></h3>
<p>Concepts are ordered in a similar manner to variable templates.</p>
<p><code class="sourceCode default">sort_key(&lt;concept&gt;) = (concept, (&lt;name&gt;, (sort_key(&lt;template_parameter&gt;)...)))</code></p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-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="kw">typename</span> F <span class="op">=</span> <span class="kw">decltype</span><span class="op">([](</span>T<span class="op">){})&gt;</span> </span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> f <span class="op">=</span> <span class="kw">requires</span> <span class="op">(</span>T i, F f <span class="op">=</span> <span class="op">[](</span>T<span class="op">){})</span> <span class="op">{</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span>f<span class="op">(</span>i<span class="op">)}</span> <span class="op">-&gt;</span> std<span class="op">::</span>convertible_to<span class="op">&lt;</span><span class="dt">void</span><span class="op">&gt;</span>;</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>In order to order the type of the lambda declared in
<code class="sourceCode default">concept f</code>,
<code class="sourceCode default">concept f</code> must be comparable
with other types.</p>
<p>Concepts shall be ordered first by name, then by template
arguments.</p>
<p><code class="sourceCode default">sort_key(f&lt;int&gt;) = (concept, (f, (type, int), (lambda, 0)))</code></p>
<h1 data-number="5" id="acknowledgements"><span class="header-section-number">5</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Thanks to all of the following:</p>
<ul>
<li>Davis Herring for his suggestions on ordering non-type template
parameters.</li>
</ul>
</div>
</div>
</body>
</html>
