GCC accepts the following code: template <typename T> struct meta { typedef typename T::type type; }; struct S{}; template <typename T> typename meta<T>::type foo(T, S); int foo(int, int); int main() { foo(0, 0); } Clang rejects this code with the following error: test.cpp:4:22: error: type 'int' cannot be used prior to '::' because it has no members typedef typename T::type type; ^ test.cpp:10:10: note: in instantiation of template class 'meta<int>' requested here typename meta<T>::type foo(T, S); ^ test.cpp:10:24: note: while substituting deduced template arguments into function template 'foo' [with T = int] typename meta<T>::type foo(T, S); ^ I believe the code is invalid (and clang's error is correct), for the following reasons: 1. Template argument deduction should be performed on the template candidate *before* to discarding it due to a type mismatch for the second parameter (expected S, got int). Section 13.3.1/7 of the standard says (emphasis mine): "In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction. Those candidates are *then* handled as candidate functions in the usual way. A given name can refer to one or more function templates and also to a set of overloaded non-template functions. In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions." 2. Template argument deduction on the template candidate should fail with a hard error (not SFINAE), because the error that occurs (T::type not being valid for T = int) is not in the immediate context of the function type. (Section 14.8.2/8, emphasis mine: "If a substitution results in an invalid type or expression, type deduction fails. [...] Only invalid types and expressions *in the immediate context* of the function type and its template parameter types can result in a deduction failure. [...]"). GCC does reject the following example: template <typename T> struct meta { typedef typename T::type type; }; template <typename T> typename meta<T>::type foo(T); int foo(int); int main() { foo(0); } With the following error: test.cpp: In instantiation of 'struct meta<int>': test.cpp:8:24: required by substitution of 'template<class T> typename meta::type foo(T) [with T = int]' test.cpp:14:10: required from here test.cpp:4:30: error: 'int' is not a class, struct, or union type typedef typename T::type type; ^ suggesting that GCC already obeys point (2) above, and therefore the problem is likely to be with point (1).
Richard Smith has suggested that GCC is actually allowed not to instantiate 'meta<int>' as per [temp.inst]/p6: "If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place." If this is really what's happening - GCC is not instantiating 'meta<int>' because it can determine without doing so that the first overload of 'foo' will not be chosen - then I guess we can close this PR as INVALID.
Current ICC also accepts this.
Current SolarisStudio also accepts it. I guess I'm going to add the testcase and close the bug.
Author: paolo Date: Tue May 13 16:14:19 2014 New Revision: 210385 URL: http://gcc.gnu.org/viewcvs?rev=210385&root=gcc&view=rev Log: 2014-05-13 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54310 * g++.dg/template/pr54310.C: New. Added: trunk/gcc/testsuite/g++.dg/template/pr54310.C Modified: trunk/gcc/testsuite/ChangeLog
Done.