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
它是指向非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 ambiguity
无论是在默认方言还是在C ++ 11中,GCC的代码似乎都很好(感谢IDEOne!)。因此,我很乐意将此归结为MSVC中的错误,但是(a)您知道他们对那些认为自己的错误是编译器错误的人的看法,并且(b)这似乎是一个非常明显的错误,即在一致性测试期间会发出危险信号的排序。
这是不符合要求的MSVC还是不符合要求的GCC?(或两者兼有?)关于超载分辨率的推理是否合理?
MSVC是正确的。
gcc 4.9.0说:
警告:ISO C ++表示这些含义不明确,即使第一个最差的转换比第二个最差的转换要好:[默认启用]
clang 3.4.1同意这两个函数是模棱两可的。
尽管B* => B*
和B* => B const*
两者都具有完全匹配排名,但对于over.ics.rank / 3,前者仍然是更好的转换顺序;(根据示例)这是为了确保:
int f(const int *);
int f(int *);
int i;
int j = f(&i); // calls f(int*)
从over.ics.rank / 3:
daccess-ods.un.org daccess-ods.un.org如果标准转换序列
S1仅在标准转换方面有所不同,并且分别产生相似的类型T1和T2(4.4),并且cv限定签名,则标准转换序列S2比标准转换序列S2更好。类型T1是类型T2的cv资格签名的适当子集。[...]
而且,当然unsigned int => unsigned int
比更好unsigned int => signed int
。因此,在两个重载中,一个重载在第一个参数上具有更好的隐式转换序列,另一个重载在第二个参数上具有更好的隐式转换序列。因此,无法按over.match.best/1区分它们。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句