2016-11-07 40 views
2

我有一个关于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说,

此外,存在应足以确保附加重载:

  1. 如果任何算术参数对应到double参数的类型为long double,则对应于 double参数的所有算术参数被有效地转换为long double

  2. 否则,如果对应于double参数的任何算术参数的类型为double或整数类型,则对应于double参数所有算术 参数被有效地转换为 double

  3. 否则,对应于double参数的所有算术参数的类型为float

变量ul没有类型long double但整数类型,所以我觉得应该ul被转换为 double,然后ipart应该是18446744073709551616。 (也就是说,海湾合作委员会的行为是错误的。)

我对这种行为有误解吗? (当然,我认为海湾合作委员会的行为更可取。)

+0

你正在调用'std :: modf'的long double变体,但是你的静态转换只能用'double'完成。 “所以我认为ul应该被翻倍”:你错了,'ul'被转换成'long double' –

回答

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*) 
... 

,你可以请参阅编译器无法确定要调用的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<double>(ul)比较static_cast<long double>(ul)

+0

http://melpon.org/wandbox/permlink/NaNEoaHx1PVHQ5mV –

+0

我知道为什么我的样本表现如上,我知道libstdC++没有额外的重载对应于26.8 [c.math] p.11(我看到了cmath头文件)。 我的问题是为什么libstdC++没有额外的重载对应于26.8 [c.math] p.11。 –

+0

@MitsuruKariya你在说什么超负荷?每种情况都有3种重载。你只是假设错了。 –