<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; }
#hidedel:checked ~ * del, #hidedel: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>P0634R1</b>
<br/>2017-10-15</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>
If <tt>X<T>::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>Wording changes</h2>

<input type="checkbox" id="hidedel">Hide deleted text</input>

<p>Change in [temp.res] paragraph 3:</p>
<blockquote class="std">
  When a <i>qualified-id</i> is intended to refer to a type that is not
  a member of the current instantiation (17.7.2.1) and its
  <i>nested-name-specifier</i> refers to a dependent type, it shall be
  prefixed by the keyword <tt>typename</tt>, <del>forming a
  <i>typename-specifier</i>. If the <i>qualified-id</i> in a 
  <i>typename-specifier</i> does not denote a type or a class template,
  the program is ill-formed.</del><ins>unless:</ins>
  <ul>
    <li><ins>it is a qualified name in an <i>type-id-only context</i>
        (see below), or</ins>
    <li><ins>it is the <i>decl-specifier-seq</i> of a:</ins></li>
    <ul>
      <li><ins><i>simple-declaration</i> in namespace scope, </ins></li>
      <li><ins><i>member-declaration</i> in class scope,</ins></li>
      <li><ins><i>parameter-declaration</i> in a function-declarator for a
          function, pointer to function, reference to function, or
          pointer-to-member function at class sope
          [ <i>Note</i>: This includes friend function declarations.
            <i>&mdash;end note</i>],</ins></li>
      <li><ins><i>parameter-declaration</i> of a function parameter
          appearing in a <i>lambda-declarator</i>, or</ins></li>
      <li><ins><i>parameter-declaration</i> in a (non-type)
           <i>template-parameter</i>.</ins></li>
    </ul>
  </ul>

  <ins>A qualified name is said to be in an <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 class="stdins">[ <i>Example:</i>
  <blockquote><tt>
  template&lt;class T&gt; T::R f(T::P); // </tt>OK, global scope<tt><br/>
  template&lt;class T&gt; struct S {<br/>
  <tab>using Ptr = PtrTraits<T>::Ptr; //</tt> OK, in a defining-type-id<tt><br/>
  <tab>T::R f(T::P p) {               //</tt> OK<tt><br/>
  <tab><tab>return static_cast&lt;T::R&gt;    //</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> (not at class scope) does not denote a type<tt><br/>
  };<br/>
  </tt></blockquote>
<p><i>&mdash; end example</i> ]</p>
</blockquote>

  <ins>A qualified name prefixed with <tt>typename</tt> in this way forms a
  <i>typename-specifier<i>:</ins>
  <blockquote>
    <i>typename-specifier</i>:<br/>
    <tab3><tt>typename</tt> <i>nested-name-specifier identifier</i><br/>
    <tab3><tt>typename</tt> <i>nested-name-specifier</i>
             <tt>template</tt><sub>opt</sub> <i>simple-template-id</i><br/>
  </blockquote>
<ins>If the <i>qualified-id</i> in a <i>typename-specifier</i> does not
denote a type or a class template, the program is ill-formed.</ins>
</blockquote>

</body>
</html>

