<!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="2022-07-15" />
  <title>Forwarding reference to specific type/template</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.hanging-indent{margin-left: 1.5em; text-indent: -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; }
      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;
}
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">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</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">Forwarding reference to specific type/template</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2481R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2022-07-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>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@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="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#introduction"><span class="toc-section-number">2</span> Introduction<span></span></a>
<ul>
<li><a href="#stdtuple-converting-constructor"><span class="toc-section-number">2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>tuple</code> converting constructor<span></span></a></li>
<li><a href="#stdget-for-stdtuple"><span class="toc-section-number">2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>get</code> for <code class="sourceCode cpp">std<span class="op">::</span>tuple</code><span></span></a></li>
<li><a href="#transform-for-stdoptional"><span class="toc-section-number">2.3</span> <code class="sourceCode cpp">transform</code> for <code class="sourceCode cpp">std<span class="op">::</span>optional</code><span></span></a></li>
<li><a href="#view_interface-members"><span class="toc-section-number">2.4</span> <code class="sourceCode cpp">view_interface</code> members<span></span></a></li>
<li><a href="#the-goal"><span class="toc-section-number">2.5</span> The Goal<span></span></a></li>
</ul></li>
<li><a href="#not-a-proposal"><span class="toc-section-number">3</span> Not a proposal<span></span></a>
<ul>
<li><a href="#t-auto"><span class="toc-section-number">3.1</span> <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&amp;&amp;</span></code><span></span></a></li>
<li><a href="#t"><span class="toc-section-number">3.2</span> <code class="sourceCode cpp">T<span class="op">&amp;&amp;&amp;</span></code><span></span></a></li>
<li><a href="#constbool"><span class="toc-section-number">3.3</span> <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="dt">bool</span><span class="op">)</span></code><span></span></a></li>
<li><a href="#qualifiers-q"><span class="toc-section-number">3.4</span> <code class="sourceCode cpp">qualifiers Q</code><span></span></a></li>
<li><a href="#circles-approach"><span class="toc-section-number">3.5</span> Circle’s approach<span></span></a></li>
<li><a href="#something-else"><span class="toc-section-number">3.6</span> Something else<span></span></a></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">4</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>Since <span class="citation" data-cites="P2481R0">[<a href="#ref-P2481R0" role="doc-biblioref">P2481R0</a>]</span>, added <a href="#circles-approach">Circle’s approach</a> and a choice implementor quote.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>There are many situations where the goal of a function template is deduce an arbitrary type - an arbitrary range, an arbitrary value, an arbitrary predicate, and so forth. But sometimes, we need something more specific. While we still want to allow for deducing <code class="sourceCode cpp"><span class="kw">const</span></code> vs mutable and lvalue vs rvalue, we know either what concrete type or concrete class template we need - and simply want to deduce <em>just</em> that. With the adoption of <span class="citation" data-cites="P0847R7">[<a href="#ref-P0847R7" role="doc-biblioref">P0847R7</a>]</span>, the incidence of this will only go up.</p>
<p>It may help if I provide a few examples.</p>
<h2 data-number="2.1" id="stdtuple-converting-constructor"><span class="header-section-number">2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>tuple</code> converting constructor<a href="#stdtuple-converting-constructor" class="self-link"></a></h2>
<p><code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>T<span class="op">...&gt;</span></code> is constructible from <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>U<span class="op">...&gt;</span> <em>cv</em> <em>ref</em></code> when <code class="sourceCode cpp">T<span class="op">...</span></code> and <code class="sourceCode cpp">U<span class="op">...</span></code> are the same size and each <code class="sourceCode cpp">T</code> is constructible from <code class="sourceCode cpp">U <em>cv</em> <em>ref</em></code> (plus another constraint to avoid clashing with other constructors that I’m just going to ignore for the purposes of this paper). The way this would be written today is:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>        <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>              <span class="op">&amp;&amp;</span> <span class="op">(</span>is_constructible_v<span class="op">&lt;</span>Ts, Us<span class="op">&amp;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>    tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;&amp;)</span>;</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>        <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-10"><a href="#cb1-10"></a>              <span class="op">&amp;&amp;</span> <span class="op">(</span>is_constructible_v<span class="op">&lt;</span>Ts, Us <span class="kw">const</span><span class="op">&amp;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb1-11"><a href="#cb1-11"></a>    tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;)</span>;</span>
<span id="cb1-12"><a href="#cb1-12"></a></span>
<span id="cb1-13"><a href="#cb1-13"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb1-14"><a href="#cb1-14"></a>        <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-15"><a href="#cb1-15"></a>              <span class="op">&amp;&amp;</span> <span class="op">(</span>is_constructible_v<span class="op">&lt;</span>Ts, Us<span class="op">&amp;&amp;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb1-16"><a href="#cb1-16"></a>    tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;&amp;&amp;)</span>;</span>
<span id="cb1-17"><a href="#cb1-17"></a></span>
<span id="cb1-18"><a href="#cb1-18"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb1-19"><a href="#cb1-19"></a>        <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-20"><a href="#cb1-20"></a>              <span class="op">&amp;&amp;</span> <span class="op">(</span>is_constructible_v<span class="op">&lt;</span>Ts, Us <span class="kw">const</span><span class="op">&amp;&amp;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb1-21"><a href="#cb1-21"></a>    tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;&amp;)</span>;</span>
<span id="cb1-22"><a href="#cb1-22"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>This is pretty tedious to say the least. But it also has a subtle problem: these constructors are all <em>overloads</em> - which means that if the one you’d think would be called is valid, it is still possible for a different one to be invoked. For instance:</p>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">void</span> f<span class="op">(</span>tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;)</span>;</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> g<span class="op">()</span> <span class="op">-&gt;</span> tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&amp;&gt;</span>;</span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="dt">void</span> h<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    f<span class="op">(</span>g<span class="op">())</span>; <span class="co">// ok!</span></span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Here, we’re trying to construct a <code class="sourceCode cpp">tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;</span></code> from an <em>rvalue</em> <code class="sourceCode cpp">tuple<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&amp;&gt;</span></code>. The desired behavior is that the <code class="sourceCode cpp">tuple<span class="op">&lt;</span>Us<span class="op">...&gt;&amp;&amp;</span></code> is considered and then rejected (because <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;</span></code> is not constructible from <code class="sourceCode cpp">Us<span class="op">&amp;&amp;</span></code> - <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;&amp;</span></code>). That part indeed happens. But the <code class="sourceCode cpp">tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;</span></code> constructor still exists and that one ends up being fine (because <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;</span></code> is constructible from <code class="sourceCode cpp">Us <span class="kw">const</span><span class="op">&amp;</span></code> - which is <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;</span></code> here). That’s surprising and undesirable.</p>
<p>But in order to avoid this, we’d need to only have a single constructor template. What we <em>want</em> is to have <em>some kind</em> of <code class="sourceCode cpp">tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span></code> and just deduce the <code class="sourceCode cpp"><em>cv</em> <em>ref</em></code> part. But our only choice today is either the code above (tedious, yet mostly functional, despite this problem) or to go full template:</p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Other<span class="op">&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>        <span class="kw">requires</span> is_specialization_of<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>Other<span class="op">&gt;</span>, tuple<span class="op">&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>              <span class="op">&amp;&amp;</span> <span class="co">/* ???? */</span></span>
<span id="cb3-6"><a href="#cb3-6"></a>    tuple<span class="op">(</span>Other<span class="op">&amp;&amp;</span> rhs<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>How do we write the rest of the constraint? We don’t really have a good way of doing so. Besides, for types which inherit from <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>, this is now actually wrong - that derived type will not be a specialization of tuple, but rather instead inherit from one. We have to do extra work to get that part right, as we currently do in the <code class="sourceCode cpp">std<span class="op">::</span>visit</code> specification - see <span>22.6.7 <a href="https://wg21.link/variant.visit">[variant.visit]</a></span>/1.</p>
<h2 data-number="2.2" id="stdget-for-stdtuple"><span class="header-section-number">2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>get</code> for <code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdget-for-stdtuple" class="self-link"></a></h2>
<p>We run into the same thing for non-member functions, where we want to have <code class="sourceCode cpp">std<span class="op">::</span>get<span class="op">&lt;</span>I<span class="op">&gt;</span></code> be invocable on every kind of tuple. Which today likewise has to be written:</p>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&amp;)</span> <span class="op">-&gt;</span> tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;&amp;</span>;</span>
<span id="cb4-3"><a href="#cb4-3"></a></span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;)</span> <span class="op">-&gt;</span> tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb4-6"><a href="#cb4-6"></a></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&amp;&amp;)</span> <span class="op">-&gt;</span> tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;&amp;&amp;</span>;</span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb4-11"><a href="#cb4-11"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> tuple_element_t<span class="op">&lt;</span>I, tuple<span class="op">&lt;</span>Ts<span class="op">...&gt;&gt;</span> <span class="kw">const</span><span class="op">&amp;&amp;</span>;</span></code></pre></div>
</blockquote>
<p>This one we could try to rewrite as a single function template, but in order to do that, we need to first coerce the type down to some kind of specialization of <code class="sourceCode cpp">tuple</code> - which ends up requiring a lot of the same work anyway.</p>
<h2 data-number="2.3" id="transform-for-stdoptional"><span class="header-section-number">2.3</span> <code class="sourceCode cpp">transform</code> for <code class="sourceCode cpp">std<span class="op">::</span>optional</code><a href="#transform-for-stdoptional" class="self-link"></a></h2>
<p>The previous two examples want to deduce to some specialization of a class template, this example wants to deduce to a specific type. One of the motivation examples from “deducing <code class="sourceCode cpp"><span class="kw">this</span></code>” was to remove the quadruplication necessary when writing a set of overloads that want to preserve <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category. The adoption of <span class="citation" data-cites="P0798R8">[<a href="#ref-P0798R8" role="doc-biblioref">P0798R8</a>]</span> gives us several such examples.</p>
<p>In C++20, we’d write it as:</p>
<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-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="cb5-2"><a href="#cb5-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&amp;&amp;)</span> <span class="op">&amp;</span>;</span>
<span id="cb5-4"><a href="#cb5-4"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&amp;&amp;)</span> <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb5-5"><a href="#cb5-5"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&amp;&amp;)</span> <span class="op">&amp;&amp;</span>;</span>
<span id="cb5-6"><a href="#cb5-6"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&amp;&amp;)</span> <span class="kw">const</span><span class="op">&amp;&amp;</span>;</span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>complete with quadruplicating the body. But with deducing this, we might consider writing it as:</p>
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-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="cb6-2"><a href="#cb6-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Self, <span class="kw">typename</span> F<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> Self<span class="op">&amp;&amp;</span>, F<span class="op">&amp;&amp;)</span>;</span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>But this deduces too much! We don’t want to deduce derived types (which in addition to unnecessary extra template instantiations, can also run into <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#the-shadowing-mitigation-private-inheritance-problem">shadowing issues</a>). We <em>just</em> want to know what the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category of the <code class="sourceCode cpp">optional</code> are. But the only solution at the moment is to C-style cast your way back down to your own type. And that’s not a particular popular solution, even amongst <a href="https://discourse.llvm.org/t/std-pmr-maturity/62200/17">standard library implementors</a>:</p>
<div class="quote">
<p>FWIW, we’re no longer using explicit object member functions for <code class="sourceCode cpp">std<span class="op">::</span>expected</code>; STL couldn’t stomach the necessary C-style cast without which the feature is not fit for purpose.</p>
</div>
<h2 data-number="2.4" id="view_interface-members"><span class="header-section-number">2.4</span> <code class="sourceCode cpp">view_interface</code> members<a href="#view_interface-members" class="self-link"></a></h2>
<p>Similar to the above, but even more specific, are the members for <code class="sourceCode cpp">view_interface</code> (see <span>26.5.3 <a href="https://wg21.link/view.interface">[view.interface]</a></span>). Currently, we have a bunch of pairs of member functions:</p>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="kw">class</span> view_interface <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3"></a>    <span class="kw">constexpr</span> D<span class="op">&amp;</span> derived<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>D<span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb7-4"><a href="#cb7-4"></a>    <span class="kw">constexpr</span> D <span class="kw">const</span><span class="op">&amp;</span> derived<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>D <span class="kw">const</span><span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb7-5"><a href="#cb7-5"></a></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb7-7"><a href="#cb7-7"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">requires</span> forward_range<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>derived<span class="op">())</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb7-9"><a href="#cb7-9"></a>    <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> forward_range<span class="op">&lt;</span>D <span class="kw">const</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>derived<span class="op">())</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb7-12"><a href="#cb7-12"></a>    <span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>With deducing this, we could write this as a single function template - deducing the self parameter such that it ends up being the derived type. But that’s again deducing way too much, when all we want to do is know if we’re a <code class="sourceCode cpp">D<span class="op">&amp;</span></code> or a <code class="sourceCode cpp">D <span class="kw">const</span><span class="op">&amp;</span></code>. But we can’t deduce just <code class="sourceCode cpp"><span class="kw">const</span></code>-ness.</p>
<h2 data-number="2.5" id="the-goal"><span class="header-section-number">2.5</span> The Goal<a href="#the-goal" class="self-link"></a></h2>
<p>To be more concrete, the goal here is to be able to specify a particular type or a particular class template such that template deduction will <em>just</em> deduce the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category, while also (where relevant) performing a derived-to-base conversion. That is, I want to be able to implement a single function template for <code class="sourceCode cpp">optional<span class="op">&lt;</span>T<span class="op">&gt;::</span>transform</code> such that if I invoke it with an rvalue of type <code class="sourceCode cpp">D</code> that inherits publicly and unambiguously from <code class="sourceCode cpp">optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>, the function template will be instantiated with a first parameter of <code class="sourceCode cpp">optional<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;&amp;&amp;</span></code> (not <code class="sourceCode cpp">D<span class="op">&amp;&amp;</span></code>).</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="not-a-proposal"><span class="header-section-number">3</span> Not a proposal<a href="#not-a-proposal" class="self-link"></a></h1>
<p>If you don’t find the above examples and the need for more concrete deduction motivating, then I’m sorry for wasting your time.</p>
<p>If you <em>do</em> find the above examples and the need for more concrete deduction motivating, then I’m sorry that I don’t actually have a solution for you. What I have instead are several example syntaxes that I’ve thought about over the years that are all varying degrees of mediocre. My hope with this paper is that other, more creative, people are equally interesting in coming up with a solution to this problem and can come up with a better syntax for it.</p>
<p>Here are those syntax options. I will, for each option, demonstrate how to implement the <code class="sourceCode cpp">tuple</code> converting constructor, <code class="sourceCode cpp">optional<span class="op">::</span>transform</code>, and <code class="sourceCode cpp">view_interface<span class="op">::</span>empty</code>. I will use the following tools:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="pp">#define FWD</span><span class="op">(</span>e<span class="op">)</span><span class="pp"> </span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>e<span class="op">)&amp;&amp;&gt;(</span>e<span class="op">)</span></span>
<span id="cb8-2"><a href="#cb8-2"></a></span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> RV, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="kw">using</span> apply_ref <span class="op">=</span> std<span class="op">::</span>conditional_t<span class="op">&lt;</span>RV, T<span class="op">&amp;&amp;</span>, T<span class="op">&amp;&gt;</span>;</span>
<span id="cb8-5"><a href="#cb8-5"></a></span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> C, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb8-7"><a href="#cb8-7"></a><span class="kw">using</span> apply_const <span class="op">=</span> std<span class="op">::</span>conditional_t<span class="op">&lt;</span>C, T <span class="kw">const</span>, T<span class="op">&gt;</span>;</span>
<span id="cb8-8"><a href="#cb8-8"></a></span>
<span id="cb8-9"><a href="#cb8-9"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> C, <span class="dt">bool</span> RV, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb8-10"><a href="#cb8-10"></a><span class="kw">using</span> apply_const_ref <span class="op">=</span> apply_ref<span class="op">&lt;</span>RV, apply_const<span class="op">&lt;</span>C, T<span class="op">&gt;&gt;</span>;</span>
<span id="cb8-11"><a href="#cb8-11"></a></span>
<span id="cb8-12"><a href="#cb8-12"></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="cb8-13"><a href="#cb8-13"></a><span class="kw">using</span> copy_cvref_t <span class="op">=</span> apply_const_ref<span class="op">&lt;</span></span>
<span id="cb8-14"><a href="#cb8-14"></a>  is_const_v<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>,</span>
<span id="cb8-15"><a href="#cb8-15"></a>  <span class="op">!</span>is_lvalue_reference_v<span class="op">&lt;</span>T<span class="op">&gt;</span>,</span>
<span id="cb8-16"><a href="#cb8-16"></a>  U<span class="op">&gt;</span>;</span></code></pre></div>
</blockquote>
<h2 data-number="3.1" id="t-auto"><span class="header-section-number">3.1</span> <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&amp;&amp;</span></code><a href="#t-auto" class="self-link"></a></h2>
<p>The principle here is that in the same say that <code class="sourceCode cpp">range <span class="kw">auto</span><span class="op">&amp;&amp;</span></code>is some kind of <code class="sourceCode cpp">range</code>, that <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span></code> is some kind of <code class="sourceCode cpp"><span class="dt">int</span></code>. It kind of makes sense, kind of doesn’t. Depends on how you think about it.</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>  tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb9-5"><a href="#cb9-5"></a>    <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb9-6"><a href="#cb9-6"></a>          <span class="op">&amp;&amp;</span> <span class="op">(</span>constructible_from<span class="op">&lt;</span></span>
<span id="cb9-7"><a href="#cb9-7"></a>                Ts,</span>
<span id="cb9-8"><a href="#cb9-8"></a>                copy_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>rhs<span class="op">)</span>, Us<span class="op">&gt;</span></span>
<span id="cb9-9"><a href="#cb9-9"></a>              <span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span>
<span id="cb9-10"><a href="#cb9-10"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-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="cb10-2"><a href="#cb10-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4"></a>    <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> optional <span class="kw">auto</span><span class="op">&amp;&amp;</span> self, F<span class="op">&amp;&amp;</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5"></a>        <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F,</span>
<span id="cb10-6"><a href="#cb10-6"></a>            <span class="kw">decltype</span><span class="op">(</span>FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">())&gt;</span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a></span>
<span id="cb10-8"><a href="#cb10-8"></a>        <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-9"><a href="#cb10-9"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb10-10"><a href="#cb10-10"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;()</span>;</span>
<span id="cb10-12"><a href="#cb10-12"></a>        <span class="op">}</span></span>
<span id="cb10-13"><a href="#cb10-13"></a>    <span class="op">}</span></span>
<span id="cb10-14"><a href="#cb10-14"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> D <span class="kw">auto</span><span class="op">&amp;</span> self<span class="op">)</span></span>
<span id="cb11-4"><a href="#cb11-4"></a>        <span class="kw">requires</span> forward_range<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>self<span class="op">)&gt;</span></span>
<span id="cb11-5"><a href="#cb11-5"></a>    <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb11-7"><a href="#cb11-7"></a>    <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>The advantage of this syntax is that it’s concise and lets you do what you need to do.</p>
<p>The disadvantage of this syntax is that the only way you can get the type is by writing <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code> - and the only way to can pass through the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and qualifiers is by grabbing them off of <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code>. That’s fine if the type itself is all that is necessary (as it the case for <code class="sourceCode cpp">view_interface</code>) but not so much when you actually need to apply them (as is the case for <code class="sourceCode cpp">tuple</code>). This also means that the only place you can put the <code class="sourceCode cpp"><span class="kw">requires</span></code> clause is after the parameters. Another disadvantage is that the derived-to-base conversion aspect of this makes it inconsistent with what <code class="sourceCode cpp">Concept <span class="kw">auto</span></code> actually means - which is not actually doing any conversion.</p>
<h2 data-number="3.2" id="t"><span class="header-section-number">3.2</span> <code class="sourceCode cpp">T<span class="op">&amp;&amp;&amp;</span></code><a href="#t" class="self-link"></a></h2>
<p>Rather than writing <code class="sourceCode cpp">tuple<span class="op">&lt;</span>U<span class="op">...&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> rhs</code> we can instead introduce a new kind of reference and spell it <code class="sourceCode cpp">tuple<span class="op">&lt;</span>U<span class="op">...&gt;&amp;&amp;&amp;</span> rhs</code>. This syntactically looks nearly the same as the <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&amp;&amp;</span></code> version, so I’m not going to copy it.</p>
<p>If we went this route, we would naturally have to also allow:</p>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-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="dt">void</span> f<span class="op">(</span>T<span class="op">&amp;&amp;)</span>;  <span class="co">// regular forwarding reference</span></span>
<span id="cb12-2"><a href="#cb12-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="dt">void</span> g<span class="op">(</span>T<span class="op">&amp;&amp;&amp;)</span>; <span class="co">// also regular forwarding reference</span></span></code></pre></div>
</blockquote>
<p>The advantage here is that it’s less arguably broken than the previous version, since it’s more reasonable that the <code class="sourceCode cpp">tuple<span class="op">&lt;</span>U<span class="op">...&gt;&amp;&amp;&amp;</span></code> syntax would allow derived-to-base conversion.</p>
<p>The disadvantages are all the other disadvantages of the previous version, plus also a whole new reference token? Swell.</p>
<h2 data-number="3.3" id="constbool"><span class="header-section-number">3.3</span> <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="dt">bool</span><span class="op">)</span></code><a href="#constbool" class="self-link"></a></h2>
<p>We have <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> and <code class="sourceCode cpp"><span class="kw">explicit</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code>. What about <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code>?</p>
<p>On some level, this seems to make perfect sense. At least for <code class="sourceCode cpp"><span class="kw">const</span></code> - since we want to deduce either <code class="sourceCode cpp">T</code> or <code class="sourceCode cpp">T <span class="kw">const</span></code>, and so <code class="sourceCode cpp"><span class="kw">const</span></code> is either absent or present. But what about value category? How do you represent <code class="sourceCode cpp">T<span class="op">&amp;</span></code> vs <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>? Surely, we wouldn’t do <code class="sourceCode cpp">T <span class="op">&amp;(</span>LV<span class="op">)</span> <span class="op">&amp;&amp;(</span>RV<span class="op">)</span></code> for deducing two different <code class="sourceCode cpp"><span class="dt">bool</span></code>s - these two cases are mutually exclusive. Keeping one of the <code class="sourceCode cpp"><span class="op">&amp;</span></code>s around, as in <code class="sourceCode cpp">T<span class="op">&amp;</span> <span class="op">&amp;(</span>RV<span class="op">)</span></code> (with a mandatory space) also seems pretty bad. So for the purposes of this section, let’s try <code class="sourceCode cpp">T <span class="op">&amp;&amp;</span> <span class="op">(</span>RV<span class="op">)</span></code> (where <code class="sourceCode cpp">RV</code> is <code class="sourceCode cpp"><span class="kw">true</span></code> for rvalues and <code class="sourceCode cpp"><span class="kw">false</span></code> for lvalues, but still a forwarding reference).</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us, <span class="dt">bool</span> C, <span class="dt">bool</span> RV<span class="op">&gt;</span></span>
<span id="cb13-4"><a href="#cb13-4"></a>    <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb13-5"><a href="#cb13-5"></a>          <span class="op">&amp;&amp;</span> <span class="op">(</span>constructible_from<span class="op">&lt;</span></span>
<span id="cb13-6"><a href="#cb13-6"></a>                Ts,</span>
<span id="cb13-7"><a href="#cb13-7"></a>                apply_const_ref<span class="op">&lt;</span>C, RV, Us<span class="op">&gt;</span></span>
<span id="cb13-8"><a href="#cb13-8"></a>              <span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb13-9"><a href="#cb13-9"></a>  tuple<span class="op">(</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">(</span>C<span class="op">)</span> <span class="op">&amp;&amp;(</span>RV<span class="op">)</span> rhs<span class="op">)</span>;</span>
<span id="cb13-10"><a href="#cb13-10"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-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="cb14-2"><a href="#cb14-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, <span class="dt">bool</span> C, <span class="dt">bool</span> RV<span class="op">&gt;</span></span>
<span id="cb14-4"><a href="#cb14-4"></a>    <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> optional <span class="kw">const</span><span class="op">(</span>C<span class="op">)</span> <span class="op">&amp;&amp;(</span>RV<span class="op">)</span> self, F<span class="op">&amp;&amp;</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-5"><a href="#cb14-5"></a>        <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F,</span>
<span id="cb14-6"><a href="#cb14-6"></a>            <span class="co">// apply_const_ref&lt;C, RV, T&gt;</span></span>
<span id="cb14-7"><a href="#cb14-7"></a>            <span class="kw">decltype</span><span class="op">(</span>FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">())&gt;</span>;</span>
<span id="cb14-8"><a href="#cb14-8"></a></span>
<span id="cb14-9"><a href="#cb14-9"></a>        <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-10"><a href="#cb14-10"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb14-11"><a href="#cb14-11"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;()</span>;</span>
<span id="cb14-13"><a href="#cb14-13"></a>        <span class="op">}</span></span>
<span id="cb14-14"><a href="#cb14-14"></a>    <span class="op">}</span></span>
<span id="cb14-15"><a href="#cb14-15"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> C<span class="op">&gt;</span></span>
<span id="cb15-4"><a href="#cb15-4"></a>        <span class="kw">requires</span> forward_range<span class="op">&lt;</span>apply_const<span class="op">&lt;</span>C, D<span class="op">&gt;&gt;</span></span>
<span id="cb15-5"><a href="#cb15-5"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> D <span class="dt">bool</span><span class="op">(</span>C<span class="op">)&amp;</span> self<span class="op">)</span></span>
<span id="cb15-6"><a href="#cb15-6"></a>    <span class="op">{</span></span>
<span id="cb15-7"><a href="#cb15-7"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb15-8"><a href="#cb15-8"></a>    <span class="op">}</span></span>
<span id="cb15-9"><a href="#cb15-9"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>This syntax is… pretty weird. Very weird.</p>
<p>The advantages are that it’s clearer that we’re only deducing <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and ref qualifiers. It also allows you to put <code class="sourceCode cpp"><span class="kw">requires</span></code> clauses after the <em>template-head</em> rather than much later. When only deducing <code class="sourceCode cpp"><span class="kw">const</span></code>, it’s arguably pretty clear what’s going on.</p>
<p>The disadvantages are the obvious weirdness of the syntax, <em>especially</em> for figuring out the value category, and the mandatory metaprogramming around applying those boolean values that we deduce through the types. <code class="sourceCode cpp">apply_const</code> and <code class="sourceCode cpp">apply_const_ref</code> (as I’m arbitrarily calling them here, the former appears as an exposition-only trait in Ranges under the name <code class="sourceCode cpp"><em>maybe-const</em></code>) will be <em>everywhere</em>, and those aren’t exactly obvious to understand either. It may be tempting to allow writing <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span> <span class="op">&amp;&amp;(</span><span class="kw">true</span><span class="op">)</span></code> as a type directly to facilitate writing such code (this would be <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&amp;&amp;</span></code>), but this seems facially terrible.</p>
<p>There’s further issues that <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> isn’t quite valid grammar today, but it’s pretty close. <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> looks like a cast, and it’s not unreasonable that we may at some point consider <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span>x<span class="op">)</span></code> as a language cast version of <code class="sourceCode cpp">std<span class="op">::</span>as_const<span class="op">(</span>x<span class="op">)</span></code>.</p>
<p>But there is one entirely unrelated benefit. Consider trying to write a function that accepts any function pointer:</p>
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2"></a><span class="dt">void</span> accepts_function_ptr<span class="op">(</span>R <span class="op">(*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span></code></pre></div>
</blockquote>
<p>That’s all you need (if we ignore varargs, assume the adoption of <span class="citation" data-cites="CWG2355">[<a href="#ref-CWG2355" role="doc-biblioref">CWG2355</a>]</span> - which was accepted but not fully processed yet). And note here the deduction of <code class="sourceCode cpp"><span class="kw">noexcept</span></code>-ness (and the usage of it on a function type) very closely resembles the kind of deduction of <code class="sourceCode cpp"><span class="kw">const</span></code> and value category discussed in this section.</p>
<p>But today if we wanted to deduce a pointer to <em>member</em> function, we have to write a whole lot more - precisely because we can’t deduce all the other stuff at the end of the type:</p>
<blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1"></a><span class="co">// this only accepts non-const pointers to member functions that have no ref-qualifier</span></span>
<span id="cb17-2"><a href="#cb17-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-3"><a href="#cb17-3"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-4"><a href="#cb17-4"></a></span>
<span id="cb17-5"><a href="#cb17-5"></a><span class="co">// so we also need this one</span></span>
<span id="cb17-6"><a href="#cb17-6"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-8"><a href="#cb17-8"></a></span>
<span id="cb17-9"><a href="#cb17-9"></a><span class="co">// ... and this one</span></span>
<span id="cb17-10"><a href="#cb17-10"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-11"><a href="#cb17-11"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="op">&amp;</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-12"><a href="#cb17-12"></a></span>
<span id="cb17-13"><a href="#cb17-13"></a><span class="co">// ... and also this one</span></span>
<span id="cb17-14"><a href="#cb17-14"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-15"><a href="#cb17-15"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-16"><a href="#cb17-16"></a></span>
<span id="cb17-17"><a href="#cb17-17"></a><span class="co">// ... and then also these two</span></span>
<span id="cb17-18"><a href="#cb17-18"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-19"><a href="#cb17-19"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span><span class="op">&amp;</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-20"><a href="#cb17-20"></a></span>
<span id="cb17-21"><a href="#cb17-21"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">&gt;</span></span>
<span id="cb17-22"><a href="#cb17-22"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span><span class="op">&amp;&amp;</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span></code></pre></div>
</blockquote>
<p>The direction where we can deduce <code class="sourceCode cpp"><span class="kw">const</span></code> in the same way that we can deduce <code class="sourceCode cpp"><span class="kw">noexcept</span></code> provides a much better solution for this. Although here, unlike the examples presented earlier, we’re not simply selecting between <code class="sourceCode cpp"><span class="op">&amp;</span></code> and <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code>. Here, we have three options. Does that mean a different design then? And what would it look like to handle both cases? It’s a bit unclear.</p>
<h2 data-number="3.4" id="qualifiers-q"><span class="header-section-number">3.4</span> <code class="sourceCode cpp">qualifiers Q</code><a href="#qualifiers-q" class="self-link"></a></h2>
<p>This approach is quite different and involves introducing a new kind of template parameter, which I’m calling <code class="sourceCode cpp">qualifiers</code>, which will deduce an <em>alias template</em>. It may be easier to look at the examples:</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us, qualifiers Q<span class="op">&gt;</span></span>
<span id="cb18-4"><a href="#cb18-4"></a>    <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb18-5"><a href="#cb18-5"></a>          <span class="op">&amp;&amp;</span> <span class="op">(</span>constructible_from<span class="op">&lt;</span>Ts, Q<span class="op">&lt;</span>Us<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb18-6"><a href="#cb18-6"></a>  tuple<span class="op">(</span>Q<span class="op">&lt;</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;&gt;</span> rhs<span class="op">)</span>;</span>
<span id="cb18-7"><a href="#cb18-7"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-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="cb19-2"><a href="#cb19-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F, qualifiers Q<span class="op">&gt;</span></span>
<span id="cb19-4"><a href="#cb19-4"></a>    <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> Q<span class="op">&lt;</span>optional<span class="op">&gt;</span> self, F<span class="op">&amp;&amp;</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-5"><a href="#cb19-5"></a>        <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F, Q<span class="op">&lt;</span>T<span class="op">&gt;&gt;&gt;</span>;</span>
<span id="cb19-6"><a href="#cb19-6"></a></span>
<span id="cb19-7"><a href="#cb19-7"></a>        <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-8"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb19-9"><a href="#cb19-9"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb19-10"><a href="#cb19-10"></a>          <span class="cf">return</span> optional<span class="op">&lt;</span>U<span class="op">&gt;()</span>;</span>
<span id="cb19-11"><a href="#cb19-11"></a>        <span class="op">}</span></span>
<span id="cb19-12"><a href="#cb19-12"></a>    <span class="op">}</span></span>
<span id="cb19-13"><a href="#cb19-13"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span>qualifiers Q<span class="op">&gt;</span></span>
<span id="cb20-4"><a href="#cb20-4"></a>        <span class="kw">requires</span> forward_range<span class="op">&lt;</span>Q<span class="op">&lt;</span>D<span class="op">&gt;&gt;</span></span>
<span id="cb20-5"><a href="#cb20-5"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> Q<span class="op">&lt;</span>D<span class="op">&gt;&amp;</span> self<span class="op">)</span></span>
<span id="cb20-6"><a href="#cb20-6"></a>    <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb20-8"><a href="#cb20-8"></a>    <span class="op">}</span></span>
<span id="cb20-9"><a href="#cb20-9"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>The idea here is that a parameter of the form <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;</span> x</code> will deduce <code class="sourceCode cpp">T</code> and <code class="sourceCode cpp">Q</code> separately, but <code class="sourceCode cpp">Q</code> will be deduced as one of the following four alias templates:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T<span class="op">&amp;</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span><span class="op">&amp;</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T<span class="op">&amp;&amp;</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span><span class="op">&amp;&amp;</span>;</code></li>
</ul>
<p>Whereas a parameter of the form <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> x</code> or <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;&amp;&amp;</span></code> will deduce <code class="sourceCode cpp">Q</code> either as:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span>;</code></li>
</ul>
<p>The significant advantage here is that applying the <code class="sourceCode cpp"><span class="kw">const</span></code> and reference qualifiers that we just deduced is trivial, since we already have exactly the tool we need to do that: <code class="sourceCode cpp">Q</code>. This makes all the implementations simpler. It also gives you a way to name the parameter other than <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code>, since there is a proper C++ spelling for the parameter itself in all cases.</p>
<p>The disadvantage is that this is <em>quite</em> novel for C++, and extremely weird. Even more dramatically weird than the other two solutions. And that’s even with using the nice name of <code class="sourceCode cpp">qualifiers</code>, which is probably untenable (although <code class="sourceCode cpp">cvrefquals</code> or <code class="sourceCode cpp">refqual</code> might be available?). Also <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;</span> x</code> does not look like a forwarding reference, but since <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> x</code> is the only meaningful way to deduce just <code class="sourceCode cpp"><span class="kw">const</span></code> - this suggests that <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;&amp;&amp;</span> x</code> <em>also</em> needs to deduce just <code class="sourceCode cpp"><span class="kw">const</span></code> (even though why would anyone write this), which leaves <code class="sourceCode cpp">Q<span class="op">&lt;</span>T<span class="op">&gt;</span> x</code> alone.</p>
<p>There’s also the question of how we could provide an explicit template argument for <code class="sourceCode cpp">Q</code>. Perhaps that’s spelled <code class="sourceCode cpp">qualifiers<span class="op">::</span>rvalue</code> (to add <code class="sourceCode cpp"><span class="op">&amp;&amp;</span></code>) or <code class="sourceCode cpp">qualifiers<span class="op">::</span>const_lvalue</code> (to add <code class="sourceCode cpp"><span class="kw">const</span><span class="op">&amp;</span></code>) and the like? There’d need to be some language magic way of spelling such a thing - since we probably wouldn’t want to just allow an arbitrary alias template. <code class="sourceCode cpp">std<span class="op">::</span>add_pointer_t</code>, for instance, would suddenly introduce a non-deduced context, and wouldn’t make any sense anyway.</p>
<h2 data-number="3.5" id="circles-approach"><span class="header-section-number">3.5</span> Circle’s approach<a href="#circles-approach" class="self-link"></a></h2>
<p>Sean Baxter implemented the following approach in Circle:</p>
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2"></a><span class="dt">void</span> f<span class="op">(</span>T<span class="op">&amp;&amp;</span> y <span class="op">:</span> std<span class="op">::</span>tuple<span class="op">&lt;</span>Args<span class="op">...&gt;)</span>;</span></code></pre></div>
</blockquote>
<p>In this syntax, we effectively are deducing some kind of <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op">&lt;</span>Args<span class="op">...&gt;</span></code>. <code class="sourceCode cpp">T</code> here is always a (possibly reference to) (possibly const) <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>. This behaves the same way as the previous section’s:</p>
<blockquote>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">template</span><span class="op">&lt;</span>qualifiers Q, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb22-2"><a href="#cb22-2"></a><span class="dt">void</span> f<span class="op">(</span>Q<span class="op">&lt;</span>std<span class="op">::</span>tuple<span class="op">&lt;</span>Args<span class="op">...&gt;&gt;</span> y<span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>with the only difference being what additional information you have available to you: whether that’s the type of <code class="sourceCode cpp">y</code> (<code class="sourceCode cpp">T</code>, or really <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>) or an alias providing the appropriate qualifiers (<code class="sourceCode cpp">Q</code>). As such, their uses are broadly similar:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Qualifiers</strong>
</div></th>
<th><div style="text-align:center">
<strong>Circle</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb23-2"><a href="#cb23-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb23-3"><a href="#cb23-3"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us, qualifiers Q<span class="op">&gt;</span></span>
<span id="cb23-4"><a href="#cb23-4"></a>    <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb23-5"><a href="#cb23-5"></a>          <span class="op">&amp;&amp;</span> <span class="op">(</span>constructible_from<span class="op">&lt;</span>Ts, Q<span class="op">&lt;</span>Us<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb23-6"><a href="#cb23-6"></a>  tuple<span class="op">(</span>Q<span class="op">&lt;</span>tuple<span class="op">&lt;</span>Us<span class="op">...&gt;&gt;</span> rhs<span class="op">)</span>;</span>
<span id="cb23-7"><a href="#cb23-7"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb24-2"><a href="#cb24-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span><span class="op">...</span> Us, <span class="kw">typename</span> Rhs<span class="op">&gt;</span></span>
<span id="cb24-4"><a href="#cb24-4"></a>    <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb24-5"><a href="#cb24-5"></a>          <span class="op">&amp;&amp;</span> <span class="op">(</span>constructible_from<span class="op">&lt;</span>Ts, copy_cvref_t<span class="op">&lt;</span>Rhs, Us<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb24-6"><a href="#cb24-6"></a>  tuple<span class="op">(</span>Rhs<span class="op">&amp;&amp;</span> rhs <span class="op">:</span> tuple<span class="op">&lt;</span>Us<span class="op">...&gt;)</span>;</span>
<span id="cb24-7"><a href="#cb24-7"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span>qualifiers Q<span class="op">&gt;</span></span>
<span id="cb25-4"><a href="#cb25-4"></a>        <span class="kw">requires</span> forward_range<span class="op">&lt;</span>Q<span class="op">&lt;</span>D<span class="op">&gt;&gt;</span></span>
<span id="cb25-5"><a href="#cb25-5"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> Q<span class="op">&lt;</span>D<span class="op">&gt;&amp;</span> self<span class="op">)</span></span>
<span id="cb25-6"><a href="#cb25-6"></a>    <span class="op">{</span></span>
<span id="cb25-7"><a href="#cb25-7"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb25-8"><a href="#cb25-8"></a>    <span class="op">}</span></span>
<span id="cb25-9"><a href="#cb25-9"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Self<span class="op">&gt;</span></span>
<span id="cb26-4"><a href="#cb26-4"></a>        <span class="kw">requires</span> forward_range<span class="op">&lt;</span>Self<span class="op">&gt;</span></span>
<span id="cb26-5"><a href="#cb26-5"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> Self<span class="op">&amp;</span> self <span class="op">:</span> D<span class="op">)</span></span>
<span id="cb26-6"><a href="#cb26-6"></a>    <span class="op">{</span></span>
<span id="cb26-7"><a href="#cb26-7"></a>        <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb26-8"><a href="#cb26-8"></a>    <span class="op">}</span></span>
<span id="cb26-9"><a href="#cb26-9"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>The Circle approach requires a bit more work to propagate the qualifiers as compared to the qualifiers approach (which exists to propagate qualifiers), but gives you an actual name for the actual type you end up with rather than having to re-spell it manually.</p>
<p>As Circle’s approach is conceptually similar to the qualifiers approach, it is weird for some of the same ways. The declaration <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span> t <span class="op">:</span> tuple<span class="op">&lt;</span>U<span class="op">...&gt;</span></code> may look like it’s deducing <code class="sourceCode cpp">t</code> as a regular forwarding reference, but it’s not - it additionally (potentially) undergoes a derived-to-base conversion at the call site. We now have two types attached to a given variable. For those coming from languages which put the type of a variable after a colon, it would look like the type of <code class="sourceCode cpp">t</code> is <code class="sourceCode cpp">tuple<span class="op">&lt;</span>U<span class="op">...&gt;</span></code> - and that’s kind of correct at least (the type of <code class="sourceCode cpp">remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>t<span class="op">)&gt;</span></code> is <code class="sourceCode cpp">tuple<span class="op">&lt;</span>U<span class="op">...&gt;</span></code>). It seems unlikely that we would ever move C++ into a direction with better declaration syntax, but if we did this would cut off that approach.</p>
<h2 data-number="3.6" id="something-else"><span class="header-section-number">3.6</span> Something else<a href="#something-else" class="self-link"></a></h2>
<p>If there’s a different approach someone has, I’d love to hear it. But this is what I’ve got so far.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">4</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-CWG2355">
<p>[CWG2355] John Spicer. 2017-09-06. Deducing noexcept-specifiers. <br />
<a href="https://wg21.link/cwg2355">https://wg21.link/cwg2355</a></p>
</div>
<div id="ref-P0798R8">
<p>[P0798R8] Sy Brand. 2021. Monadic operations for std::optional. <br />
<a href="https://wiki.edg.com/pub/Wg21virtual2021-10/StrawPolls/p0798r8.html">https://wiki.edg.com/pub/Wg21virtual2021-10/StrawPolls/p0798r8.html</a></p>
</div>
<div id="ref-P0847R7">
<p>[P0847R7] Barry Revzin, Gašper Ažman, Sy Brand, Ben Deane. 2021-07-14. Deducing this. <br />
<a href="https://wg21.link/p0847r7">https://wg21.link/p0847r7</a></p>
</div>
<div id="ref-P2481R0">
<p>[P2481R0] Barry Revzin. 2021-10-15. Forwarding reference to specific type/template. <br />
<a href="https://wg21.link/p2481r0">https://wg21.link/p2481r0</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
