视觉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是指向非const的指针)。
现在,这似乎应该是完全毫不含糊的。对于重载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 ambiguityGCC似乎对默认方言和C++11 (谢谢,IDEOne!)的代码都很在行。所以我倾向于把这归咎于MSVC中的一个bug,但是(a)你知道他们对那些认为自己的bug是编译器错误的人说了什么,(b)这似乎是一个很明显的错误,在他们的一致性测试中会发出警告。
这是不符合MSVC,还是不符合GCC?(还是两者兼而有之?)我对过载决议的推理是否合理?
发布于 2014-09-02 13:17:00
MSVC是正确的。
gcc 4.9.0说:
警告: ISO C++说这些都是模棱两可的,尽管第一个最坏的转换比第二个最坏的转换要好:默认情况下启用。
clang 3.4.1同意这两个函数是不明确的。
尽管B* => B*和B* => B const*都具有精确的匹配级别,但前者仍然是每个over.ics.range/3更好的转换序列;这是(例如)以确保:
int f(const int *);
int f(int *);
int i;
int j = f(&i); // calls f(int*)来自over.ics.level/3:
标准转换序列S1是比标准转换序列S2更好的转换序列。 - S1和S2的资格转换不同,分别产生了相似类型的T1和T2 (4.4),而T1类型的cv-资格签名是T2型资格证书签名的一个适当子集。..。
当然,unsigned int => unsigned int比unsigned int => signed int更好。因此,在这两个重载中,一个在第一个参数上有一个更好的隐式转换序列,另一个在第二个参数上有一个更好的隐式转换序列。因此,它们不能被区分为每一个过载的匹配。
https://stackoverflow.com/questions/25624303
复制相似问题