<html>
<head>
<title>Down with typename!</title>
<style type="text/css">
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: #FFA0A0;
                    border: 1px solid #ECD7EC;
                    padding-left: 0.5em; padding-right: 0.5em; }

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

blockquote.stdrepl { color: #000000; background-color: #FFFFA0;
                    border: 1px solid #EBEBB3; padding: 0.5em; }


ins { background-color:#A0FFA0; text-decoration: none }
del { background-color:#FFA0A0; text-decoration: line-through; }
strong { font-weight: inherit; color: #2020ff }
#xdel:checked ~ * del { display:none; visibility:hidden }

tab { padding-left: 2em; }
tab3 { padding-left: 6em; }
tabh { padding-left: 1em; }
tabq { padding-left: 0.5em; }
</style>
</head>
<body>

<p align=right>
<b>P0634R3</b>
<br/>2018-03-14</p>

<p align=right>
Nina Ranns (dinka.ranns@gmail.com)<br/>
Daveed Vandevoorde (daveed@edg.com)
</p>
<p align=right>
Core Working Group (CWG)
</p>

<h1 align=center>Down with <tt>typename</tt>!</h1>

<h2>Summary</h2>

<p><i>Note:</i> This proposal also resolves Core issue 1271.</p>

<p>
If <tt>X&lt;T&gt;::Y</tt> &mdash; where <tt>T</tt> is a template parameter &mdash;
is to denote a type, it must be preceded by the keyword <tt>typename</tt>; 
otherwise, it is assumed to denote a name producing an expression.
There are currently two notable exceptions to this rule:
<i>base-specifier</i>s and <i>mem-initializer-id</i>s.  For example:

<blockquote><tt>
  template&lt;class T&gt;<br/>
  struct D: T::B {  // </tt>No <tt>typename</tt> required here.</tt><br/>
  };
</tt></blockquote>
	
Clearly, no <tt>typename</tt> is needed for this <i>base-specifier</i>
because nothing but a type is possible in that context.  However, there
are several other places where we know only a type is possible and asking
programmers to nonetheless specify the <i>typename</i> keyword feels like
a waste of source code space (and is detrimental to readability).
</p><p>
We therefore propose we make <tt>typename</tt> optional in a number of
commonplace contexts that are known to only permit type names.
</p><p>
A cursory read through some common standard library headers suggests
that by-far most occurrences of <tt>typename</tt> for the purpose of
disambiguating type names from other names can be eliminated with
the new rules.
</p><p>
The EDG front end has an `implicit typename` mode to emulate pre-C++98
compilers that didn't parse templates in their generic form.  Although
that mode doesn't exactly cover the contexts where we are proposing to
make <tt>typename</tt> optional, the implementation effort is similar
(and not excessively expensive).
</p><p>
This proposal was approved in Toronto (July 2017) by EWG:
<blockquote>
SF: 14 | F: 8 | N: 1 | A: 0 | SA: 0
</blockquote>
</p>

<h2>Changes since P0634R2</h2>
<p>Applied changes requested by the Core work group.</p>


<h2>Changes since P0634R1</h2>
<ul>
	<li> HTML angle brackets typo fix </li>
	<li> Merged with changes for CWG issue 1271: Imprecise wording regarding dependent types </li>
	<li> addressed review comments </li>
</ul>


<h2>Wording changes</h2>
<input type="checkbox" id="xdel"/><label for="xdel">Hide deleted text</label>


</p><strong>Change in 17.7 [temp.res] paragraphs 3 and 4:</strong></p>

<blockquote class="std">
<del>A <em>qualified-id</em> is intended to refer to a type that is
not a member of the current instantiation (17.6.2.1) and
its <em>nested-name-specifier</em> refers to a dependent type, it
shall be prefixed by the keyword <code>typename</code>, forming
a <em>typename-specifier</em>. If the <em>qualified-id</em> in
a <em>typename-specifier</em> does not denote a type or a class
template, the program is ill-formed.</del>
<pre>
       <em>typename-specifier:</em>
             typename <em>nested-name-specifier identifier</em>
             typename <em>nested-name-specifier</em> template<sub>opt</sub> <em>simple-template-id</em>
</pre>
<ins>A <em>typename-specifier</em> denotes the <strong>type or class
template denoted by the <em>simple-type-specifier</em> (10.1.7.2
[dcl.type.simple])</strong> formed by omitting the
keyword <code>typename</code>.</ins>
<p>
<del>If a specialization of a template is instantiated for a set of
<em>template-argument</em>s such that the <em>qualified-id</em>
prefixed by typename does not denote a type or a class
template, the specialization is ill-formed.</del> The usual
qualified name lookup (6.4.3) is used to find the qualified-id even in
the presence of <tt>typename</tt>. [ Example: ... ]

</blockquote> 

<strong>Add a new paragraph in [temp.res] before paragraph 6:</strong>
<blockquote class="std">
  <ins>A <i>qualified-id</i> is assumed to name a type if </ins>
  <ul>
    <li><ins>it is a qualified name in a <i>type-id-only context</i>
        (see below), or</ins>
    <li><ins>it is a <i>decl-specifier</i> of the <i>decl-specifier-seq</i> of a</ins></li>
    <ul>
      <li><ins><i>simple-declaration</i> or a <i>function-definition</i> in namespace scope, </ins></li>
      <li><ins><i>member-declaration</i>,</ins></li>
      <li><ins><i>parameter-declaration</i> in a <i>member-declaration</i>, unless that <i>parameter-declaration</i> appears in a default argument [ <i>Note</i>: This includes friend function declarations.
            <i>&mdash;end note</i>],</ins></li>
      <li><ins><i>parameter-declaration</i> in a <i>declarator</i> of a function or function template declaration where the <i>declarator-id</i> is qualified, unless that <i>parameter-declaration</i> appears in a default argument,</ins></li>
      <li><ins><i>parameter-declaration</i> 
          in a <i>lambda-declarator</i>, unless that <i>parameter-declaration</i> appears in a default argument, or</ins></li>
      <li><ins><i>parameter-declaration</i> of a (non-type)
           <i>template-parameter</i>.</ins></li>
    </ul>
  </ul>

  <ins>A qualified name is said to be in a <i>type-id-only context</i>
  if it appears in a <i>type-id</i>, <i>new-type-id</i>, or
  <i>defining-type-id</i> and the smallest enclosing <i>type-id</i>,
  <i>new-type-id</i>, or <i>defining-type-id</i> is a</ins>
  <ul>
    <li><ins><i>new-type-id</i>,</ins></li>
    <li><ins><i>defining-type-id</i>,</ins></li>
    <li><ins><i>trailing-return-type</i>, </ins></li>
    <li><ins>default argument of a <i>type-parameter</i> of a template,
          or </ins></li>
    <li><ins><i>type-id</i> of a <tt>static_cast</tt>, <tt>const_cast</tt>,
        <tt>reinterpret_cast</tt>, or <tt>dynamic_cast</tt>.</ins></li>
  </ul>
</blockquote>

<blockquote class="stdins">[ <i>Example:</i>
  <blockquote><tt>
  template&lt;class T&gt; T::R f(); // </tt>OK, return type of a function declaration at global scope<tt><br/>
  template&lt;class T&gt; void f(T::R); // </tt>Ill-formed (no diagnostic required), attempt to declare a void variable template<tt><br/>
  template&lt;class T&gt; struct S {<br/>
  <tab>using Ptr = PtrTraits&lt;T&gt;::Ptr; //</tt> OK, in a defining-type-id<tt><br/>
  <tab>T::R f(T::P p) {               //</tt> OK, class scope<tt><br/>
  <tab><tab>return static_cast&lt;T::R&gt(p);    //</tt> OK, type-id of a static_cast<tt><br/>
  <tab>}<br/> 
  <tab>auto g() -&gt; S&lt;T*&gt;::Ptr;<tab>&emsp;  //</tt> OK, trailing-return-type<tt><br/>
  };<br/>
  template&lt;typename T&gt; void f() {<br/>
  <tab>void (*pf)(T::X);<tab3>
        //</tt> Variable <tt>pf</tt> of type <tt>void*</tt> initialized with <tt>T::X<br/>
  <tab>void g(T::X); <tab3><tab><tabq> // </tt> Error: <tt>T::X</tt> at block scope does not denote a type<tt><br/>
  <tab><tab><tab><tab><tab><tab><tab><tab> // </tt>(attempt to declare a <tt>void</tt> variable)<tt><br/>
  }<br/>
  </tt></blockquote>
<p><i>&mdash; end example</i> ]</p>
</blockquote>


<strong>Change in 17.7 [temp.res] paragraph 6</strong>:

<blockquote class="std">
<del>If, for a given set of template arguments, a specialization of a
template is instantiated that refers to a qualified-id that denotes a
type or a class template, and the qualified-id refers to a member of
an unknown specialization, the qualified-id shall either be prefixed
by typename or shall be used in a context in which it implicitly names
a type as described above.</del> <ins>A <em>qualified-id</em> that
refers to a member of an unknown specialization,<strong> that</strong> is not prefixed
by <code>typename</code>, and<strong> that</strong> is not otherwise assumed to name a type
(see above) denotes a non-type.</ins> [ Example:
<pre>
  template &lt;class T> void f(int i) {
     T::x * i;           // <del>T::x must not be a type</del><ins>expression, not the declaration of a variable i</ins>
   }
   struct Foo {
     typedef int x;
   };
   struct Bar {
     static int const x = 5;
   };
   int main() {
     f&lt;Bar>(1);          // OK
     f&lt;Foo>(1);          // error: Foo::x is a type
   }
</pre>
-- end example ]
</blockquote>

<strong>Change in 17.7 [temp.res] paragraphs 7 and 8</strong>:

<blockquote class="std">
Within the definition of a class template or within the definition of
a member of a class template following the <em>declarator-id</em>, the
keyword <code>typename</code> is not required when referring to <ins>a
member of the current instantiation (17.7.2.1 [temp.dep.type]).</ins>

<del>the name of a previously declared
member of the class template that declares a type or a class template. [ Note: Such names can be found
using unqualified name lookup (6.4.1), class member lookup (6.4.3.1) into the current instantiation (17.7.2.1),
or class member access expression lookup (6.4.5) when the type of the object expression is the current
  instantiation (17.7.2.2). -- end note ]</del> [ Example:
<pre>
   template&lt;class T> struct A {
      typedef int B;
      B b;               // OK, no typename required
   };
</pre>
-- end example ]
<p>
<ins>[ Note:</ins> Knowing which names are type names allows the
syntax of every template to be checked. <ins> -- end note ]</ins> The
program is ill-formed, no diagnostic required, if: ...


</blockquote>


</body>
</html>

