Reputation: 2907
So, I wrote something like this
#include <iostream>
using namespace std;
void f(int32_t i)
{
cout << "int32: " << i << endl;
}
void f(int16_t i)
{
cout << "int16: " << i << endl;
}
void f(int8_t i)
{
cout << "int8: " << i << endl;
}
void f(uint32_t i)
{
cout << "uint32: " << i << endl;
}
void f(uint16_t i)
{
cout << "uint16: " << i << endl;
}
int main() {
uint8_t i = 0u;
f(i);
return 0;
}
And it printed
int32: 0
I'm a bit confused:
Is this well-defined behaviour, or is it implementation specific?
What are the rules that determine which overload is used here and to what type the variable is converted?
Upvotes: 17
Views: 1301
Reputation: 2406
The behavior is well-defined, but implementation-specific. With a 16-bit int
it would have been different.
The particular rules in the standard are:
[over.best.ics] for overload resolution. [conv.prom] for integral promotion.
Upvotes: 9
Reputation: 72311
In comparing the conversions needed by different overloaded functions, a "promotion" is considered a better conversion sequence than a standard "conversion". Every arithmetic type can promote to at most one other type. (Promotions are also used when passing an argument to a C-style variadic function like printf
. The unary +
operator can be used to force a promotion of an arithmetic expression, like +n
.)
For integer types which are not character types or bool
, the promoted type is:
int
can represent all the values of the original type, then int
;unsigned int
can represent all the values of the original type, then unsigned int
;In your example, when comparing the overloaded functions, an "exact match" would be best, but there is no function taking exactly int8_t
(or int8_t&
or const int8_t&
). The promoted type of uint8_t
is int
, since it's required to support a range much larger than 0-255. And apparently on your system, int32_t
is an alias for int
, so the function void f(int32_t);
requires only a promotion on the argument. The other functions are all viable, but require an integer conversion on the argument. So void f(int32_t);
is considered the best overload.
So the technical answer to the question is that it is implementation specific, but only because of the relationship between int
and the <cstdint>
types, not because of the overload resolution rules.
Upvotes: 22