2016-11-07 14 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 

参照

  1. 任意演算の引数が対応する場合:http://melpon.org/wandbox/permlink/7ZF2CwqEwBRU5hg4

    C++ 14標準26.8 [c.math] P.11は

    はまた、確実にするのに十分な追加の過負荷が存在しなければならない、と言いますdoubleパラメータがタイプlong doubleである場合、 doubleパラメータに対応するすべての算術引数は、long doubleに効果的にキャストされます。

  2. そうでない場合、doubleパラメータに対応する任意の演算の引数がdoubleまたは整数型の型を持つ、次いでdoubleパラメータに対応するすべての算術 引数が有効 doubleにキャストされた場合。

  3. それ以外の場合、doubleパラメータに対応する算術引数はすべてfloatです。

変数ul

はタイプ long doubleが、整数型を持っていないので、私は、その後、 ipart18446744073709551616でなければなりません uldoubleにキャストされるべきだと思います。 (つまり、GCCの動作が間違っています)

この現象について誤解がありますか? (もちろん、GCCの動作がより好ましいと思います)

+0

'std :: modf'の' long double'バリアントを呼び出していますが、静的キャストは 'double'でのみ行われます。 "ulは二重にキャストされるべきだと思う":あなたは間違っている、 'ul'は' long double'にキャストされる –

答えて

2

あなたはここで何が起こっているのか誤解しています。すべての

まず者はstd::modfに唯一のパラメータとして渡すことでulは、にキャストするために何が起こっているかチェックしてみましょう:

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

することができますように:

#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; 
} 

これはコンパイルに失敗しましたコンパイラは3つのオーバーロードされた関数のうちどれを呼び出すかを決めることはできません。渡すパラメータからどの関数が必要かを知ることはできません。

なぜ、コンパイルの例がありますか?

パスした2番目の検量線を確認してください:long double ipart;へのポインタ。 これは、コンパイラが処理できるものです。

long double *を2番目のパラメータとする関数はありますか?はい、あります:

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つの場合それぞれ3つの過負荷があります。あなたは間違ったものを前提にしています。 –

関連する問題