Both clang and gcc reject this code:
template<int i> struct ambiguous { static const int value = i; }; namespace N { template<int i> void ambiguous(); int i = ambiguous<3>::value; // finds the function template name }
However, they both accept the following code:
struct ambiguous { static const int value = 0; }; namespace N { void ambiguous(); int i = ambiguous::value; }
The standard states that searching for the name of a name preceding :: only considers namespaces, types, and patterns whose specialization is types. "Are clang and gcc right to reject this code? If so, what am I missing?
From C ++ Working draft standard n3337
3.4.3 Qualified Name Search [basic.lookup.qual]
The name of a member of a class or element of a namespace or enumerator can be passed after the permission :: scope statement (5.1), applied to the nested qualifier name, which denotes its class, namespace or enumeration. If :: the scope operator in the nested qualifier is not preceded by the decltype-specifier, the search for the name preceding this :: considers only namespaces, types and templates whose specialization is types . If the name found does not indicate a namespace or class, enumeration or dependent type, the program is poorly formed.
14.2 Names of specialized templates [temp.names]
In order for the template name to be explicitly specified by the template arguments, the name must be known in order to refer to the template .
After searching for the name (3.4), it finds that the name is the name of the template or that the operator-function-identifier or identifier of the operator-literal refers to a set of overloaded functions, any member that is a function template , if it follows a < , < always accepted as a delimiter of a list of argument templates and never less than an operator .
Edit
To avoid confusing this problem with ambiguity between expression and declaration, here is the source code with templates using a type parameter instead of a non-type parameter.
template<class> struct ambiguous { static const int value = 0; }; namespace N { template<class> void ambiguous(); int i = ambiguous<int>::value; // finds the function template name }
This leads to the same error in all cases. < cannot be interpreted as an operator.
ambiguous uniquely the name of the template, but can be either a type or a function. You can parse the entire template identifier without knowing whether it calls a function or type, and resolve the ambiguity later. Does this justify execution as standard?