How does the lookup rule apply to a name that is used in a default member initializer within a class template?

Viewed 114
#include <iostream>
template<class T>
struct A{
    int c = T::a;
};
struct B{
    A<B> cc;
    static const int a = 0;
};
int main(){

}

GCC and Clang both accept 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.
[basic.lookup#class.member.lookup-3]

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 complete-class context of C or from P otherwise. If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.

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.

The definition of non-static member cc would cause the implicit instantiation of specialization A<B>, at this point, it's not the complete context of class B. Hence, the subsequent lookup for a name in the scope B should be from this point. If T::a is used as the type-specifier of a non-static member of class template A, It's 100% sure that the compiler would report an error that says no identifier a can be found in the scope of B.

However, except for the following rule
temp.res#general-1

If the name is dependent (as specified in [temp.dep]), it is looked up for each specialization (after substitution) because the lookup depends on a template parameter.

I cannot find any wording in the standard that states whether an implicit instantiation of A can cause the lookup rule to be applied to the name within the default member initializer or is not at that point.

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 a cannot be found in the scope of B since it's not deemed as a complete class at that point and only these declarations that are reachable at point P can be found.

Obviously, the behavior of GCC and Clang consider T is a complete type such that a can be found in T. In other words, it seems that these compilers do not immediately perform the lookup for T::a when A is instantiating. If I miss a certain special rule, please point them out.

0 Answers
Related