为什么 B::f 不能解决歧义,而 A::f 可以解决?
Why doesn't B::f solve the ambiguity but A::f does?
为什么B::f不能解决歧义,而A::f能解决?
namespace A
{
class X { };
void f( X );
}
namespace B
{
void f( A::X );
void g( A::X x )
{
using B::f; // which expression shall I use here to select B::f?
f(x); // ambiguous A::f or B::f
}
}
using声明充当普通声明:它隐藏外部作用域声明,但不抑制依赖于参数的查找(ADL)。
当你做using B::f
时,你基本上什么都不改变。您只需在本地作用域中重新声明B::f
,在那里它已经可见了。这并不妨碍ADL也找到A::f
,这在A::f
和B::f
之间产生歧义。
如果执行using A::f
,则A::f
的本地声明将隐藏B::f
的外部声明。因此B::f
不再可见,也不再通过非限定名称查找找到。现在只找到了A::f
,这意味着不再有歧义了。
抑制ADL是不可能的。由于您的案例中的参数是
A::X
类型,因此ADL将始终为不合格名称f
找到函数A::f
。你不能把它排除在考虑之外。这意味着你不能在不产生歧义的情况下考虑B::f
。唯一的方法是使用限定名称
正如@Richard Smith在评论中正确指出的那样,ADL可以被抑制。ADL仅在函数名称本身用作函数调用中的后缀表达式时使用。以任何其他方式指定目标函数都会吓坏ADL。
例如,函数指针的初始化不受ADL 的约束
void g( A::X x )
{
void (*pf)(A::X) = &f;
pf(x);
}
在上述示例中,将调用CCD_ 15。即使函数名周围只有一对()
也足以抑制ADL,即
void g( A::X x )
{
(f)(x);
}
已经足以使其调用CCD_ 17。
当编译器试图在f(x)
中解析f
时,它会找到B::f
,因为我们在名称空间B
中。由于x
是在名称空间A
中定义的X
的实例,因此它还使用参数相关查找来查找A::f
。因此产生了歧义。
使用B::f
的声明没有任何效果,因为我们已经在名称空间B
中了。
要解决歧义,请使用A::f(x)
或B::f(x)
。
您应该每次都显式地编写命名空间。只做
#include <iostream>
namespace A
{
class X { };
void f( X ) {
std::cout << "A";
}
}
namespace B
{
void f( A::X ) {
std::cout << "B";
}
void g( A::X x )
{
// using B::f;
B::f(x);
}
}
int main() {
B::g(A::X()); // outputs B
}
相关文章:
- 歧义语法是如何解决的
- 使用enable_if解决多重继承歧义
- 如何解决传递给boost线程的函数中的歧义
- 解决虚拟方法的歧义继承的两种方法
- 解决歧义的方法
- 如何解决以下代码中的函数重载歧义
- 使用声明解决歧义
- 解决 CRTP 函数重载歧义问题
- 如何解决钻石问题的这种歧义
- 在size_t的声明中解决歧义
- LR解析器如何解决歧义和冲突
- 概念没有按预期解决歧义。代码示例有什么问题?
- 引用如何解决多重继承中的歧义
- 解决C++构造函数和调用歧义
- 如何解决嵌入结构内嵌入的操作员中的歧义
- 在这里的派生类中,如何解决歧义
- 用前瞻性解决歧义增强::精神::气语法
- 此关键字在启动器中用于解决歧义
- 使用双大括号,例如 Foo{{初始值设定项列表}} 来解决歧义
- 为什么 B::f 不能解决歧义,而 A::f 可以解决?