In C++, type checking of function templates is deferred until the template function is called (instantiated). For example
template<typename T>
int right() {
return T::f();
}
is legal C++ code, after which the function call right<Foo>() is legal as long as type Foo has a static method f that returns an int.
I observed that my C++ compiler (Clang) can catch some type errors as long as they don’t depend on the template parameter. For example
template<typename T>
int wrong1() {
return "";
}
Fails to compile with Clang 16.0.0 (char* is not compatible with int), even if the template function is never called (instantiated). Which brings a question: does the C++ compiler require template function declarations to be well-typed (ignoring expressions that depend on template parameters)? Or is it just a feature of Clang, where it tries to catch type errors as early as possible?
>Solution :
Any non-dependent construct in a template definition that would cause a hypothetical instantiation of the template immediately after its definition to be ill-formed makes the program IFNDR (ill-formed, no diagnostic required), meaning that there is no requirement imposed by the C++ standard on how a compiler shall handle such a program.
The compiler is allowed to bail out of compilation with an error immediately in this situation, even if there is no actual instantiation of the template, or it may ignore it and only provide a diagnostic when the template is actually instantiated. (And technically it is also allowed to do anything else, such as compiling the program but having it behave in unexpected ways. IFNDR is effectively the same as a undefined behavior for all inputs.)
There are a few additional situations in which a template definition can be checked for validity already at its definition, causing the program to be IFNDR if certain requirements are not satisfied as listed in [temp.res.general]/8. For example if the template is not actually instantiated but any instantiation of the template would be ill-formed.
But aside from the listed situations a compiler is not permitted to bail out of compilation or issue a diagnostic for a template for which a valid specialization could be instantiated.
"non-dependent" has a specific technical meaning relating to whether or not a construct is dependent on a template argument. For a reference see https://en.cppreference.com/w/cpp/language/dependent_name as well as [temp.dep] in the standard (draft).
In your examples T::f is a dependent name but the expression "" and return type in the second example are not (type-/value-)dependent. Furthermore it is impossible to specialize the template in the second example such that the conversion from "" to the int return value is well-formed, while it is possible to define and pass a type for T in the first example such that the instantiation would be well-formed.