On compiling that code: --- begin code --- class Y {}; void f(Y*) { } // line 3. If comment - all ok template < typename T> void sel(T* a) { f(a); } //line 6 void f(void*) {} int main(int argc, char **argv) { sel((void*)0); //line 12 } --- end code --- Àppears error: ../main.cpp: In function ‘void sel(T*) [with T = void]’: ../main.cpp:12: instantiated from here ../main.cpp:6: error: invalid conversion from ‘void*’ to ‘Y*’ ../main.cpp:6: error: initializing argument 1 of ‘void f(Y*)’ If comment line 3, then work. Also work, if line 3 move after line 6. If functions f(Y*), f(void*) and sel(T*) placed in different header files, then arise dependency on order including headers.
GCC is correct here. Well partly. It should reject it no matter what.
*** Bug 34893 has been marked as a duplicate of this bug. ***
This case is similar to the bug 31047 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31047). There Andrew Pinski wrote (comment 4): >14.6.4.2/1 says this is invalid code. >For a function call that depends on a template parameter, if the function is an >unqualified-id but not a template-id, the candiate functions are found using >the usual lookup rules (3.4.1, 3.4.2) except that: >.... > >Paraphasing since I don't want to type it all in >* non argument dependent lookup (3.4.1: template definition context >* argument dependent lookup (3.4.2): template definition context and template >instation context This case is argument dependent lookup, therefore should used both contexts - definition and instantiation. Point of instantiation "sel(T* a) with T = void" - after "void f(void*)" and before "int main()". Thus should be visible both f(void*) and f(Y*), whether not so? Why gcc does not see "void f (void *)"?
In resolving dependent names, names from the following sources are considered: — Declarations that are visible at the point of definition of the template. — Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.7.4.1) and from the definition context. — If T is a fundamental type, its associated sets of namespaces and classes are both empty. — If T is a pointer to U or an array of U, its associated namespaces and classes are those associated with U. void* is a pointer to fundamental type so has no associated namespaces, so only the first source is considered, and only f(T*) is visible at the point of definition. This is invalid.
Actually ....
> void* is a pointer to fundamental type so has no associated namespaces Well there is a still open defect report that says this might not be true :). *** This bug has been marked as a duplicate of 29131 ***