title: Can typename be omitted in the type-specifier of an out of line member definition?
body: <p>I ran into this strange behaviour when testing whether or not <code>typename</code> is required by clang. Both clang and gcc accept this code while msvc rejects it.</p>
  
  <pre><code>template&lt;class T1&gt;
  struct A
  {
      template&lt;class T2&gt;
      struct B
      {
          static B f;
          static typename A&lt;T2&gt;::template B&lt;T1&gt; g;
      };
  };
  
  template&lt;class T1&gt;
  template&lt;class T2&gt;
  typename A&lt;T2&gt;::template B&lt;T1&gt; // ok, typename/template required
      A&lt;T1&gt;::B&lt;T2&gt;::g;
  
  template&lt;class T1&gt;
  template&lt;class T2&gt;
  A&lt;T1&gt;::B&lt;T2&gt; // clang/gcc accept, msvc rejects missing typename
      A&lt;T1&gt;::B&lt;T2&gt;::f;
  </code></pre>
  
  <p>In general, a qualified-id <code>A&lt;T1&gt;::B&lt;T2&gt;</code> (where <code>A&lt;T1&gt;</code> is a dependent name) should be written <code>typename A&lt;T1&gt;::template B&lt;T2&gt;</code>. Is the behaviour of gcc/clang incorrect, or is there an exception to the general rule (quoted below) in this particular case?</p>
  
  <p>It could be argued that <code>A&lt;T1&gt;</code> is not a dependent name, or that <code>B&lt;T2&gt;</code> refers to a member of the current instantiation. However, at the point of parsing the type-specifier it's not possible to know that the current instantiation is <code>A&lt;T1&gt;</code>. It seems problematic to require the implementation to guess that <code>A&lt;T1&gt;</code> is the current instantiation.</p>
  
  <blockquote>
    <p>14.6 Name resolution [temp.res]</p>
    
    <p>A name used in a template declaration or definition and that is dependent on a template-parameter is
    assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
    by the keyword typename.</p>
    
    <p>14.2 Names of template specializations [temp.names]</p>
    
    <p>When the name of a member template specialization appears after <code>.</code> or <code>-&gt;</code> in a postfix-expression or after a
    nested-name-specifier in a qualified-id, and the object or pointer expression of the postfix-expression or the
    nested-name-specifier in the qualified-id depends on a template parameter (14.6.2) but does not refer to a
    member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword
    template. Otherwise the name is assumed to name a non-template.</p>
  </blockquote>
  
  <p>To further investigate what clang is doing here, I also tried this:</p>
  
  <pre><code>template&lt;class T1&gt;
  struct C
  {
      template&lt;class T2&gt;
      struct D
      {
          static typename A&lt;T1&gt;::template B&lt;T2&gt; f;
          static typename A&lt;T1&gt;::template B&lt;T2&gt; g;
      };
  };
  
  template&lt;class T1&gt;
  template&lt;class T2&gt;
  typename A&lt;T1&gt;::template B&lt;T2&gt; // ok, typename/template required
      C&lt;T1&gt;::D&lt;T2&gt;::f;
  
  template&lt;class T1&gt;
  template&lt;class T2&gt;
  A&lt;T1&gt;::B&lt;T2&gt; // clang rejects with incorrect error
      C&lt;T1&gt;::D&lt;T2&gt;::g;
  </code></pre>
  
  <p>Clang gives <code>error: redefinition of 'g' with a different type</code>, but the type of <code>g</code> actually matches the declaration.</p>
  
  <p>I would instead expect to see a diagnostic suggesting the use of <code>typename</code> or <code>template</code>.</p>
  
  <p>This gives credit to the hypothesis that clang's behaviour in the first example is unintended.</p>