更新 2
这个问题与一个完全相同的副本合并,看看这个,实际答案比任何人最初想象的要简单得多。当前版本的std_lib_facilities.h包括以下行:
inline double sqrt(int x) { return sqrt(double(x)); } // to match C++0x
它为int情况创建了一个特定的重载,以匹配现代编译器应该执行的操作,将整数参数转换为 double,尽管此版本并未涵盖所有情况。
如果未使用std_lib_facilities.h,则原始逻辑仍然适用,尽管与原始问题中的Visual Studio 2012gcc-4.2
相比相当旧,但有一个版本专门用于整数情况。4.1.2
__builtin_sqrt
原来的
自2005年左右以来,标准草案要求将整数参数强制转换为double,这在草案 C++ 标准中有所介绍。如果我们查看26
Numerics 库部分,然后转到包含标题的 C 部分库26.8
,它指定了第8段中涵盖的float、double和long double<cmath>
的数学函数的重载:
除了 中数学函数的 double 版本外,C++ 还添加了这些函数的 float 和 long double 重载版本,具有相同的语义。
这将ambiguous
适用于这种int
情况,但标准要求提供足够的重载,以便将整数参数强制转换为double。它包含在第11段中,它说(强调我的):
此外,应有足够的额外过载以确保:
- 如果对应于 double 参数的任何算术参数的类型为 long double,则对应于 double 参数的所有算术参数都将有效地强制转换为 long double。
- 否则,如果对应于 double 参数的任何算术参数具有 double 类型或整数类型,则对应于 double 参数的所有算术参数都将有效地转换为 double。
- 否则,对应于双参数的所有算术参数都具有浮点类型。
更新
正如@nos 指出的那样,sqrt
被调用的版本可能来自math.h
标头而不是重载 from cmath
,如果是这种情况并且这里可能有实现定义的警告,那么我们可能会恢复到旧的C 样式行为,如果唯一可用的版本sqrt(double)
意味着int将被隐式转换为 double。
我发现对此进行测试的一种方法gcc
是clang
使用long类型,如果我们只有可用的情况下,a
该类型与标志一起触发在我的平台上可能改变值的转换的警告。事实上,如果我包含而不是我们可以产生这个警告。虽然我无法在clang中触发这种行为,这似乎表明这是依赖于实现的。-Wconversion
sqrt(double)
math.h
cmath