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?(或两者兼而有之?)我关于过载分辨率的推理是否合理?