为什么int
与int64_t
与int
的隐式转换为double
不明确?
我原以为整数重载优先于浮点积分?
#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) {} ^
我的环境是:
-std=c++14
) int64_t
在我的计算机上是long int
:
/usr/include/stdint.h
:
# if __WORDSIZE == 64
typedef long int int64_t;
# else
我已在我的测试应用程序中使用静态断言确认了这一点:
static_assert(__WORDSIZE == 64, "");
static_assert(std::is_same<int64_t, long int>::value, "");
我的构建标志是:
-std=c++14 -Werror -Wall -Wextra -m64 -msse2 -msse4.2 -mfpmath=sse
-ftemplate-depth-128 -Wno-unused-parameter -pthread -g -ggdb3 -O0 -fno-inline
答案 0 :(得分:10)
来自[over.ics.user]表12我们有
正如您所见,整数和浮点促销具有相同的排名和整数,浮点转换具有相同的排名。
现在我们需要确定5 -> int64_t
是否为整数提升或转化。如果我们检查[conv.prom] / 1,我们会找到
除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue,其整数转换等级(4.13)小于int的等级,如果int可以表示所有的值,则可以转换为int类型的prvalue。来源类型;否则,源prvalue可以转换为unsigned int类型的prvalue。
促销在int
停止,因此我们必须查看[conv.integral] / 1这是整数转换,我们有
整数类型的prvalue可以转换为另一个整数类型的prvalue。可以将未范围的枚举类型的prvalue转换为整数类型的prvalue。
这是怎么回事。所以5 -> int64_t
是整数转换,5 -> double
是浮点转换,两者的排名相同,因此重载分辨率不明确。
答案 1 :(得分:5)
我担心这真的归结为&#34; ,因为它是&#34;。
整数促销以int
结束;没有促销大于int
的类型。所以,你留下了两个标准的隐含转换,并且碰巧它们同样是很好的匹配。
[C++14: 4.5/1]:
整数转换级别(4.13)小于bool
,char16_t
,char32_t
或wchar_t
的整数类型的prvalue如果int
可以表示源类型的所有值,则int
的等级可以转换为int
类型的prvalue;否则,源prvalue可以转换为unsigned int
类型的prvalue。
[C++14: 4.5/7]:
这些转化称为整体促销。
[C++14: 5/10]:
[..] 此模式称为通常的算术转换,其定义如下:
- 如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果另一个操作数的类型不同,则表达式格式不正确。
- 如果任一操作数的类型为
long double
,则另一个操作数应转换为long double
。- 否则,如果任一操作数为
double
,则另一个操作数将转换为double
。- 否则,如果任一操作数为
float
,则另一个操作数将转换为浮动。- 否则,应在两个操作数上执行整体促销(4.5) [..]
也许,当long int
和long long int
的使用变得流行时(特别是通过cstdint
和朋友中的类型别名),可以修改标准以对这些类型引入整体促销。然后你的转换不会模棱两可。但是,许多现有代码也可能被破坏。
由于执行演员阵容是一个廉价的解决方案,我怀疑这被认为是值得的&#34;修复&#34;标准委员会。
也许有说服力的是,相对较新的固定宽度char
类型可以以这种方式推广:
[C++14: 4.5/2]:
类型char16_t
,char32_t
或wchar_t
(3.9.1)的prvalue可以转换为以下第一种类型的prvalue表示其基础类型的所有值:int
,unsigned int
,long int
,unsigned long int
,long long int
或unsigned long long int
。如果该列表中的任何类型都不能表示其基础类型的所有值,则可以将类型为char16_t
,char32_t
或wchar_t
的prvalue转换为其基础类型的prvalue
答案 2 :(得分:0)
编译器是正确的...默认情况下,您的数字文字5
的类型为int
...
要进行该函数调用,必须进行重载解析,这基本上会检查转换的可行性。请注意,这将是转换而不是促销的案例
现在,解释原因?我将引用cppreference的故事:(我知道,不是标准的替代品)
为overload resolution选择最佳可行功能:
如果隐含的话,F1被确定为比F2更好的功能 F1的所有参数的转换都不比隐含的更糟糕 F2和
的所有参数的转换
- 至少有一个F1的参数,其隐式转换优于该参数的相应隐式转换 F2
- 或,......
- 或,......
醇>
现在让我们看看隐含conversion sequence是什么:
隐式转换序列按以下顺序组成:
- 零个或一个标准转换序列;
- 。 。 。
醇>
现在,让我们看看standard conversion sequence是什么:
标准转换序列由以下内容组成 顺序:
- 零或一个左值变换;
- 零或一次数字促销或数字转换;
- 。 。 。
醇>
你有它,从这里开始参考NathanOliver's answer ..
中的表格答案 3 :(得分:0)
编译器具有int
-> double
和int
-> int64_t
的内置隐式转换。它不知道它需要使用哪个。
如果问题是在构造函数或类型转换运算符中发生的,则可以使用explicit
关键字来禁用歧义。然后,您将需要为要调用的类型编写不同的重载方法(它们大多在进行显式转换+包装)。
对于函数/方法,它要简单得多:如果您有不需要隐式转换的重载方法,则编译器会选择该方法。只需开发
void foo(int64_t) {}
问题解决了。