title: How does the lookup rule apply to a name that is used in a default member initializer within a class template?
body: <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  template&lt;class T&gt;
  struct A{
      int c = T::a;
  };
  struct B{
      A&lt;B&gt; cc;
      static const int a = 0;
  };
  int main(){
  
  }
  </code></pre>
  <p>GCC and Clang both <a href="https://godbolt.org/z/Pc84PdrMh" rel="nofollow noreferrer">accept</a> the above example. Regarding how the lookup rule applies to a name in a class template specialization, which might be a member of a class that causes the implicit instantiation of the class template specialization is not clear in c++20 or before. Fortunately, it's clear in the current draft.<br />
  <a href="https://eel.is/c++draft/basic.lookup#class.member.lookup-3" rel="nofollow noreferrer">[basic.lookup#class.member.lookup-3]</a></p>
  <blockquote>
  <p>The declaration set is the result of a single search in the scope of C for N from immediately after the class-specifier of C if P is in a <strong>complete-class context of C</strong> or from <strong>P otherwise</strong>. If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.</p>
  </blockquote>
  <p>It seems that the rule can be used to interpret most cases that I said in the above, however, consider the above example, it's a bit special.</p>
  <p>The definition of non-static member <code>cc</code> would cause the implicit instantiation of specialization <code>A&lt;B&gt;</code>, at this point, it's not the complete context of class <code>B</code>. Hence, the subsequent lookup for a name in the scope <code>B</code> should be from this point. If <code>T::a</code> is used as the type-specifier of a non-static member of class template <code>A</code>, It's 100% sure that the compiler would report an error that says no identifier <code>a</code> can be found in the scope of <code>B</code>.</p>
  <p>However, except for the following rule<br />
  <a href="https://eel.is/c++draft/temp.res#general-1" rel="nofollow noreferrer">temp.res#general-1</a></p>
  <blockquote>
  <p>If the name is dependent (as specified in [temp.dep]), <strong>it is looked up for each specialization (after substitution)</strong> because the lookup depends on a template parameter.</p>
  </blockquote>
  <p>I cannot find any wording in the standard that states whether an implicit instantiation of <code>A</code> can cause the lookup rule to be applied to the name within the <strong>default member initializer</strong> or is not at that point.</p>
  <p>At first glance of the above rule, It should mean that the lookup should be performed for the name when the enclosing class template specialization is instantiating, then <code>a</code> cannot be found in the scope of <code>B</code> since it's not deemed as a complete class at that point and only these declarations that are reachable at point <code>P</code> can be found.</p>
  <p>Obviously, the behavior of GCC and Clang consider <code>T</code> is a complete type such that <code>a</code> can be found in <code>T</code>. In other words, it seems that these compilers do not immediately perform the lookup for <code>T::a</code> when <code>A</code> is instantiating. If I miss a certain special rule, please point them out.</p>