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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With