我对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的行为是错误的。)
我对这种行为有误解吗? (当然,我认为海湾合作委员会的行为更为可取。)
答案 0 :(得分:2)
你误解了这里发生的事情。
首先让我们通过将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*)
...
无法编译:
long double ipart;
正如您所看到的,编译器无法确定要调用的3个重载函数中的哪一个,因为它不知道您传递的参数中的哪一个。
那你为什么要编译?
检查您传递的第二个参数:指向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)
与new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}
进行比较。