Why is this function call ambiguous?
Asked Answered
G

1

32

I'm reading the standard and trying to figure out why this code won't be resolved without a cast.

void foo(char c) { }

// Way bigger than char
void foo(unsigned long int) { }

int main()
{
   foo(123456789); // ambiguous
   foo((unsigned long int) 123456789); // works
}

Here's what it says:

4.13 Integer conversion rank [conv.rank]

Every integer type has an integer conversion rank defined as follows:

— The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type.

— The rank of char shall equal the rank of signed char and unsigned char.

In particular, what rustles my jimmies is that it doesn't say ANY unsigned integral type, just unsigned char. My guess is that char is being promoted to an unsigned type via conversion. Is this true?

Goebbels answered 24/9, 2014 at 7:16 Comment(6)
Perhaps 123456789U would do it for you.Ragged
"In particular, what rustles my jimmies is that it doesn't say ANY unsigned integral type, just unsigned char. My guess is that char is being promoted to an unsigned type via conversion. Is this true?" - I'd hazard that you're misunderstanding the significance of 4.13 in the Standard... char is not being promoted to unsigned... the issue is as AndreyT says - that 123456789 is an int and it's not clearly better to truncate it as a char or pass it as an unsigned long (long would be just as bad - unsigned is not significant here).Clathrate
Despite the name, the "integer conversion rank" isn't actually used to rank integer conversions during overload resolution.Trait
Neither conversion is safe -- one is signed to unsigned and the other is larger type to smaller type -- so why should one unsafe operation win over the other?Villeinage
+1 For "rustles my jimmies"Deaconess
"it doesn't say ANY unsigned integral type, just unsigned char" - what part are you referring to? In what you quoted I don't see anything that would give any exclusive treatment to unsigned char.Teide
T
52

It has little to do with rank of the type defined in 4.13. 4.13 defined internal rankings used to describe integral promotions and usual arithmetic conversions. They by itself do not directly affect overload resolution. Rankings relevant to overload resolution are defined in "13.3.3.1.1 Standard conversion sequences" and then used in "13.3.3.2 Ranking implicit conversion sequences".

So, it is about rank of the conversion as defined under 13.3. 123456789 is an integer literal of type int on your platform. This means that calling both char and unsigned long versions of your function requires an implicit conversion from int to char or from int to unsigned long. In both cases we have conversions of "integral conversion" type. That means that both functions are equally "bad" in this case. Hence the ambiguity.

If one of these functions required a mere integral promotion (as opposed to integral conversion), it would win the resolution and the call would be considered unambiguous. But alas both of your functions require integral conversions.

Teide answered 24/9, 2014 at 7:32 Comment(1)
Or, another way of looking at it: the function call overload doesn't distinguish between 123456789 and -123456789, both are ints. Converting -123456789 to unsigned long could lose data: so in general, a conversion from int to unsigned long could lose data. The same is true of char. Now, with the specific constant of 123456789 you can prove that it won't be lost, but the overload rules do not take that into account: the type of 123456789 is int on your system, so int is used to do overload resolution.Loment

© 2022 - 2024 — McMap. All rights reserved.