【问题标题】:C++ strange ambiguous call to overloaded function [duplicate]C ++对重载函数的奇怪模糊调用[重复]
【发布时间】:2013-04-12 10:31:42
【问题描述】:

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

以下代码无法编译:

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++ 标准中定义?还有其他解释吗?谢谢。

【问题讨论】:

  • 第一种情况有两个可能的匹配项,导致错误。在第二种情况下,您删除了这两个可能的匹配项之一,从而消除了错误。有什么玄机?
  • 为什么在第二种情况下我删除了一个可能的匹配项?还有 ::a(bar::foo) 和 foobar::a(bar::foo)。你明白其中的奥秘了吗?

标签: c++ namespaces compiler-theory ambiguous


【解决方案1】:

'void a(foo)' [使用参数相关查找找到]

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

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

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

在第二种情况下,a 在 foobar 中,但不在参数类型 bar::foo 的命名空间中:其中是 bar。

【讨论】:

  • +1 感谢您的解释。
【解决方案2】:

有两个符号 a(foo) 并且编译器无法决定使用哪一个。 因此,您必须明确指示编译器。

如果你想调用 foobar 的 a(foo),那么试试这个,

   void b(foo f) { foobar::a(f); }

如果你想要全局 a(foo) 然后试试这个,

   void b(foo f) { ::a(f); }

【讨论】:

  • 是的,我知道。但问题是为什么第二个示例编译而第一个不编译。唯一的区别是 struct foo 周围的命名空间。
猜你喜欢
  • 1970-01-01
  • 2011-12-12
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 2014-09-05
  • 1970-01-01
相关资源
最近更新 更多