Reputation: 1135
I was studying about overloading and I am completely getting confused with promotions. I looked at few articles in SO (implicit conversion sequence in function overloading) and I am sure some more are available, but could not find the right article. I was also referring to http://www.dcs.bbk.ac.uk/~roger/cpp/week20.htm. I was looking at C++ Programming special edition by Stroustrup and came across following explanation.
Finding the right version to call from a set of overloaded functions is done by looking for a best match between the type of the argument expression and the parameters (formal arguments) of the functions. To approximate our notions of what is reasonable, a series of criteria are tried in order: 1 Exact match [2] Match using promotions; [3] Match using standard conversions [4] Match using user-defined conversions [5] Match using the ellipsis ......
void print(int);
void print(double);
void print(long);
void print(char);
void h(char c, int i, short s, float f)
{
print(s); // integral promotion: invoke print(int)
print(f); // float to double promotion: print(double)
}
I wrote below code. I was thinking that if I call the function with value of 1, func1(long) will be called because promotion takes place. But I get error message "error: call of overloaded 'func1(int)' is ambiguous". It is not calling the function with even unsigned char type of variable.
Also if I pass call func1(3.4f), func1(double) is called and promotion takes place as per my expectation. Why 1 is not promoted to long int but why float is promoted to double? What integer promotions takeplace?
void func1(unsigned char speed)
{
cout<<"Func1 with unsigned char: speed =" << speed <<" RPM\n";
}
void func1(long speed)
{
cout<<"Func1 with long Int: speed =" << speed <<" RPM\n";
}
void func1(double speed)
{
cout<<"Func1 with double: speed =" << speed <<" RPM\n";
}
int main(void)
{
func1(1);
func1(3.4f);
return(0);
}
Upvotes: 4
Views: 1377
Reputation: 1
Short answer: In most cases only conversions from types smaller then int to int, and float to double are considered "promotions", and thus are a better match then all other implicit conversions.
So counter intuitive - int to long or int to double or int to char - are all considered as matches of the same level and thus are ambiguous.
IMPORTANT: "promotion" in this context has a different meaning from "promotion rules" in discussing a mixed type arithmetic expression: (short)6+(float)78
Long answer: enums, modern char types (w_char, char8_t...) and bit fields have some exceptions to this rule, see the standard or https://en.cppreference.com/w/cpp/language/implicit_conversion the section about "Integral promotion"
Upvotes: -1
Reputation: 73366
The standard specifies:
[C++11: 4.13/1]:
("Integer conversion rank")Every integer type has an integer conversion rank defined as follows:
- [..]
- The rank of
long long int
shall be greater than the rank oflong int
, which shall be greater than the rank ofint
, which shall be greater than the rank ofshort int
, which shall be greater than the rank of signed char.- The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type.
- [..]
which calls for ambiguity in your example.
As for func1(3.4f);
, it's just a promotion from float to double, and that's the best match, since the other two overloaded methods have long
and unsigned char
.
Also check this table:
where a subclause specifies:
[conv.fpprom]:
(7.7 Floating-point promotion )
- A prvalue of type
float
can be converted to a prvalue of typedouble
. The value is unchanged.- This conversion is called floating-point promotion.
Upvotes: 2