わかりやすく簡単にするために、次の数字を次のように短縮します。
−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 はこの型の定数を定義する方法を提供していないため、このデータ型のユーザー定義リテラル (生のリテラル) を実装しました: _u128
forunsigned __int128
および_i128
for __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 に追加のトリックを使用する必要があります。