Testcase: template <int> struct A { typedef int I; }; template <class T> typename A<T() >::I foo (T) { return 0; } ----- I found this while looking at PR 27402. This is not a regression as it did not work in 2.95 on wards.
gcc parses this as template <class T> typename A<T (&)() >::I foo (T) { return 0; } i.e. as meaning that the argument is not an integer, but a function that returns an integer. A simpler testcase is this (icc accepts it, though I'm not sure who's right): ------------------- template <int> struct A {}; A<int()> foo (int); ------------------- W.
t4.cc:4:17: error: type/value mismatch at argument 1 in template parameter list for ‘template<int <anonymous> > struct A’ t4.cc:4:17: error: expected a constant of type ‘int’, got ‘T()’
Wolfgang is right, the testcase is invalid, T() is parsed as a function type, not an expression that value-initializes a T. [temp.arg]p2, "In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter." i.e. it doesn't matter that the argument is expecting a non-type parameter of type int, because T() can be a type-id it is interpreted as one. (This happened to be discussed last month on the committee reflectors) Using T{} in C++11 works because that cannot be a type-id and is unambiguously an initialization of T.