2016-11-07 71 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種重載。你只是假設錯了。 –