首先,这个问题完全是理论性的。我不是在寻找解决方案(我已经知道了),我只是在寻找解释。
以下代码无法编译:
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 ++ - Standard中定义的吗?还有其他解释吗?感谢。
答案 0 :(得分:4)
'void a(foo)'[使用参数依赖查找找到]
嗯,令人惊讶的是MSVC有一个非常好的错误解释:
遵循标准,在函数内部,编译器在当前命名空间和定义参数类型的命名空间中查找符号。
在第一种情况下a
在foobar
和参数类型foo
的命名空间中:全局命名空间,使其不明确。
在第二种情况下,a
位于foobar
但不在参数类型bar::foo
的名称空间中:with bar
。
答案 1 :(得分:0)
有两个符号a(foo),编译器无法决定使用哪一个。 因此,您必须明确指示编译器。
如果你想要调用foobar的(foo),那就试试吧,
void b(foo f) { foobar::a(f); }
如果你想要全局a(foo),那就试试吧,
void b(foo f) { ::a(f); }