<!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="2020-02-07" />
  <title>Allow Templates in Local Classes</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>
  <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">Allow Templates in Local Classes</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>D1988R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2020-02-07</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>
      Steve Downey<br>&lt;<a href="mailto:sdowney@gmail.com" class="email">sdowney@gmail.com</a>, <a href="mailto:sdowney2@bloomberg.net" class="email">sdowney2@bloomberg.net</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<h1 data-number="1" id="abstract" data-number="1"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>Local classes should be permitted to have member templates.</p>
<h1 data-number="2" id="before-after-table" data-number="2"><span class="header-section-number">2</span> Before / After Table<a href="#before-after-table" class="self-link"></a></h1>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="co">// Extracted From LLVM test case temp.mem/p2.cpp</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="dt">void</span> fun() {</span>
<span id="cb1-3"><a href="#cb1-3"></a>    <span class="kw">struct</span> foo {</span>
<span id="cb1-4"><a href="#cb1-4"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="kw">struct</span> bar {};     <span class="co">// Error</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="dt">void</span> baz() {}      <span class="co">// Error</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="kw">using</span> corge = <span class="dt">int</span>; <span class="co">// Error</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>    };</span>
<span id="cb1-8"><a href="#cb1-8"></a>}</span></code></pre></div></td>
<td><div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="co">// Extracted From LLVM test case temp.mem/p2.cpp</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="dt">void</span> fun() {</span>
<span id="cb2-3"><a href="#cb2-3"></a>    <span class="kw">struct</span> foo {</span>
<span id="cb2-4"><a href="#cb2-4"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="kw">struct</span> bar {};     <span class="co">// Allowed</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="dt">void</span> baz() {}      <span class="co">// Allowed</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>        <span class="kw">template</span> &lt;<span class="kw">typename</span>&gt; <span class="kw">using</span> corge = <span class="dt">int</span>; <span class="co">// Allowed</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>    };</span>
<span id="cb2-8"><a href="#cb2-8"></a>}</span>
<span id="cb2-9"><a href="#cb2-9"></a></span></code></pre></div></td>
</tr>
</tbody>
</table>
<h1 data-number="3" id="implementation-experience-for-c98" data-number="3"><span class="header-section-number">3</span> Implementation Experience For C++98<a href="#implementation-experience-for-c98" class="self-link"></a></h1>
<p>Implemented in clang by deleting the check for template inside local class.</p>
<div>
<div class="sourceCode" id="cb1"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>index 5633582d679..d155bf8b5e4 100644</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="dt">--- a/clang/lib/Sema/SemaTemplate.cpp</span></span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="dt">+++ b/clang/lib/Sema/SemaTemplate.cpp</span></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="dt">-7385,12 +7385,7 Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>     if (CXXRecordDecl *RD = dyn_cast&lt;CXXRecordDecl&gt;(Ctx)) {</span>
<span id="cb1-7"><a href="#cb1-7"></a>       // C++ [temp.mem]p2:</span>
<span id="cb1-8"><a href="#cb1-8"></a>       //   A local class shall not have member templates.</span>
<span id="cb1-9"><a href="#cb1-9"></a><span class="st">-      if (RD-&gt;isLocalClass())</span></span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="st">-        return Diag(TemplateParams-&gt;getTemplateLoc(),</span></span>
<span id="cb1-11"><a href="#cb1-11"></a><span class="st">-                    diag::err_template_inside_local_class)</span></span>
<span id="cb1-12"><a href="#cb1-12"></a><span class="st">-          &lt;&lt; TemplateParams-&gt;getSourceRange();</span></span>
<span id="cb1-13"><a href="#cb1-13"></a><span class="st">-      else</span></span>
<span id="cb1-14"><a href="#cb1-14"></a><span class="st">-        return false;</span></span>
<span id="cb1-15"><a href="#cb1-15"></a><span class="va">+      return false;</span></span>
<span id="cb1-16"><a href="#cb1-16"></a>     }</span>
<span id="cb1-17"><a href="#cb1-17"></a>   }</span></code></pre></div>
</div>
<p>Built a stage2 bootstrap of llvm, including libc++, which succeeded.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1"></a><span class="va">CXX=</span>clang++-8 <span class="va">CC=</span>clang-8 <span class="fu">cmake</span> -DCLANG_ENABLE_BOOTSTRAP=On \</span>
<span id="cb3-2"><a href="#cb3-2"></a>-DCLANG_BOOTSTRAP_PASSTHROUGH=\</span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="st">&quot;CMAKE_INSTALL_PREFIX;CMAKE_BUILD_TYPE;LLVM_USE_LINKER;LLVM_PARALLEL_LINK_JOBS;LLVM_ENABLE_PROJECTS&quot;</span> \</span>
<span id="cb3-4"><a href="#cb3-4"></a>-DCMAKE_INSTALL_PREFIX=~/install/llvm-localclass/ -DLLVM_ENABLE_LIBCXX=yes \</span>
<span id="cb3-5"><a href="#cb3-5"></a>-DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=yes -DLLVM_USE_LINKER=lld \</span>
<span id="cb3-6"><a href="#cb3-6"></a>-DLLVM_PARALLEL_LINK_JOBS=1 \</span>
<span id="cb3-7"><a href="#cb3-7"></a>-DLLVM_ENABLE_PROJECTS=\</span>
<span id="cb3-8"><a href="#cb3-8"></a><span class="st">&quot;clang;clang-tools-extra;compiler-rt;debuginfo-tests;libcxx;libcxxabi;libunwind;lld;lldb;llvm&quot;</span> \</span>
<span id="cb3-9"><a href="#cb3-9"></a>-G Ninja ../llvm-project/llvm/</span></code></pre></div>
<p>The test suite produced one new set of errors, the tests checking that templates not be declared inside of a local class.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1"></a>error: &#39;error&#39; diagnostics expected but not seen:</span>
<span id="cb2-2"><a href="#cb2-2"></a>  File &lt;snip&gt;/temp/temp.decls/temp.mem/p2.cpp Line 8: templates cannot be declared inside of a local class</span>
<span id="cb2-3"><a href="#cb2-3"></a>  File &lt;snip&gt;/temp/temp.decls/temp.mem/p2.cpp Line 9: templates cannot be declared inside of a local class</span>
<span id="cb2-4"><a href="#cb2-4"></a>  File &lt;snip&gt;/temp/temp.decls/temp.mem/p2.cpp Line 10: templates cannot be declared inside of a local class</span>
<span id="cb2-5"><a href="#cb2-5"></a>  File &lt;snip&gt;/temp/temp.decls/temp.mem/p2.cpp Line 11: templates cannot be declared inside of a local class</span>
<span id="cb2-6"><a href="#cb2-6"></a>  File &lt;snip&gt;/temp/temp.decls/temp.mem/p2.cpp Line 12: templates cannot be declared inside of a local class</span>
<span id="cb2-7"><a href="#cb2-7"></a>5 errors generated.</span></code></pre></div>
<h1 data-number="4" id="why-c-98" data-number="4"><span class="header-section-number">4</span> Why C++ 98<a href="#why-c-98" class="self-link"></a></h1>
<p>In C++98 there is no way for a local class to escape the scope in which it is declared. (Un)Fortunately in C++11 we allowed the <code class="sourceCode default">auto</code> keyword and the deduction of the return type of a function.</p>
<p>What this means for templates in local classes is that the instantiation point may be outside the scope that the class is declared in. This leads to complications.</p>
<p>If the local class is returned from such a function, and the member template is used, the context defining the member, in existing implementations is lost.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">template</span>&lt;<span class="kw">typename</span> T&gt; <span class="kw">auto</span> f(T t) {</span>
<span id="cb4-2"><a href="#cb4-2"></a>    <span class="kw">struct</span> X {</span>
<span id="cb4-3"><a href="#cb4-3"></a>      <span class="kw">template</span>&lt;<span class="kw">typename</span> U&gt; <span class="dt">void</span> g() {</span>
<span id="cb4-4"><a href="#cb4-4"></a>        <span class="kw">decltype</span>(t) x = <span class="dv">123</span>; }</span>
<span id="cb4-5"><a href="#cb4-5"></a>      };</span>
<span id="cb4-6"><a href="#cb4-6"></a>    <span class="cf">return</span> X();</span>
<span id="cb4-7"><a href="#cb4-7"></a>}</span>
<span id="cb4-8"><a href="#cb4-8"></a></span>
<span id="cb4-9"><a href="#cb4-9"></a><span class="dt">void</span> h() {</span>
<span id="cb4-10"><a href="#cb4-10"></a>  f(<span class="kw">nullptr</span>).g&lt;<span class="dt">int</span>&gt;();</span>
<span id="cb4-11"><a href="#cb4-11"></a>}</span></code></pre></div>
<p>With the patch above, clang will ICE. The corresponding lambda expression is diagnosed as an error.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">template</span> &lt;<span class="kw">typename</span> T&gt;</span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">auto</span> f(T t) {</span>
<span id="cb5-3"><a href="#cb5-3"></a>    <span class="kw">auto</span> y = []&lt;<span class="kw">typename</span> U&gt;(U u) { <span class="kw">decltype</span>(t) x = <span class="dv">123</span>;};</span>
<span id="cb5-4"><a href="#cb5-4"></a>    <span class="cf">return</span> y;</span>
<span id="cb5-5"><a href="#cb5-5"></a>}</span>
<span id="cb5-6"><a href="#cb5-6"></a></span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="dt">void</span> h1() { <span class="kw">auto</span> k = f(<span class="kw">nullptr</span>);};</span></code></pre></div>
<p>clang reports:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb3-1"><a href="#cb3-1"></a>&lt;source&gt;:3:48: error: cannot initialize a variable of type &#39;decltype(t)&#39; (aka &#39;nullptr_t&#39;) with an rvalue of type &#39;int&#39;</span>
<span id="cb3-2"><a href="#cb3-2"></a>    auto y = []&lt;typename U&gt;(U u) { decltype(t) x = 123;};</span>
<span id="cb3-3"><a href="#cb3-3"></a>                                               ^   ~~~</span>
<span id="cb3-4"><a href="#cb3-4"></a>&lt;source&gt;:7:22: note: in instantiation of function template specialization &#39;f&lt;nullptr_t&gt;&#39; requested here</span>
<span id="cb3-5"><a href="#cb3-5"></a>void h1() { auto k = f(nullptr);};</span>
<span id="cb3-6"><a href="#cb3-6"></a>                     ^</span>
<span id="cb3-7"><a href="#cb3-7"></a>1 error generated.</span>
<span id="cb3-8"><a href="#cb3-8"></a>Compiler returned: 1</span></code></pre></div>
<p><a href="https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAM1QDsCBlZAQwBtMQBGAFlICsupVs1qhkAUgBMAISnTSAZ0ztkBPHUqZa6AMKpWAVwC2tEAGYAbKS3oAMnlqYAcsYBGmYiADspAA6oFQnVaPUMTQX9AtTp7Rxcjd09ORWVMVWCGAmZiAlDjU0sUlWjaTOyCWOc3D29FLJy88OSFeoqHKoSazgBKRVQDYmQOAHICTCNfYTGAanEzHQIAT18tZiNMaYAVOexxAAYAQWYDImmqCE3pgm7Zr1lD6cfp49PF2bMAEVmAVllvj7mC2Wq3W0wAqjsIGDpgYbuI7tMsMhWEsVhBrtMAB7vL6cSRmOayLwAsz3A5PabETAEAa0aaLQn7A7wgGHJkAN1QeHQ0wQnAgcIRL1Q0wA1jizhBaAZWKxfARiN1GcTCbNDgB6dWc7m8yQC27SZ4nEXiuZfc7S2XyxWq0UQHrKkmG4a9VggYbfYakUzDPZe1DunRyOTTBT9QYbKRmThegjuv3dXqikDcTgAOgsmaz2azPjdw24Xp9ftIAeGXoUID2pDjvpdpDgsBgiBQdBoxCMIiG5EoaAmeHYxErsD7vgHHgAkugUMJRAB9BUGWii0vy4KV4YAWk3LXQZokMjkkmY9Ygo/HxCnIGAClozF8CgQqAIq5KG%2B3u/3wZkx5dvUw%2BBEMQ3KCLOwBXgesgyEIeCuMOAquu6nrevG/qBm2JCdrQQzTOyeCYAA7h40wQLghAkLM%2BI9NMkjqpwJa1gmvQIJgzBYJ4AqkMmZgABxpjxAmCUJAkAJxCO6hakEYIDfNWxZoeWihVjWqG9I2UDNhASDnoOPZnqg/aDjOIjAAuxBLiuVADmMQ6UK4qGkK4DjZIs7oxqQfbrPQADytCsK5dakFgWHAOwDn4FS6TspgG4lpgmJpCcIzuQ4Yz5iWrCwcQLl6FgbmxsB0nDDGvQ0PQTBsBwPD8KBJkoN%2B8iZXB8C9Kga50O%2BO4EHunyQUeJ59AMQxcIhHpFg5ZaYjxFibhY3DTMiJkkYuy43KRgEUVGyTTHohnEVtNxBoeMixqpzGsexlCjZJ0myShgVlhWymMaemnaQZY66RQ%2Bl7Z4N53g%2BT4vlZKIeJWED2YFTl3sQAXuZ5WgEL5/nheMJlhYFEVpGo0WxV68WJWM%2BXkPQygOU12Ww7lyUFXgRUlaQZWMCwYXVQIkhCHVfXQU18Gte1tCdZ%2BvUNb%2Bg0RiN4ljfdJaTdNs3zcAyDIMt5mrSRZFAZR0akDtH0XtrkiHQ1p11ompAsWxNScdxZhpmYDuO07ju8PmN0yXJE3uk91YvebyaSHx3wO9wIkWF4ZiSHskgWJw3xS2Y40Pd7Klmw2mlvSA/QEL4Jx6TpXTWBtSSM3QzOVVwvAEdlvj5aNyHyaW7pbdMBGEAgWLy3NC1garFndKbTEWxd1tJiAkiSGmE/TzPM9mFL7t3Y3j1Kb7qnp/AWlZycucvt9BeeBzAHkSXTMVazVc13XUsN17wxRpIrft53M3d0rKvomrooD6nQ%2BW5dnE3Zelup7ZOilKxrzNmPSOaZvheC8LHbgZgvAiT2DxUOPEE5J1linP2Y9vh8WdkQx2Vh8ySGAVwPYoCcGKTwVLchMsFKDz/KQaKQ5ggpiAA%3D%3D%3D">Compiler Explorer</a></p>
<p>Interestingly, there is some divergence in detecting the error. GCC doesn’t unless k is invoked:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="dt">void</span> h2() { <span class="kw">auto</span> k = f(<span class="kw">nullptr</span>); k(<span class="dv">1</span>);};</span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1"></a>&lt;source&gt;: In instantiation of &#39;f(T) [with T = std::nullptr_t]::&lt;lambda(U)&gt; [with U = int]&#39;:</span>
<span id="cb4-2"><a href="#cb4-2"></a>&lt;source&gt;:8:37:   required from here</span>
<span id="cb4-3"><a href="#cb4-3"></a>&lt;source&gt;:3:52: error: cannot convert &#39;int&#39; to &#39;std::nullptr_t&#39; in initialization</span>
<span id="cb4-4"><a href="#cb4-4"></a>      |     auto y = []&lt;typename U&gt;(U u) { decltype(t) x = 123;};</span>
<span id="cb4-5"><a href="#cb4-5"></a>      |                                                    ^~~</span>
<span id="cb4-6"><a href="#cb4-6"></a>      |                                                    |</span>
<span id="cb4-7"><a href="#cb4-7"></a>      |                                                    int</span>
<span id="cb4-8"><a href="#cb4-8"></a>Compiler returned: 1</span></code></pre></div>
<p><a href="https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAM1QDsCBlZAQwBtMQBGAFlICsupVs1qhkAUgBMAISnTSAZ0ztkBPHUqZa6AMKpWAVwC2tQVvQAZPLUwA5YwCNMxEAA5SAB1QLC62nsMTQS8fNTorG3sjJxd3JRUw2gYCZmICAONTTkVlTFU/ZNSCCLtHZzdFFLSMoOyFKuLrUujy1wBKRVQDYmQOAHICTCMPYUGAanEAZh0CAE8PLWYjTDGAFSnscQAGAEFmAyIxqghVsYI2iYB2WV2xu7H9w9mJyYARCYBWWQ/XqZn5xbLMYAVQ2EGBYwMF3E1zGWGQrDmCwg5zGAA8Xu9OJJJlNZJdfpMbjt7mNiJgCN1aGNZnjtjsYb9dvSAG6oPDoMYITgQaGwx6oMYAa0xRwgtAMrFYHgIxDadIJeImuzZHK5kl5V2kDwOgpFU3exwlUplcqVQognHlRMZSr6HVYID6Hz6pFMfS2rtQTp0cjkYwUXR6Kykk04roITs9bQ6QpA3E4ADoAGyptPptOXIRO7iu92e0jevquhQgLakSMe%2B2kOCwGCIFB0GjEIwiXrkShoYZ4djEUuwLseHvOACS6BQwlEAH1ZQZaELCzK/KW%2BgBaVf1dAGiQyOSSZjViCD4fEMcgYAKWjMDwKBCoAiLxIr9eb7d%2BmT7%2B0dTD4IjEDmCJOwBnjusgyEIeAOP2vIOk6LpulGXo%2Bk2JCtrQvRjCyeCYAA7s4YwQLghAkBMOJWmMkgAPScAWlbRh0CCYMwWAuLypBxpMriJq4PG8XxPEAJzZn0uakEYIAfOW%2BZIcWihlhWiEdLWUD1hASDHr2HZHqg3a9hOIjADOxBzguVA9oMfaUA4iGkA41ipLMTrhqQXbLPQADytCsI5VakFgaHAOwNn4OS%2BQspgK4FpgaJ5Ac/TOdYgyOr5rCQcQDl6FgTkRv%2B4l9OGHQ0PQTBsBwPD8IBBkoO%2B8ipVB8AdKgS50M%2BG4EFubygXuB45AkfiaNoNRZKQ5glFEMTBN4vh0ENk2hH4Y1lC4dS5PkdCFNU%2BiZII8R5IkG2NJES07Q0s11A0i0tMtHSBt0vRcLBzp5jZRZoq4yarsm3BjAiBkEbO84XIRv4kaG2RjHoun4WDFy%2BruMgRopDFMSxlCPaJ4mSQhvlFiW8l0YeqnqTpQ6aRQ2lQy4F5Xjed4PmZiLOKWEDWb5dlXsQPnOa5WgEJ53nBUMBlBb5IV7Xg4WRa60WxYM2XkPQyg2XV6Wc5l8U5XgeUFaQRWMCwQXlQIkhCFVXXgXV0GNc1tCta%2BnU1Z%2BvXixoEDmGdI3aJdE3ZCE03%2BFttSeFNiTe%2BUK19etp2B8Nu1rUkF1NON4eVEUHv1EUYfXZ0d1lY98HSYWTpvR9X1jMAyDIP9xmAwRRF/qRYakBDJMno3kiwzViNVjGpCMcx5RsRxkyJpMY/jxP4%2B8MlGMSVJL1Onj5YE73caSFxHxj9wAnJpckySFskjJpwHzCZMz044vCk9zWqlEyAXQEB4BxaRpKc/sRy263Q%2BulVwvA4XSh4bK%2BcL4FiLGDMYOFCAIHRO9T631fqiGriZNo3d6J9xRoPWMIBJCSETHgwhRCiGTGErPLGhdcZyWXopW%2B8A1IPwOM/B85M34uBNh/P8gg9YlUNgAoBIDhIFwXn0UMkgoEwLgaXb6Fcq4ohrkKNB18MH91RmxGerpMbz0vrJUsNCe44P3omD4lxLjH24JMS4AktiuG3u4ZK59sbgKvivHBHwuKT08ePZMwlJCaK4FsbRzjZKuN8WAmS6CvykHCn2fq3AgA%3D%3D">Compiler Explorer</a></p>
<p>I believe that clang is being too aggressive in instatiation of the <code class="sourceCode default">operator()</code> of the lambda, but I have not constructed an example that errors on otherwise well-formed code.</p>
<h1 data-number="5" id="modules-and-reachability" data-number="5"><span class="header-section-number">5</span> Modules and Reachability<a href="#modules-and-reachability" class="self-link"></a></h1>
<p>The problem of unnamable types whose members might be templates is similar to that of types in modules that are not exported but are present in interfaces that are.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">export</span> module M;</span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="kw">struct</span> X {};</span>
<span id="cb7-3"><a href="#cb7-3"></a></span>
<span id="cb7-4"><a href="#cb7-4"></a><span class="kw">export</span> {</span>
<span id="cb7-5"><a href="#cb7-5"></a>    X func(){<span class="cf">return</span> X{};}</span>
<span id="cb7-6"><a href="#cb7-6"></a>}</span></code></pre></div>
<p>The name X is unavailable outside the module, but the function <code class="sourceCode default">func</code> is. <code class="sourceCode default">auto x = funct();</code> is valid code.</p>
<p>This suggests we could leverage Reachability in order to provide meaning to local classes outside their declarative region. From <a href="http://eel.is/c++draft/module.reach">module.reach</a></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> A declaration D is reachable if, for any point P in the instantiation context ([module.context]),</p>
<p><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span> D appears prior to P in the same translation unit, or</p>
<p><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span> D is not discarded ([module.global.frag]), appears in a translation unit that is reachable from P, and either does not appear within a private-module-fragment or appears in a private-module-fragment of the module containing P.</p>
<p>[ Note: Whether a declaration is exported has no bearing on whether it is reachable. — end note ]</p>
</blockquote>
<p>The language already requires that the declaration of D, the local class, appear before any use of it, because of the existing rules for <code class="sourceCode default">auto</code>.</p>
<p><a href="http://eel.is/c++draft/module#global.frag">module.global.frag</a> provides</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> A declaration D in a global module fragment of a module unit is discarded if D is not decl-reachable from any top-level-declaration in the top-level-declaration-seq of the translation unit. [ Note: A discarded declaration is neither reachable nor visible to name lookup outside the module unit, nor in template instantiations whose points of instantiation ([temp.point]) are outside the module unit, even when the instantiation context ([module.context]) includes the module unit. — end note ]</p>
</blockquote>
<p>If we extend decl-reachable to include local classes that are made available via the return type of its declaring function, the defintion of the local class would be <em>reachable</em> for purposes of instantiating its member functions.</p>
<p>I do not know if this is viable in any sense as an implementation, but it seems to be a viable direction in terms of the standard.</p>
<h1 data-number="6" id="wording" data-number="6"><span class="header-section-number">6</span> Wording<a href="#wording" class="self-link"></a></h1>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">(temp.mem.2)</a></span> <span class="rm" style="color: #bf0303"><del>A local class of non-closure type shall not have member templates.</del></span> Access control rules apply to member template names. A destructor shall not be a member template. A non-template member function ([dcl.fct]) with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.</p>
</blockquote>
<p>I have not figured out how to word decl-reachable yet.</p>
</div>
</div>
</body>
</html>
