【问题标题】:Overload Resolution: How is this not ambiguous?重载解决方案:这不是模棱两可的吗?
【发布时间】:2015-12-15 03:06:16
【问题描述】:
假设我们有这段代码,复制自一个单独的问题:
namespace x
{
void f()
{
}
class C
{
void f()
{
using x::f;
f(); // <==
}
};
}
指定行上的名称f 明确指代x::f(至少根据gcc 和clang)。为什么在这种情况下x::f 比x::C::f 更受欢迎?因为两个名字都是可见的,所以不应该模棱两可吗?
【问题讨论】:
标签:
c++
language-lawyer
overload-resolution
【解决方案1】:
因为using声明将x::f纳入f的范围,比C的范围窄。不合格查找会考虑本地块范围,找到匹配项,然后在考虑更广泛的类范围之前停止。由于没有函数参数,因此没有依赖于参数的查找,因此不考虑进一步的作用域。
【解决方案2】:
@MikeSeymour 的回答很到位;以下是相关的标准引用(C++11,强调我的):
13.3.1.1.1/3:
在不合格的函数调用中,名称不受-> 或. 运算符的限定,并且具有更通用的形式
primary-expression。 名称在函数调用的上下文中按照正常规则进行查找
用于函数调用 (3.4) 中的名称查找。通过该查找找到的函数声明构成了一组
候选函数。 由于名称查找规则,候选函数集完全由 (1)
非成员函数或 (2) 完全是某个类 T 的成员函数。 ...
3.4.1/1:
在 3.4.1 中列出的所有情况下,将按照每个列表中列出的顺序搜索范围以查找声明
各自的类别;一旦找到名称的声明,名称查找就会结束。如果没有声明
发现,程序格式不正确。
3.4.1/8
在函数的 declarator-id 之后的类 X 的成员函数 (9.3) 的定义中使用的名称
... 应在其中之一中声明
有以下几种方式:
- 在其用于使用它的块或封闭块 (6.3) 之前,或
- 应为
X 类的成员或X (10.2) 基类的成员,或
- ...
从 3.4.1/8 开始,我们看到在使用它的块中名称 f 的声明(例如声明 using x::f;)早于 f 作为类 @ 的成员列出987654330@。根据 3.4.1/1,选择较早的那个,因此整个查找解析为 using 声明引入的 x::f。
【解决方案3】:
我认为来自 C++ 标准的这些引用将是相关的:
来自 C++ 标准(7.3.3 using 声明)
13 由于 using-declaration 是一个声明,因此限制
同一声明区域中的同名声明 (3.3)
也适用于 using-declarations。
和(3.3.7 类范围)
4) 在成员函数中声明的名称隐藏了
范围延伸到或超过成员末尾的同名
函数的类。