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?
An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.
This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading. For example, we can overload an operator '+' in a class like String so that we can concatenate two strings by just using +.
Implicit type conversion also known as automatic type conversion is carried out by the compiler without the need for a user-initiated action. It takes place when an expression of more than one data type is present which in such an instance type conversion takes place to avoid data loss.
An overloaded operator is called an operator function. You declare an operator function with the keyword operator preceding the operator. Overloaded operators are distinct from overloaded functions, but like overloaded functions, they are distinguished by the number and types of operands used with the operator.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With