次の方法で共有


SafeInt クラス

整数プリミティブを拡張して、整数オーバーフローを防止すると共に、異なる型の整数を比較できるようにします。

template<typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY>
class SafeInt;

パラメーター

テンプレート

Description

T

SafeInt によって置き換えられる整数パラメーターまたはブール値パラメーターの型。

E

エラー処理ポリシーを定義する列挙型。

U

2 番目のオペランドの整数パラメーターまたはブール値パラメーターの型。

パラメーター

Description

[入力] rhs

複数のスタンドアロン関数で演算子の右側の値を表す入力パラメーター。

[入力] i

複数のスタンドアロン関数で演算子の右側の値を表す入力パラメーター。

[入力] bits

複数のスタンドアロン関数で演算子の右側の値を表す入力パラメーター。

メンバー

Dd570021.collapse_all(ja-jp,VS.110).gifパブリック コンストラクター

名前

Description

SafeInt::SafeInt

既定のコンストラクターです。

Dd570021.collapse_all(ja-jp,VS.110).gif代入演算子

名前

構文

=

template<typename U>

SafeInt<T,E>& operator= (const U& rhs)

=

SafeInt<T,E>& operator= (const T& rhs) throw()

=

template<typename U>

SafeInt<T,E>& operator= (const SafeInt<U, E>& rhs)

=

SafeInt<T,E>& operator= (const SafeInt<T,E>& rhs) throw()

Dd570021.collapse_all(ja-jp,VS.110).gifキャスト演算子

名前

構文

bool

operator bool() throw()

char

operator char() const

signed char

operator signed char() const

unsigned char

operator unsigned char() const

__int16

operator __int16() const

unsigned __int16

operator unsigned __int16() const

__int32

operator __int32() const

unsigned __int32

operator unsigned __int32() const

long

operator long() const

unsigned long

operator unsigned long() const

__int64

operator __int64() const

unsigned __int64

operator unsigned __int64() const

wchar_t

operator wchar_t() const

Dd570021.collapse_all(ja-jp,VS.110).gif比較演算子

名前

構文

<

template<typename U>

bool operator< (U rhs) const throw()

<

bool operator< (SafeInt<T,E> rhs) const throw()

>=

template<typename U>

bool operator>= (U rhs) const throw()

>=

Bool operator>= (SafeInt<T,E> rhs) const throw()

>

template<typename U>

bool operator> (U rhs) const throw()

>

Bool operator> (SafeInt<T,E> rhs) const throw()

<=

template<typename U>

bool operator<= (U rhs) const throw()

<=

bool operator<= (SafeInt<T,E> rhs) const throw()

==

template<typename U>

bool operator== (U rhs) const throw()

==

bool operator== (bool rhs) const throw()

==

bool operator== (SafeInt<T,E> rhs) const throw()

!=

template<typename U>

bool operator!= (U rhs) const throw()

!=

bool operator!= (bool b) const throw()

!=

bool operator!= (SafeInt<T,E> rhs) const throw()

Dd570021.collapse_all(ja-jp,VS.110).gif算術演算子

名前

構文

+

const SafeInt<T,E>& operator+ () const throw()

-

SafeInt<T,E> operator- () const

++

SafeInt<T,E>& operator++ ()

--

SafeInt<T,E>& operator-- ()

%

template<typename U>

SafeInt<T,E> operator% (U rhs) const

%

SafeInt<T,E> operator% (SafeInt<T,E> rhs) const

%=

template<typename U>

SafeInt<T,E>& operator%= (U rhs)

%=

template<typename U>

SafeInt<T,E>& operator%= (SafeInt<U, E> rhs)

*

template<typename U>

SafeInt<T,E> operator* (U rhs) const

*

SafeInt<T,E> operator* (SafeInt<T,E> rhs) const

*=

SafeInt<T,E>& operator*= (SafeInt<T,E> rhs)

*=

template<typename U>

SafeInt<T,E>& operator*= (U rhs)

*=

template<typename U>

SafeInt<T,E>& operator*= (SafeInt<U, E> rhs)

/

template<typename U>

SafeInt<T,E> operator/ (U rhs) const

/

SafeInt<T,E> operator/ (SafeInt<T,E> rhs ) const

/=

SafeInt<T,E>& operator/= (SafeInt<T,E> i)

/=

template<typename U>

SafeInt<T,E>& operator/= (U i)

/=

template<typename U>

SafeInt<T,E>& operator/= (SafeInt<U, E> i)

+

SafeInt<T,E> operator+ (SafeInt<T,E> rhs) const

+

template<typename U>

SafeInt<T,E> operator+ (U rhs) const

+=

SafeInt<T,E>& operator+= (SafeInt<T,E> rhs)

+=

template<typename U>

SafeInt<T,E>& operator+= (U rhs)

+=

template<typename U>

SafeInt<T,E>& operator+= (SafeInt<U, E> rhs)

-

template<typename U>

SafeInt<T,E> operator- (U rhs) const

-

SafeInt<T,E> operator- (SafeInt<T,E> rhs) const

-=

SafeInt<T,E>& operator-= (SafeInt<T,E> rhs)

-=

template<typename U>

SafeInt<T,E>& operator-= (U rhs)

-=

template<typename U>

SafeInt<T,E>& operator-= (SafeInt<U, E> rhs)

Dd570021.collapse_all(ja-jp,VS.110).gif論理演算子

名前

構文

!

bool operator !() const throw()

~

SafeInt<T,E> operator~ () const throw()

<<

template<typename U>

SafeInt<T,E> operator<< (U bits) const throw()

<<

template<typename U>

SafeInt<T,E> operator<< (SafeInt<U, E> bits) const throw()

<<=

template<typename U>

SafeInt<T,E>& operator<<= (U bits) throw()

<<=

template<typename U>

SafeInt<T,E>& operator<<= (SafeInt<U, E> bits) throw()

>>

template<typename U>

SafeInt<T,E> operator>> (U bits) const throw()

>>

template<typename U>

SafeInt<T,E> operator>> (SafeInt<U, E> bits) const throw()

>>=

template<typename U>

SafeInt<T,E>& operator>>= (U bits) throw()

>>=

template<typename U>

SafeInt<T,E>& operator>>= (SafeInt<U, E> bits) throw()

&

SafeInt<T,E> operator& (SafeInt<T,E> rhs) const throw()

&

template<typename U>

SafeInt<T,E> operator& (U rhs) const throw()

&=

SafeInt<T,E>& operator&= (SafeInt<T,E> rhs) throw()

&=

template<typename U>

SafeInt<T,E>& operator&= (U rhs) throw()

&=

template<typename U>

SafeInt<T,E>& operator&= (SafeInt<U, E> rhs) throw()

^

SafeInt<T,E> operator^ (SafeInt<T,E> rhs) const throw()

^

template<typename U>

SafeInt<T,E> operator^ (U rhs) const throw()

^=

SafeInt<T,E>& operator^= (SafeInt<T,E> rhs) throw()

^=

template<typename U>

SafeInt<T,E>& operator^= (U rhs) throw()

^=

template<typename U>

SafeInt<T,E>& operator^= (SafeInt<U, E> rhs) throw()

|

SafeInt<T,E> operator| (SafeInt<T,E> rhs) const throw()

|

template<typename U>

SafeInt<T,E> operator| (U rhs) const throw()

|=

SafeInt<T,E>& operator|= (SafeInt<T,E> rhs) throw()

|=

template<typename U>

SafeInt<T,E>& operator|= (U rhs) throw()

|=

template<typename U>

SafeInt<T,E>& operator|= (SafeInt<U, E> rhs) throw()

解説

SafeInt クラスを使用することで、数値演算での整数オーバーフローを防止できます。たとえば、2 つの 8 ビット整数を加算するとします。一方の整数の値が 200、もう一方の整数の値が 100 です。正しい数値演算は 200 + 100 = 300 です。ところが、8 ビット整数の制限により上位ビットが削除されるため、コンパイラが返す結果は 44 (300 - 28) になります。この数式に依存する演算を使用した場合、常に予期しない動作が発生します。

SafeInt クラスは、算術オーバーフローが発生するかどうか、またはコードで 0 除算が試行されるかどうかを検証します。どちらの場合においても、このクラスは、エラー ハンドラーを呼び出し、問題が発生する可能性があることをプログラムに警告します。

また、このクラスを使用することで、型の異なる 2 つの整数が SafeInt オブジェクトである限り、その 2 つの整数を比較することができます。通常、比較を行う際には、最初に数値を同じ型に変換する必要があります。多くの場合、ある数値を別の型の数値と比較する際、データの損失がないかどうかを確認する必要があります。

このトピックの演算子の一覧に、SafeInt クラスでサポートされる数値演算子と比較演算子を示しています。ほとんどの数値演算子は、T 型の SafeInt オブジェクトを返します。

SafeInt と整数型の比較演算は、どちらの方向にも実行することができます。たとえば、SafeInt<int>(x) < y と y > SafeInt<int>(x) はどちらも有効であり、同じ結果が返されます。

2 つの異なる SafeInt 型を使用することは、ほとんどの二項演算子においてサポートされていません。この例の 1 つとして、& 演算子があります。SafeInt<T, E> & int はサポートされていますが、SafeInt<T, E> & SafeInt<U, E> はサポートされていません。2 番目の例の場合、コンパイラが返されるパラメーターの型を判別できないためです。この問題を解決する方法の 1 つとして、2 番目のパラメーターを基本型にキャストできます。同じパラメーターを使用してこれを行うには、SafeInt<T, E> & (U)SafeInt<U, E> を使用します。

[!メモ]

ビットごとの演算を実行するには、2 つの異なるパラメーターのサイズが同じであることが必要です。サイズが異なる場合、コンパイラは ASSERT (MFC) 例外をスローします。この演算の結果は、正確性が保証されません。この問題を解決するには、小さい方のパラメーターが大きい方のパラメーターと同じサイズになるまで、小さい方のパラメーターをキャストします。

シフト演算子の場合、テンプレートの型に存在するビットよりも多くのビットをシフトすると、ASSERT 例外がスローされます。リリース モードでは、これによる影響はありません。シフト演算子の場合、戻り値の型が元の型と同じであるため、2 種類の型の SafeInt パラメーターを組み合わせることができます。演算子の右側の数値は、シフトするビット数を示すのみです。

SafeInt オブジェクトで論理比較を実行するとき、厳密に算術的な比較が実行されます。たとえば、次の式について考えてみます。

  • SafeInt<uint>((uint)~0) > -1

  • ((uint)~0) > -1

1 番目のステートメントは true に解決されますが、2 番目のステートメントは false に解決されます。0 のビットごとの否定は 0xFFFFFFFF です。2 番目のステートメントでは、既定の比較演算子により 0xFFFFFFFF と 0xFFFFFFFF が比較され、この 2 つが等しいと判断されます。SafeInt クラスの比較演算子によって、1 番目のパラメーターが符号なしであるのに対し、2 番目のパラメーターが負の値であることが判明します。そのため、ビット表現が同一であっても、SafeInt の論理演算子によって、符号なし整数が -1 より大きいことがわかります。

SafeInt クラスを ?: 三項演算子と同時に使用する際には注意が必要です。次のコード行があるとします。

Int x = flag ? SafeInt<unsigned int>(y) : -1;

コンパイラはこのコード行を次のように変換します。

Int x = flag ? SafeInt<unsigned int>(y) : SafeInt<unsigned int>(-1);

flag が false の場合、コンパイラは x に値 -1 を代入する代わりに例外をスローします。このような動作を回避するための正しいコードは次のとおりです。

Int x = flag ? (int) SafeInt<unsigned int>(y) : -1;

T と U には、ブール型、文字型、または整数型を割り当てることができます。整数型は、signed 型であるか unsigned 型であるかを問わず、8 ~ 64 ビットまでの任意のサイズに設定できます。

[!メモ]

SafeInt クラスでは任意の種類の整数を使用できますが、unsigned 型の方が効率的に実行できます。

E は、SafeInt で使用されるエラー処理機能です。SafeInt ライブラリには 2 つのエラー処理機能が用意されています。既定のポリシーは SafeIntErrorPolicy_SafeIntException であり、エラー発生時に SafeIntException クラス例外をスローします。もう一方のポリシーは SafeIntErrorPolicy_InvalidParameter であり、エラー発生時にプログラムを停止します。

エラー ポリシーをカスタマイズする方法は、2 つあります。1 つは、SafeInt を作成する際に E パラメーターを設定する方法です。この方法は、1 つの SafeInt のみに対してエラー処理ポリシーを変更する場合に使用します。もう 1 つは、SafeInt ライブラリを含める前に、カスタマイズしたエラー処理クラスとして _SAFEINT_DEFAULT_ERROR_POLICY を定義する方法です。この方法は、コード内のすべての SafeInt クラス インスタンスに対して既定のエラー処理ポリシーを変更する場合に使用します。

[!メモ]

SafeInt ライブラリのエラーを処理するカスタマイズ クラスがエラー ハンドラーを呼び出したコードに制御を返さないようにしてください。エラー ハンドラーが呼び出された後では、SafeInt 操作の結果は信頼できません。

必要条件

ヘッダー: safeint.h

名前空間: msl::utilities

参照

関連項目

SafeIntException クラス

その他の技術情報

その他のサポート ライブラリのクラス

SafeInt ライブラリ