Classe SafeInt
Étend les primitives d'entiers pour éviter un dépassement sur des entiers et vous permet de comparer différents types d'entiers.
template<typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY>
class SafeInt;
Paramètres
Modèle |
Description |
---|---|
T |
Le type de paramètre booléen ou entier que SafeInt remplace. |
E |
Un type de données énuméré qui définit la stratégie de gestion des erreurs. |
U |
Le type de paramètre de type entier ou booléen pour l'opérande secondaire. |
Paramètre |
Description |
---|---|
[in] rhs |
Un paramètre d'entrée qui représente la valeur à droite de l'opérateur dans plusieurs fonctions autonomes. |
[in] i |
Un paramètre d'entrée qui représente la valeur à droite de l'opérateur dans plusieurs fonctions autonomes. |
[in] bits |
Un paramètre d'entrée qui représente la valeur à droite de l'opérateur dans plusieurs fonctions autonomes. |
Membres
Constructeurs publics
Nom |
Description |
---|---|
Constructeur par défaut. |
Opérateurs d'assignation
Nom |
Syntaxe |
---|---|
= |
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() |
Opérateurs de casting
Nom |
Syntaxe |
---|---|
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 |
Opérateurs de comparaison
Nom |
Syntaxe |
---|---|
< |
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() |
Opérateurs arithmétiques
Nom |
Syntaxe |
---|---|
+ |
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) |
Opérateurs logiques
Nom |
Syntaxe |
---|---|
! |
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() |
Notes
La classe d' SafeInt protège contre le dépassement sur des entiers dans des opérations mathématiques. Par exemple, envisagez d'ajouter deux entiers de 8 bits: l'un a la valeur 200 et le second a la valeur 100. L'opération mathématique correcte est 200 + 100 = 300. Cependant, du fait de la limite entière de 8 bits, le bit supérieur est perdu et le compilateur retourne 44 (300 - 28) comme résultat. Toute opération qui dépend de cette équation mathématique génère un comportement inattendu.
La classe d' SafeInt vérifie si un dépassement de capacité arithmétique a lieu ou si le code tente de diviser par zéro. Dans les deux cas, la classe appelle le gestionnaire d'erreurs pour informer le programme du problème potentiel.
Cette classe vous permet également de comparer deux types différents d'entiers tant que ce sont des objets d' SafeInt. En règle générale, lorsque vous exécutez une comparaison, vous devez d'abord convertir les nombres pour qu'ils soient du même type. La conversion d'un nombre à un autre type requiert souvent des contrôles pour garantir qu'aucune perte de données n'a lieu.
Le tableau des opérateurs dans ce thème répertorie les fonctions mathématiques et les opérateurs de comparaison pris en charge par la classe d' SafeInt . La plupart des opérateurs mathématiques retournent un objet d' SafeInt de type T.
Les opérations de comparaison entre un SafeInt et un type intégral peuvent être effectuées dans un sens ou l'autre. Par exemple, SafeInt<int>(x) < y et y > SafeInt<int>(x) sont valides et retournent le même résultat.
De nombreux opérateurs binaires ne prennent pas en charge l'utilisation de deux types différents d' SafeInt. Un exemple de cette opération est l'opérateur d' &. SafeInt<T, E> & int est pris en charge, mais SafeInt<T, E> & SafeInt<U, E> ne l'est pas. Dans le dernier exemple, le compilateur ne connaît pas le type de paramètre à retourner. Une solution à ce problème consiste à convertir le deuxième paramètre vers le type de base. En utilisant les mêmes paramètres, cette opération peut être effectuée avec SafeInt<T, E> & (U)SafeInt<U, E>.
Notes
Pour toutes les opérations de bits, les deux paramètres différents doivent avoir la même taille.Si les tailles diffèrent, le compilateur lève une exception d' ASSERT (MFC).La précision des résultats de cette opération ne peuvent pas être garantis.Pour résoudre ce problème, effectuez un cast de la valeur la plus petite jusqu'à ce qu'elle soit de la même taille que le paramètre le plus grand.
Pour les opérateurs de décalage, le déplacement de plus de bits que ceux qui existent pour le type de modèle lèvera une exception d'ASSERTION. Cela n'a aucun effet dans le mode de version. Combiner deux types de paramètres de SafeInt est possible pour les opérateurs de décalage car le type de retour est identique au type d'origine. Le numéro à droite de l'opérateur indique uniquement le nombre de bits à déplacer.
Lorsque vous exécutez une comparaison logique avec un objet de SafeInt, la comparaison est strictement arithmétique. Par exemple, considérez ces expressions:
SafeInt<uint>((uint)~0) > -1
((uint)~0) > -1
La première déclaration se résoud à true, mais la deuxième déclaration se résoud à false. La négation au niveau du bit à 0 est 0xFFFFFFFF. Dans la deuxième déclaration, l'opérateur de comparaison par défaut compare 0xFFFFFFFF à 0xFFFFFFFF et les considère égaux. L'opérateur de comparaison pour la classe d' SafeInt vous signale que le deuxième paramètre est négatif alors que le premier paramètre n'est pas signé. Par conséquent, même si la représentation binaire est identique, l'opérateur logique d' SafeInt se rend compte que l'entier non signé est supérieur à -1.
Soyez prudent lorsque vous utilisez la classe d' SafeInt avec l'opérateur ternaire d' ?:. Observons la ligne de code suivante:
Int x = flag ? SafeInt<unsigned int>(y) : -1;
Le compilateur le convertit vers ceci:
Int x = flag ? SafeInt<unsigned int>(y) : SafeInt<unsigned int>(-1);
Si flag est false, le compilateur lève une exception au lieu d'affecter la valeur -1 à x. Par conséquent, pour éviter ce comportement, le code approprié à utiliser est la ligne suivante.
Int x = flag ? (int) SafeInt<unsigned int>(y) : -1;
T et U peuvent être attribués un type booléen, un type caractère, ou un type entier. Les types d'entiers peuvent être signés ou non signés et de toute taille entre 8 bits et 64 bits.
Notes
Bien que la classe d' SafeInt reçoive n'importe quel type d'entier, elle marche plus efficacement avec les types non signés.
E est le mécanisme de gestion des erreurs qu' SafeInt utilise. Deux mécanismes de gestion des erreurs sont fournis avec la bibliothèque de SafeInt. La stratégie par défaut est SafeIntErrorPolicy_SafeIntException, qui lève une exception de classe de SafeIntException lorsqu'une erreur se produit. L'autre stratégie est SafeIntErrorPolicy_InvalidParameter, qui arrête le programme si une erreur se produit.
Il existe deux options pour personnaliser la stratégie d'erreur. La première option consiste à définir le paramètre E lorsque vous créez un SafeInt. Utilisez cette option lorsque vous souhaitez modifier la stratégie de gestion des erreurs pour un seul SafeInt. L'autre solution consiste à définir _SAFEINT_DEFAULT_ERROR_POLICY comme votre programme personnalisé de gestion des erreurs avant d'inclure la bibliothèque d' SafeInt. Utilisez cette option si vous souhaitez modifier la stratégie par défaut de gestion des erreurs pour toutes les instances de la classe d' SafeInt dans votre code.
Notes
Une classe personnalisée qui gère les erreurs de la bibliothèque de SafeInt ne doit pas retourner le contrôle au code qui a appelé le gestionnaire d'erreurs.Une fois le gestionnaire d'erreurs appelé, le résultat de l'opération d' SafeInt ne peut pas être approuvé.
Configuration requise
En-tête : safeint.h
Espace de noms : msl::utilities