This rule is called "biphasic name lookup."
Names that do not depend on the template parameters are checked and checked upon determination, and dependent names are checked at the time of instantiation.
In your example, there is one important detail: the end of the translation unit is also considered the instantiation point for function templates:
C ++ 14 N4140 14.6.4.1 [temp.point] P8:
A specialization of a function template, a template of a member function, or a member function or a static data element of a class template can have several instantiation points inside a translation unit and, in addition to the instantiation points described above, for any such specialization that has an instantiation point inside a translation unit, end translation units are also considered a point of specification.
Thus, although the type is not incomplete at point "2", where an explicit instantiation occurs, it ends at the end of the file, which makes the creation of the template legal.
Note : Microsoft compiler does not fully implement this rule, violating the standard. In the Microsoft compiler, the entire search takes place at the time the instance is created (so the example should work, but I do not have access to the MSVC check). Other major compilers implement this rule correctly.
source share