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 says that name lookup of a name preceding ::
"considers only namespaces, types, and templates whose specializations are types". Are clang and gcc correct in rejecting this code? If so, what am I missing?
From C++ Working Draft Standard n3337
3.4.3 Qualified name lookup [basic.lookup.qual]
The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.
14.2 Names of template specializations [temp.names]
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.
After name lookup (3.4) finds that a name is a template-name or that an operator-function-id or a literal-operator-id refers to a set of overloaded functions any member of which is a function template if this is followed by a
<
, the<
is always taken as the delimiter of a template-argument-list and never as the less-than operator.
Edit
To avoid confusion of this issue with the ambiguity between an expression and a declaration, here is the original code with the 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 results in the same error in all cases. The <
cannot be interpreted as an operator.
ambiguous
is unambiguously a template-name, but could either be a type or a function. It's possible to parse the entire template-id without knowing whether it names a function or a type, and resolve the ambiguity later on. Does the standard excuse the implementor from doing this?
error: qualified name refers into a specialization of function template 'ambiguous'
, gcc:cannot resolve overloaded function ‘ambiguous’ based on conversion to type ‘int’
, msvc'ambiguous' : use of class template requires template argument list
– Paestum::
whether or not we should ignore the non-type name - so the ambiguity remains unresolved until we parse the entiretemplate-id
:D. – Paestumtemplate-id
until we know thatambiguous
names a template, which means that the name has to be bound first. (The<
could be a less than.) – Oxblood<
is a keyword which names a type (likeint
); it ceases to be valid for a user defined type (since the lookup used will depend on whether<
is less than, or opens a template argument list). Presumably, the committee didn't want to make this a special case. – Oxblood<
differ between an expression or a template-argument-list? Even if the name of the template is a qualified-id, "the names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression occurs." – Paestum