Unexpectedly ambiguous overload resolution in VC ++ 2012

Visual C ++ 2012. Code. I think he should compile; the compiler respectfully disagrees. I narrowed the reproduction to:

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); } 

So, we have two candidates for permission to overload. For the first overload, the first argument exactly matches, and for the second argument an integral conversion is required (unsigned for signing). For the second overload, the second argument matches exactly, and the first argument requires cv-tuning (because &b is a pointer to non-constant).

Now it seems that this should be absolutely unambiguous. For Overload 1, the first argument is Exact Match, as defined by the standard section for overload resolution, and the second is Conversion. For Overload 2, both arguments are โ€œExact Coincidencesโ€ (qualification conversion has the same rank as personality). Therefore (my, apparently, imperfect reasoning), you should choose Overload 2 without ambiguity. But still:

 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 looks great with code, both in the default dialect and in C ++ 11 (thanks, IDEOne!). Therefore, I am inclined to prevent this error in MSVC, but (a) you know that they are talking about people who think that their errors are compiler errors, and (b) it looks like this will be a fairly obvious error, sorting that would send red flags during their conformance testing.

Is it inappropriate MSVC or inappropriate GCC? (Or both?) Is my reasoning about sound overloaded?

+5
source share
1 answer

MSVC is correct.

gcc 4.9.0 says:

warning: ISO C ++ says they are ambiguous, although the worst conversion for the first is better than the worst conversion for the second: [enabled by default]

clang 3.4.1 agrees that the two functions are ambiguous.

Although B* => B* and B* => B const* both have an Exact Match rank, the former is still the best conversion sequence for over.ics.rank / 3; this (for example) to provide:

 int f(const int *); int f(int *); int i; int j = f(&i); // calls f(int*) 

From over.ics.rank / 3:

The standard conversion sequence S1 is a better conversion sequence than the standard conversion sequence S2 if [...]
- S1 and S2 differ only in their qualification transformation and give similar types T1 and T2 (4.4), respectively, and the cv-qualification signature of type T1 is its own subset of the cv-qualification signature of type T2. [...]

And of course, unsigned int => unsigned int better than unsigned int => signed int . So, of the two overloads, one has a more efficient implicit conversion sequence for the first argument, and the second has a better implicit conversion sequence for the second argument. Therefore, they cannot be distinguished in the file over.match.best/1.

+7
source

Source: https://habr.com/ru/post/1201644/


All Articles