Case 1
Here we consider the statement: g<T>(p);
template<typename T> void func(T p) {
g<T>(p); //ERROR
}
int main()
{
}
In the above code snippet the name g is a unqualified dependent name. And from source: two phase lookup:
During the first phase, while parsing a template unqualified dependent names are looked up using the ordinary lookup rules. For unqualified dependent names, the initial ordinary lookup—while not complete—is used to decide whether the name is a template.
Now lets apply this to the statement g<T>(p);. When parsing the function template func, the statement g<T>(p); is encountered. Since g is a dependent qualified name, according to the above quoted statement, the name g is looked up using ordinary lookup rules. This is so that the compiler can decide whether the name g is a template. But since there is no declaration for a function template named g before this point, the first angle bracket < is treated as a less than symbol and hence produces the error you mentioned. Also, note that ADL is done in second phase. But for that to happen we must first successfully parse the generic definition of function func.[source: C++ Templates: The Complete guide: Page 250 second last paragraph]
Note that compilers are allowed to delay error until instantiation which is why some compilers compiles your code without any error. Demo.
Case 2
Here we consider the statement g(p);.
template<typename T> void func(T p) {
g(p); // NO ERROR
}
int main()
{
}
In this case also, the name g is an unqualified dependent name. So according to the quoted statement from the beginning of my answer, the name g is looked up using ordinary lookup rules. But since there is no g visible at this point we have an error. There are two things to note here:
- Since this time you have not explicitly(by using the angle brackets) called
g, there is no syntax error.
- And since there are no syntax error in this case and there are no POI for
func in your program, so here there are no errors to delay and the program compiles fine. However, if you instantiate func then you'll get error at instantiation time saying g was not declared.
g(p);might be found by ADL. For template notation case, any (but with same name) previous template declaration would be enough.