【发布时间】: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