【问题标题】:Unexpectedly ambiguous overload resolution in VC++ 2012VC++ 2012 中出乎意料的模棱两可的重载解决方案
【发布时间】:2014-09-02 13:13:39
【问题描述】:

Visual C++ 2012。代码。我认为它应该编译;编译器恭敬地不同意。我已将我的复制范围缩小到:

struct  B { };

void foo(B* b, signed int si) { } // Overload 1
void foo(B const* b, unsigned int ui) { } // Overload 2

int main()
{
    B b;
    unsigned int ui;
    foo(&b, ui);
}

所以我们有两个候选者来解决重载问题。对于第一个重载,第一个参数完全匹配,第二个参数需要整数转换(无符号到有符号)。对于第二个重载,第二个参数完全匹配,第一个参数需要一个 cv 调整(因为&b 是一个指向非常量的指针)。

现在看来,这应该是完全明确的。对于重载 1,第一个参数是标准的重载决议部分定义的“精确匹配”,但第二个参数是“转换”。对于重载 2,两个参数都是“精确匹配”(限定转换与身份处于同一等级)。因此(我的推理显然不完美),应该选择重载 2,没有歧义。然而:

a.cpp(12): error C2666: 'foo' : 2 overloads have similar conversions
    a.cpp(6): could be 'void foo(const B *,unsigned int)'
    a.cpp(5): or       'void foo(B *,int)'
    while trying to match the argument list '(B *, unsigned int)'
    note: qualification adjustment (const/volatile) may be causing the ambiguity

GCC 在默认方言和 C++11 中的代码似乎都很好(感谢 IDEOne!)。所以我很想把它归结为 MSVC 中的一个错误,但是(a)你知道他们对那些认为他们的错误是编译器错误的人说了什么,并且(b)这似乎是一个非常明显的错误,在一致性测试期间会发出危险信号的那种。

这是不合规的 MSVC 还是不合规的 GCC? (或两者兼而有之?)我对过载解决方案的推理是否合理?

【问题讨论】:

  • 我不知道哪个编译器是正确的,但作为一个人类,我更喜欢知道将使用哪个重载,而不必根据两种类型转换的“优先级”来消除歧义:-)
  • @Cameron 哦,我同意。实际用例更有意义,而且确实看起来明确。

标签: c++ visual-c++ overloading overload-resolution compiler-bug


【解决方案1】:

MSVC 是正确的。

gcc 4.9.0 说:

警告:ISO C++ 表示这些是模棱两可的,即使第一个的最差转换优于第二个的最差转换:[默认启用]

clang 3.4.1 同意这两个函数是不明确的。

虽然B* => B*B* => B const* 都具有完全匹配 rank,但前者仍然是一个更好的转换序列 per over.ics.rank/3;这是(每个示例)确保:

int f(const int *);
int f(int *);
int i;
int j = f(&i); // calls f(int*)

来自 over.ics.rank/3:

如果 [...]
,标准转换序列 S1 是比标准转换序列 S2 更好的转换序列 — S1 和 S2 仅在它们的限定转换上不同,并且分别产生相似的类型 T1 和 T2 (4.4),并且类型 T1 的 cv 限定签名是类型 T2 的 cv 限定签名的适当子集。 [...]

当然,unsigned int => unsigned intunsigned int => signed int 更好。所以在这两个重载中,一个在第一个参数上具有更好的隐式转换序列,另一个在第二个参数上具有更好的隐式转换序列。因此它们无法根据 over.match.best/1 进行区分。

【讨论】:

  • 谢谢。那么我的推理有什么缺陷呢?从我对标准的阅读看来,重载 2 没有转换,这比重载 1 的相应转换差——编译器在比较重载时不应该更喜欢 B*B const*
  • @Sneftel 啊,但确实如此 - 我将添加确切的措辞。
  • 是的,刚刚发现。看来我太早停止阅读了。感谢您的挖掘。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多