模组的重载分辨率
Overload resolution of modf
我有一个关于modf
过载分辨率的问题。
请考虑下面的代码。
#include <iostream>
#include <iomanip>
#include <climits>
#include <cmath>
int main()
{
unsigned long ul = ULONG_MAX;
long double ipart;
long double fpart = std::modf(ul, &ipart);
std::cout << std::fixed << std::setprecision(0)
<< ul << ", " << ipart << ", " << fpart << 'n'
<< static_cast<double>(ul) << 'n';
}
在我的测试环境中,代码输出...
18446744073709551615, 18446744073709551615, 0
18446744073709551616
参看 http://melpon.org/wandbox/permlink/7ZF2CwqEwBRU5hg4
C++14 标准 26.8[c.math] p.11 说,
此外,还应有额外的超载,足以确保:
如果对应于
double
参数的任何算术参数具有类型long double
,则对应于double
参数有效地转换为long double
。否则,如果对应于
double
参数的任何算术参数具有类型double
或整数类型,则所有算术 与double
参数对应的参数有效地转换为double
.否则,与
double
参数对应的所有算术参数的类型均为float
。
变量ul
没有类型 long double
而是整数类型,所以我认为ul
应该转换为 double
,那么ipart
应该是18446744073709551616
。(也就是说,GCC的行为是错误的。
我对此行为有误解吗?(当然,我认为海湾合作委员会的行为更可取。
你误解了这里发生的事情。
首先,让我们检查ul
将被转换为什么,将其作为唯一的参数传递给std::modf
:
#include <iostream>
#include <iomanip>
#include <climits>
#include <cmath>
int main()
{
unsigned long ul = ULONG_MAX;
auto fpart = std::modf(ul, nullptr);
std::cout << std::fixed << std::setprecision(0)
<< ul << ", " << ipart;
}
这无法编译:
prog.cc:9:46: error: call of overloaded 'modf(long unsigned int&, std::nullptr_t)' is ambiguous
...
/usr/local/gcc-head/include/c++/7.0.0/cmath:376:3: note: candidate: float std::modf(float, float*)
...
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:116:1: note: candidate: double modf(double, double*)
...
/usr/local/gcc-head/include/c++/7.0.0/cmath:380:3: note: candidate: long double std::modf(long double, long double*)
...
如您所见,编译器无法决定调用 3 个重载函数中的哪一个,因为它不知道您想要从传递的参数中调用哪一个。
那你为什么要示例编译呢?
看看你通过的第二个参数表: 指向long double ipart;
的指针 .所以这是编译器可以使用的东西。
是否有任何函数将long double *
作为第二个参数?是的,有:
long double modf( long double x, long double* iptr );
所以你的代码在这里做的或多或少是这样的:
#include <iostream>
#include <iomanip>
#include <climits>
#include <cmath>
int main()
{
unsigned long ul = ULONG_MAX;
long double ipart;
long double fpart = std::modf(static_cast<long double>(ul), &ipart);
std::cout << std::fixed << std::setprecision(0)
<< ul << ", " << ipart << ", " << fpart << 'n'
<< static_cast<double>(ul) << 'n';
}
正如您现在所看到的,您正在将static_cast<long double>(ul)
与static_cast<double>(ul)
进行比较。
- C++ 重载分辨率和恒常性
- 模板和重载分辨率
- 为什么重载分辨率不选择模板函数的 std::vector 重载?
- 使用空大括号初始值设定项的重载分辨率:指针还是引用?
- 如何获取通过重载分辨率选择的函子签名
- 重载分辨率:是否首选直接转换运算符(由于复制省略)?
- 当参数不同时,重载分辨率不会选择模板
- 为什么下面的模板函数重载分辨率不明确
- 重载分辨率:调整 const/ref 是否不比用户定义的转换更好?
- 重载分辨率 C 样式字符串
- 具有引用限定符的模板方法的重载分辨率
- 具有自动功能的模板函数的重载分辨率
- 模板重载分辨率中的位字段
- 重载分辨率如何适用于 std::vector:<int>:insert
- 外部"C"和 "C++" 版本的 qsort()/bsearch() 上的重载分辨率
- 数组衰减为指针和重载分辨率
- 函数重载和类型转换分辨率
- 为什么重载分辨率不选择第一个函数?
- 从幻数到int或long的重载分辨率(范围为v3)
- 函数重载分辨率