﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
              border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
                padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
                 border: 1px solid #D1D1D1;
                 padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
                    color: #000000; background-color: #FFEBFF;
                    border: 1px solid #ECD7EC;
                    padding-left: 0.5em; padding-right: 0.5em; }

blockquote.stdins { text-decoration: underline;
                    color: #000000; background-color: #C8FFC8;
                    border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
        margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
     padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
     padding-left: 0.8em; border: none; }

p.grammarlhs { font-style:italic; margin-bottom: 0; margin-top: 0 }
p.grammarrhs { font-style:italic; margin-left:8em; margin-top:0; margin-bottom: 0; text-indent:-4em }
p.grammarlhs tt { font-style:normal }
p.grammarrhs tt { font-style:normal }

</style>

<title>Allow typename in a template template parameter</title>
</head>

<body>

<div style="text-align: right; float: right">
<p>ISO/IEC JTC1 SC22 WG21<br>N4051<br>Richard Smith<br>2014-05-26</p>
</div>

<h1>Allow <tt>typename</tt> in a template template parameter</h1>

<h2>Rationale</h2>

<p>Since the introduction of alias templates, C++ has had type templates that
are not class templates, and in particular now has template template arguments
that are not class templates. However, the syntax for template template
parameters still requires the <tt>class</tt> keyword be used:</p>

<pre class="extract">
template&lt;typename T> struct A {};
template&lt;typename T> using B = int;

template&lt;template&lt;typename> class X> struct C;
C&lt;A> ca; // ok
C&lt;B> cb; // ok, not a class template
template&lt;template&lt;typename> typename X> struct D; // error, cannot use typename here
</pre>

<p>The relevant grammar rules are in 14.1 (temp.param) paragraph 1:

<blockquote class="std">
<p class="grammarlhs">type-parameter:</p>
<p class="grammarrhs">&hellip;
<p class="grammarrhs"><tt>class ...</tt><sub>opt</sub> identifier<sub>opt</sub>
<p class="grammarrhs"><tt>class</tt> identifier<sub>opt</sub> <tt>=</tt> id-expression
<p class="grammarrhs"><tt>typename ...</tt><sub>opt</sub> identifier<sub>opt</sub>
<p class="grammarrhs"><tt>typename</tt> identifier<sub>opt</sub> <tt>=</tt> id-expression
<p class="grammarrhs"><tt>template &lt;</tt> template-parameter-list <tt>&gt; <b>class</b> ...</tt><sub>opt</sub> identifier<sub>opt></sub>
<p class="grammarrhs"><tt>template &lt;</tt> template-parameter-list <tt>&gt; <b>class</b></tt> identifier<sub>opt</sub> <tt>=</tt> id-expression
</blockquote>

<p>Note that <tt>typename</tt> is permitted for non-template
<i>type-parameters</i>, but not for template <i>type-parameters</i>.
This difference is artificial and is a common surprise. Removing it
would make the language simpler.</p>

<h2>Proposed wording</h2>

<p>Change in 14.1 (temp.param) paragraph 1:

<blockquote class="std">
<p class="grammarlhs">type-parameter:</p>
<p class="grammarrhs">&hellip;
<p class="grammarrhs"><tt><del>class</del></tt> <ins>type-parameter-key</ins> <tt>...</tt><sub>opt</sub> identifier<sub>opt</sub>
<p class="grammarrhs"><tt><del>class</del></tt> <ins>type-parameter-key</ins> identifier<sub>opt</sub> <tt>=</tt> id-expression
<p class="grammarrhs"><del><tt>typename ...</tt><sub>opt</sub> identifier<sub>opt</sub></del>
<p class="grammarrhs"><del><tt>typename</tt> identifier<sub>opt</sub> <tt>=</tt> id-expression</del>
<p class="grammarrhs"><tt>template &lt;</tt> template-parameter-list <tt>&gt;</tt> <tt><del>class</del></tt> <ins>type-parameter-key</ins> <tt>...</tt><sub>opt</sub> identifier<sub>opt></sub>
<p class="grammarrhs"><tt>template &lt;</tt> template-parameter-list <tt>&gt;</tt> <tt><del>class</del></tt> <ins>type-parameter-key</ins> identifier<sub>opt</sub> <tt>=</tt> id-expression
<p class="grammarlhs"><ins>type-parameter-key:</p>
<p class="grammarrhs"><ins><tt>class</tt></ins>
<p class="grammarrhs"><ins><tt>typename</tt></ins>
</blockquote>

<p>Change in 14.1 (temp.param) paragraph 2:

<blockquote class="std">
There is no semantic difference between <tt>class</tt> and <tt>typename</tt> in
a
<del><i>template-parameter</i></del>
<ins><i>type-parameter-key</i></ins>.
<tt>typename</tt> followed by
an <i>unqualified-id</i> names a template type parameter.
<tt>typename</tt> followed by a <i>qualified-id</i> denotes the type
in a non-type [Footnote: &hellip;] <i>parameter-declaration</i>.
&hellip;
[Note: A template <del>parameter</del><ins>argument</ins> may be a class
template <ins>or alias template</ins>. For example, &hellip;]
</blockquote>

<p>Change in 14.1 (temp.param) paragraph 3:

<blockquote class="std">
A <i>type-parameter</i> whose <i>identifier</i> does not follow an ellipsis
defines its <i>identifier</i> to be a <i>typedef-name</i> (if declared
<del>with <tt>class</tt> or <tt>typename</tt></del><ins>without <tt>template</tt></ins>) or
<i>template-name</i> (if declared with <tt>template</tt>) in the scope of the
template declaration. [Note: &hellip;]
</blockquote>

</body>
</html>
