Sne*_*tel 5 c++ overloading visual-c++ overload-resolution compiler-bug
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);
}
Run Code Online (Sandbox Code Playgroud)
所以我们有两个重载决策候选者.对于第一个重载,第一个参数完全匹配,第二个参数需要整数转换(unsigned to signed).对于第二个重载,第二个参数完全匹配,第一个参数需要cv-adjustment(因为&b是指向非const的指针).
现在,似乎这应该是完全明确的.对于Overload 1,第一个参数是标准关于重载决策的部分定义的"精确匹配",但第二个参数是"转换".对于Overload 2,两个参数都是"Exact Matches"(资格转换与身份相同).因此(我显然不完美的推理),应该选择Overload 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
Run Code Online (Sandbox Code Playgroud)
对于默认方言和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*)
Run Code Online (Sandbox Code Playgroud)
来自over.ics.rank/3:
标准转换序列S1是比标准转换序列S2更好的转换序列,如果[...]
- S1和S2仅在它们的资格转换方面不同并且分别产生类似类型T1和T2(4.4),并且cv资格签名为类型T1是T2类型的cv资格签名的适当子集.[...]
而且,当然,unsigned int => unsigned int比unsigned int => signed int.所以在两个重载中,一个在第一个参数上有一个更好的隐式转换序列,另一个在第二个参数上有一个更好的隐式转换序列.因此,无法根据over.match.best/1区分它们.