9

特定の double/float 変数に実際のビット パターン 0x0 があることを確認したいと考えています。qIsNull()理由は聞かないでください。私がしたいQt () の関数で使用されていますconstexpr

元のコードでは共用体を使用していました:

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

constexprこれは当然のこととして機能しません。

次の試みは次のとおりでしたreinterpret_cast

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

しかしconstexpr、それは GCC 4.7 では a として機能しますが、Clang 3.1 では失敗します (当然のことながら、ポインター操作の b/c)。

最終的なアイデアは、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);

しかし、それは Clang にとっても十分に賢明ではありません。

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

他の誰かが良い考えを持っていますか?

4

3 に答える 3

6

特定の double/float 変数に実際のビット パターン 0x0 があることを確認したい

しかし、それが変数constexprをチェックしていない場合は、この変数が保持すると静的に決定されているをチェックしています。そのため、「公式に」ポイントするメモリはありません。

非トラップ IEEE ゼロ除算を行うように実装を説得できる場合は、次のようなことができます。

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

のみ+/-0が 01/-0です-Inf。0 より大きくない1/+0is+Infです。しかし、その非トラップ演算を実現する方法がわかりません。

于 2012-02-17T13:49:08.990 に答える
5

clang++ 3.0 と g++ 4.7 (4.6 ではない) の両方が として扱うstd::signbitようconstexprです。

return x == 0 && std::signbit(x) == 0;
于 2012-02-17T13:54:31.500 に答える
4

double定数式内の fromの基になるビット パターンを調べることはできません。C++11 標準には、 を介してキャストすることでそのような検査を許可する欠陥がありましたが、これはC++ コアの問題 1312void*によって対処されました。

「証明」として、clang のconstexpr実装 (これは完全であると見なされます) には、定double数値の表現を抽出するためのメカニズムがありません (非標準のベクトル演算を使用する場合を除き、その場合でも結果を検査する方法は現在ありません)。

他の人が示唆しているように、IEEE-754 浮動小数点を使用するプラットフォームをターゲットにすることがわかっている場合は、0x0正のゼロの値に対応します。これを検出する唯一の方法は、clang と g++ の両方で定数式内で機能するものであり、次を使用することだと思います__builtin_copysign

constexpr bool isPosZero(double d) {
  return d == 0.0 && __builtin_copysign(1.0, d) == 1.0;
}
于 2012-03-02T06:06:05.387 に答える