C++ 对重载函数的奇怪模棱两可的调用

标签 c++ namespaces compiler-theory ambiguous

<分区>

首先,这个问题纯属理论性质。我不是在寻找解决方案(我已经知道了),我只是在寻找解释。

以下代码无法编译:

struct foo {};
void a(foo) {}
namespace foobar {
    void a(foo) {}
    void b(foo f) {a(f);}
}
int main() {return 1;}

MSVC++:

1>c:\projects\codetests\main.cpp(7) : error C2668: 'foobar::a' : ambiguous call to overloaded function
1>        c:\projects\codetests\main.cpp(4): could be 'void foobar::a(foo)'
1>        c:\projects\codetests\main.cpp(2): or       'void a(foo)' [found using argument-dependent lookup]
1>        while trying to match the argument list '(foo)'

G++:

main.cpp: In function 'void foobar::b(foo)':
main.cpp:5:20: error: call of overloaded 'a(foo&)' is ambiguous
main.cpp:5:20: note: candidates are:
main.cpp:4:7: note: void foobar::a(foo)
main.cpp:2:6: note: void a(foo)

编译此代码时(MSVC++ 和 G++):

namespace bar {struct foo {};}
void a(bar::foo) {}
namespace foobar {
    void a(bar::foo) {}
    void b(bar::foo f) {a(f);}
}
int main() {return 1;}

这是为什么呢? foo 周围的命名空间在这里为编译器改变了什么?这种行为是否在 C++ 标准中定义?还有其他解释吗?谢谢。

最佳答案

'void a(foo)' [found using argument-dependent lookup]

好吧,令人惊讶的是 MSVC 有一个非常好的错误解释:

按照标准,在函数内部,编译器会在当前命名空间和定义参数类型的命名空间中查找符号。

在第一种情况下,a 位于 foobar 和参数类型 foo 的命名空间中:全局命名空间,使其不明确。

在第二种情况下,afoobar 中,但不在参数类型 bar::foo 的命名空间中:with is

关于C++ 对重载函数的奇怪模棱两可的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15969052/

相关文章:

c++ - 内存损坏可能是由无效*读取*释放的内存引起的吗?

c# - Linq 和 localhost,实体命名空间与程序命名空间不同,但仍然出现错误

c++ - 对于给定的输出,程序计算中使用了多少项?

c++ - 我应该在私有(private)项目中使用私有(private)类(class)吗?

c++ - 是否可以使用在没有命名空间的命名空间中声明的类名::

PHP不同的路径名空间和自动加载不起作用

compiler-construction - LLVM 中的实时值

parsing - 这个 'algorithm' 可以为空并且第一次工作(在解析器中)吗?

.net - 我正在尝试使用 System.Reflection.Emit 编写 .NET 编译器 我该如何进行类型解析?

c++ - 在 C++ 中添加 const-ness