7

わかりやすく簡単にするために、次の数字を次のように短縮します。

  • −170,141,183,460,469,231,731,687,303,715,884,105,728なので-170…728
  • 170,141,183,460,469,231,731,687,303,715,884,105,727なので170…727

これらの数値は、128 ビットの符号付き整数 ( の __int128 gcc) の最小値と最大値を表します。

gcc はこの型の定数を定義する方法を提供していないため、このデータ型のユーザー定義リテラル (生のリテラル) を実装しました: _u128forunsigned __int128および_i128for __int128

マイナス文字は UDL の一部ではありませんが、UDL の結果に適用される単項マイナス演算子です。

したがって、a -ddddd_i128(ここでdは数字) の場合、UDL は符号 __int128付きの正の値を計算しddddd、コンパイラはそれに単項マイナス演算子を適用します。ここまでは順調ですね。

問題は-170…128_i128(これは の有効な値である必要があります__int128) にあります:
UDLは の範囲外の符号付き __int128正数を計算し、未定義の動作 (符号付き整数のオーバーフロー) を引き起こします。170…128__int128

この数値定数を UDL で表す解決策はありますか?


私のUDLは宣言されています(今のところ、非constexprのループバージョンです)(生のリテラルです):

unsigned __int128 operator"" _u128(char const *str);
__int128 operator"" _i128(char const *str);

いくつかの使用法:

  1000000000000000000000000000000000_i128
  -1000000000000000000000000000000000_i128
  -170141183460469231731687303715884105728_i128 // <-- this has UB
  170141183460469231731687303715884105727_u128
  340282366920938463463374607431768211455_u128

ビットシフト、数学演算など、さまざまな方法で定数を定義する方法があることは知っていますが-170…728、一貫した方法で作成できるようにしたいです。たとえば、この状況は望ましくありません。次を使用して任意の定数を作成できますを除いて-170…728_i128、この UDL に追加のトリックを使用する必要があります。

4

1 に答える 1

6

これは基本的に、実装者が を実装するときに直面する問題と同じです<limits.h>INT_MIN(典型的な 32 ビット システムでは) を として定義できません-2147483648。代わりにとして定義することができます (そして一般的に定義されています) (-2147483647 - 1)。同様のことを行う必要があります。最も負の数を単一の否定演算子とリテラルで表現する方法はないかもしれませんが、それは問題ありません。単純にその必要がないからです。

于 2014-08-05T18:59:43.900 に答える