Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overload ambiguous (int -> int64_t vs int -> double)

Tags:

c++

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:

  • x86_64
  • g++-5.4 (with -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
like image 404
Steve Lorimer Avatar asked Aug 04 '16 16:08

Steve Lorimer


People also ask

Is int64_t same as long long int?

In a 64-bit compile, int64_t is long int , not a long long int (obviously).

Is int64 a long C++?

__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 .

What is int64_t data type in C++?

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.


1 Answers

From [over.ics.user] table 12 we have

enter image description here

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.

like image 71
NathanOliver Avatar answered Oct 29 '22 18:10

NathanOliver