2012-02-17 1 views
8

与えられたdouble/float変数が実際のビットパターン0x0を持っていることを確認したいと思います。理由を聞かないでください.Qt(qIsNull())の関数で、constexprになりたいと考えています。doubleのビットパターンをチェックする方法はC++ 11のconstexprでは0x0ですか?

元のコードは、労働組合を使用:

union { double d; int64_t i; } u; 
u.d = d; 
return u.i == 0; 

これは当然のconstexprとして動作しません。

次のtryはreinterpret_castしていました:

return *reinterpret_cast<int64_t*>(&d) == 0; 

しかし、それはGCC 4.7でconstexprとして働いている間、それは(、当然Bポインタ操作のC /)失敗したクラン3.1インチ

最終アイデアはAlexandrescuesqueを行って、これを行うことでした。

template <typename T1, typename T2> 
union Converter { 
    T1 t1; 
    T2 t2; 
    explicit constexpr Converter(T1 t1) : t1(t1) {} 
    constexpr operator T2() const { return t2; } 
}; 

// in qIsNull(): 
return Converter<double,int64_t>(d); 

をしかし、それはどちらか、クランのための十分な賢いではありません。

note: read of member 't2' of union with active member 't1' is not allowed in a constant expression 
constexpr operator T2() const { return t2; } 
            ^

誰が良いアイデアを持っていますか?

+1

私はまた、浮動小数点0を表す他のビットパターンがあると思い、あなたのドンこと見つけたくないのですか? –

+2

0を表す正確に2つのビットパターンがあります。それらは000 ... 000と100 ... 000です。最初のビットは符号ビットです。第2のビットパターンは、「負のゼロ」と呼ばれることもある。 – user763305

+2

おそらく 'return d == 0 && 1/d> 0;'? (http://en.wikipedia.org/wiki/Signed_zero#Comparisons) –

答えて

6

私は指定されたdouble/float型の変数は、実際のビットパターンは0x0

を持っていることを確認したい。しかし、それはだ場合constexprそれはどんな変数をチェックしていない、それはこのようをチェックしています変数は静的に保持されると決定されます。そういうわけで、あなたはポインターと組合のテクニックを引っ張ってはいけないのです。「公式には」指すメモリはありません。

あなたのような、あなたが何かを行うことができ、非トラッピングIEEEのゼロ除算を行うには、あなたの実装を説得することができた場合:

return (d == 0) && (1/d > 0) 

のみ+/-0が0 1/-0に等しいこと「にISNれ、-Infです0. 1/+0より大きいtは、+Infです。しかし、私はどのように非トラップ算術演算を起こさせるのか分かりません。

+0

デフォルトでは実装は通常非トラップではありませんか? –

+0

@Christian:GCCでバニラのコマンドラインオプションを使用する場合0で割ると浮動小数点エラーが発生します。 –

+0

Aha、Ok。ところで、私が正しく読むと、実際に ''(C++ 11/C99)の 'feholdecxept'を使って非トラップモードに入ることができます。そして彼はC++ 11を使っているので、これはあなたの答えに素敵な追加かもしれません(しかしこの場合は '#pragma STDC FENV_ACCESS ON'を忘れないでください)。 –

5

clang ++ 3.0とg ++ 4.7の両方(4.6ではなく)はstd::signbitconstexprとして扱います。

return x == 0 && std::signbit(x) == 0; 
+1

Clang 3.0は 'constexpr'を実装していませんか?とにかくC++ 11の[c.math]/11は、 'std :: signbit'が' constexpr'ではないことを明確に述べています:( –

4

定数式の中からdoubleの根底にあるビットパターンを見てすることはできません。 void*を介してキャスティングすることによってそのような検査を可能にしたC++ 11標準には欠陥があったが、それはC++ core issue 1312によって対処された。

clangのconstexprの実装(完全であると見なされる)には、定数doubleの値の表現を抽出するメカニズムがありません(非標準のベクトル演算以外では、現在でも結果を検査する)。

IEEE-754浮動小数点を使用するプラットフォームをターゲットにしていることが分かっている場合は、0x0が値の正のゼロに対応しています。私が打ち鳴らすとG ++の両方に定数式内部で動作これを検出する唯一の方法は、__builtin_copysignを使用することであると信じて:

constexpr bool isPosZero(double d) { 
    return d == 0.0 && __builtin_copysign(1.0, d) == 1.0; 
} 
関連する問題