Classe SafeInt
Estende le primitive Integer per impedire un overflow di Integer e consente di confrontare tipi diversi di Integer.
template<typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY>
class SafeInt;
Parametri
Modello |
Descrizione |
---|---|
T |
Il tipo di parametro Integer o booleano che SafeInt sostituisce. |
E |
Un tipo di dati enumerato che definisce i criteri di gestione degli errori. |
U |
Il tipo di parametro Integer o booleano per l'operando secondario. |
Parametro |
Descrizione |
---|---|
[in] rhs |
Un parametro di input che rappresenta il valore a destra dell'operatore in diverse funzioni autonome. |
[in] i |
Un parametro di input che rappresenta il valore a destra dell'operatore in diverse funzioni autonome. |
[in] bit |
Un parametro di input che rappresenta il valore a destra dell'operatore in diverse funzioni autonome. |
Membri
Costruttori pubblici
Nome |
Descrizione |
---|---|
Costruttore predefinito. |
Operatori di assegnazione
Nome |
Sintassi |
---|---|
= |
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() |
Operatori di cast
Nome |
Sintassi |
---|---|
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 |
Operatori di confronto
Nome |
Sintassi |
---|---|
< |
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() |
Operatori aritmetici
Nome |
Sintassi |
---|---|
+ |
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) |
Operatori logici
Nome |
Sintassi |
---|---|
! |
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() |
Note
La classe di SafeInt protegge dall'overflow di Integer nelle operazioni matematiche.Ad esempio, considerare la possibilità di aggiungere due Integer a 8 bit: uno con un valore di 200 e il secondo è un valore di 100.Un'operazione matematica corretta sarebbe 200 + 100 = 300.Tuttavia, a causa del limite Integer a 8 bit, il bit superiore andrà perduto e il compilatore restituirà 44 (da 300 a 28) del risultato.Qualsiasi operazione che dipende da questa equazione matematica genererà un comportamento imprevisto.
La classe di SafeInt controlla se un overflow si verifichi o se il codice tenta di dividere per zero.In entrambi i casi, la classe chiama il gestore degli errori per avvisare il programma del potenziale problema.
Questa classe consente di confrontare due tipi diversi di Integer purché siano oggetti di SafeInt .In genere, quando si esegue un confronto, è necessario innanzitutto convertire numeri dello stesso tipo.Eseguire il cast di un numero in un altro tipo richiede spesso i controlli di assicurarsi che non vengano perdita di dati.
Il piano degli operatori in questo argomento vengono elencati i matematico e gli operatori di confronto supportati da SafeInt la classe.La maggior parte degli operatori matematici restituiscono un oggetto di SafeInt di tipo T.
Le operazioni di confronto tra SafeInt e un tipo integrale possono essere eseguite in entrambe le direzioni.Ad esempio, sia SafeInt<int>(x) < y che y > SafeInt<int>(x) sono validi e restituiscono lo stesso risultato.
Molti operatori binari non supportano l'utilizzo di due tipi diversi di SafeInt .Un esempio è l'operatore di & .SafeInt<T, E> & int è supportato, ma SafeInt<T, E> & SafeInt<U, E> non è.Nell'esempio precedente, il compilatore non riconosce il tipo di parametro da restituire.Una soluzione a questo problema consiste nell'eseguire il cast del secondo parametro del tipo di base.Utilizzando gli stessi parametri, questa operazione può essere eseguita con SafeInt<T, E> & (U)SafeInt<U, E>.
[!NOTA]
Per tutte le operazioni bit per bit, i due parametri diversi devono essere la stessa dimensione.Se le dimensioni sono diversi, il compilatore genererà un'eccezione di ASSERT (MFC) .I risultati di questa operazione non possono essere garantiti per essere precisi.Per risolvere questo problema, eseguire il cast del più piccolo parametro che sia la stessa dimensione del più ampio parametro.
Per gli operatori di spostamento, scorrendo più bit che esistere per il tipo di modello genera un'eccezione ASSERT.Ciò non avrà alcun effetto in modalità di rilascio.Combinare due tipi di parametri SafeInt è possibile che gli operatori di spostamento poiché il tipo restituito corrisponde al tipo originale.Il numero sul lato destro dell'operatore indica solo il numero di bit allo spostamento.
Quando si esegue un confronto logico con un oggetto SafeInt, il confronto è strettamente aritmetico.Ad esempio, considerare queste espressioni:
SafeInt<uint>((uint)~0) > -1
((uint)~0) > -1
Le prime risoluzioni di istruzione a true, mentre nel secondo viene risolto in un'istruzione a false.La negazione bit per bit di 0 è 0xFFFFFFFF.Nella seconda istruzione, l'operatore di confronto predefinito confronta 0xFFFFFFFF a 0xFFFFFFFF e vengono considerate uguali.L'operatore di confronto per la classe di SafeInt tenere presente che il secondo parametro è negativo come primo parametro è senza segno.Pertanto, sebbene la rappresentazione di bit saranno identiche, l'operatore logico di SafeInt tenere presente che l'Unsigned Integer è maggiore di -1.
Prestare attenzione quando si utilizza la classe di SafeInt con l'operatore ternario di ?: .Si consideri la seguente riga di codice.
Int x = flag ? SafeInt<unsigned int>(y) : -1;
Il compilatore viene convertito alla seguente:
Int x = flag ? SafeInt<unsigned int>(y) : SafeInt<unsigned int>(-1);
Se flag è false, il compilatore genera un'eccezione anziché assegnare il valore -1 a x.Di conseguenza, evitare questo comportamento, il codice corretto per utilizzare è la seguente riga.
Int x = flag ? (int) SafeInt<unsigned int>(y) : -1;
T e U è possibile assegnare un tipo boolean, il tipo di carattere, o il tipo integer.Tipi integer possono essere firmati con o senza segno e qualsiasi dimensione di 8 bit a 64 bit.
[!NOTA]
Sebbene la classe di SafeInt accetta qualsiasi tipo di Integer, esegue più efficiente dei tipi senza segno.
E è il meccanismo di gestione degli errori che SafeInt utilizza.Due meccanismi di gestione degli errori vengono forniti della libreria SafeInt.I criteri predefiniti sono SafeIntErrorPolicy_SafeIntException, che generano un'eccezione di Classe SafeIntException quando si verifica un errore.Gli altri criteri vengono SafeIntErrorPolicy_InvalidParameter, che interrompono il programma se si verifica un errore.
Sono disponibili due opzioni per la personalizzazione dei criteri di errore.La prima opzione consiste di impostare il parametro E quando si crea SafeInt.Utilizzare questa opzione quando si desidera modificare i criteri di gestione degli errori per un solo SafeInt.Un'altra opzione consiste nel definire _SAFEINT_DEFAULT_ERROR_POLICY per essere la classe personalizzata di gestione degli errori prima di importare la libreria di SafeInt .Utilizzare questa opzione quando si desidera modificare i criteri predefiniti di gestione degli errori per tutte le istanze della classe di SafeInt nel codice.
[!NOTA]
Una classe personalizzata che gestisce gli errori dalla libreria SafeInt non deve restituire il controllo del codice che ha chiamato il gestore errori.Dopo che il gestore degli errori viene chiamato, il risultato dell'operazione di SafeInt non può essere attendibile.
Requisiti
intestazione: safeint.h
Msl::utilities diSpazio dei nomi: