clang 和 gcc 都拒绝此代码:
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
}
但是,它们都接受以下代码:
struct ambiguous
{
static const int value = 0;
};
namespace N
{
void ambiguous();
int i = ambiguous::value;
}
标准说在 ::
之前的名称的名称查找“只考虑专门化为类型的 namespace 、类型和模板”。 clang 和 gcc 拒绝此代码是否正确?如果是这样,我错过了什么?
来自 C++ 工作草案标准 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.
编辑
为了避免将此问题与表达式和声明之间的歧义混淆,这里是原始代码,其中模板使用类型参数而不是非类型参数。
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
}
这在所有情况下都会导致相同的错误。 <
不能解释为运算符。
ambiguous
是明确的模板名称,但可以是类型或函数。可以在不知道它命名的是函数还是类型的情况下解析整个 template-id,并在以后解决歧义。标准是否允许实现者不这样做?
最佳答案
问题是你引用的段落最终变成了
申请太晚了。在到达那里之前,编译器必须
确定 ambiguous<3>::value
, <
和 >
是
模板参数定界符,不大于和小于
比。 (考虑:
int ambiguous;
int value:
// ...
int i = ambiguous<3>::value;
,解析为 (ambiguous < 3) > ::value
, 其中<
和
>
分别小于和大于。)这
涉及查找 ambiguous
作为一个不合格的名字,和
将符号绑定(bind)到 N::ambiguous
.之后,你被卡住了
使用实例化模板 N::ambiguous<3>
至左侧
::
,这是不合法的。
编辑:
这个问题并不像人们想象的那么清楚:只有标准
引用第 14.2 节中的第 3.4 节,其中讨论了这一点,
第 3.4 节讨论了所有可能的名称规则
抬头。另一方面,实际上只有一种方法可以
解释它:编译器不能进一步解析任何东西直到
它知道是否ambiguous
是否命名模板,并且可以
决定是否以下 <
大于或开
模板参数列表。当然,它不能“重新绑定(bind)”
之后的参数,一旦它解析了以下标记,因为
在一般情况下,重新绑定(bind)可能会改变
<
,使解析无效。在实践中,虽然标准
没有说得那么清楚,名称查找
在这种情况下必须是非限定名称查找(或类成员
访问,如果名称前面有 .
或 ->
运营商)。
关于c++ - 在查找::之前的名称时,函数模板的名称是否应该可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18311496/