Why is the implicit conversion of int
to int64_t
vs int
to double
ambiguous?
I would have thought the integral overload would have precedence over integral to floating point?
#include <stdint.h>
void foo(double) {}
void foo(int64_t) {}
int main()
{
foo(5);
return 0;
}
main.cpp: In function ‘int main()’: main.cpp:8:10: error: call of overloaded ‘foo(int)’ is ambiguous foo(5); ^ main.cpp:3:6: note: candidate: void foo(double) void foo(double) {} ^ main.cpp:4:6: note: candidate: void foo(int64_t) void foo(int64_t) {} ^
My environment is:
-std=c++14
)int64_t
is a long int
on my machine:
/usr/include/stdint.h
:
# if __WORDSIZE == 64
typedef long int int64_t;
# else
I have confirmed this with a static assert in my test app:
static_assert(__WORDSIZE == 64, "");
static_assert(std::is_same<int64_t, long int>::value, "");
My build flags are:
-std=c++14 -Werror -Wall -Wextra -m64 -msse2 -msse4.2 -mfpmath=sse
-ftemplate-depth-128 -Wno-unused-parameter -pthread -g -ggdb3 -O0 -fno-inline
In a 64-bit compile, int64_t is long int , not a long long int (obviously).
__int8, __int16, __int32, __int64 The __int8 data type is synonymous with type char , __int16 is synonymous with type short , and __int32 is synonymous with type int . The __int64 type is synonymous with type long long .
A long on some systems is 32 bits (same as an integer), the int64_t is defined as a 64 bit integer on all systems (otherwise known as a long long). Portability may be affected using long, but using int64_t looks like it was created to increase portability.
From [over.ics.user] table 12 we have
As you can see integer and floating point promotions have the same rank and integer and floating point conversions have the same rank.
Now we need to determine if 5 -> int64_t
is a integer promotion or conversion. If we check [conv.prom]/1 we find
A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.
The promotion stops at int
so we have to look at [conv.integral]/1 which is integer conversion and we have
A prvalue of an integer type can be converted to a prvalue of another integer type. A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
Which is what is going on. So 5 -> int64_t
is integer conversion and 5 -> double
is floating point conversion which are both ranked the same so the overload resolution is ambiguous.
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