------- Comment #14 from rguenth at gcc dot gnu dot org 2009-06-21 10:38 ------- Testcase w/o std=c++0x:
template <typename I> struct T { typedef typename I::d d; }; template <typename I> I next(I __x, typename T<I>::d __n = 1); namespace X { class C { }; template<class T> void next(T) { } } int main() { X::C c; next(c); } but EDG rejects this also: t.C(1): error: class "X::C" has no member "d" template <typename I> struct T { typedef typename I::d d; }; ^ detected during instantiation of class "T<I> [with I=X::C]" at line 11 t.C(11): error: more than one instance of function template "next" matches the argument list: function template "void X::next(T)" function template "I next(I, T<I>::d)" argument types are: (X::C) next(c); ^ I'm not sure SFINAE applies here as the substitution T<I> succeeds. With the 'typename' removed in the decl for next we get t.C(2): error: nontype "T<I>::d [with I=I]" is not a type name template <typename I> I next(I __x, T<I>::d __n = 1); ^ t.C(11): error: more than one instance of function template "next" matches the argument list: function template "void X::next(T)" function template "I next(I, <error-type>)" argument types are: (X::C) next(c); ^ with template <typename I> I next(typename T<I>::d __n); we finally get SFINAE and X::next is chosen. The issue here seems to be that the default value for the argument somehow gets in the way and so the 2nd argument isn't checked properly? So an implementation workaround would be to use overloading for the default argument case like template <typename I> I next(I __x, typename T<I>::d __n); template <typename I> I next(I __x); with the first arg obfuscated so that SFINAE applies, typename iterator_traits<_InputIterator>::_InputIterator or something like this? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40497