Qu'est-ce que le jeu de couleurs selon la norme?
Répondre par une citation de la Norme:
[expr.statique.distribution]/10
Une valeur de l'intégrale ou type d'énumération peut être converties explicitement à un type d'énumération. La valeur est inchangée si la valeur d'origine est à l'intérieur de la gamme des valeurs d'énumération (7.2). Sinon, la valeur est indéterminée (et peut-être pas dans cette gamme).
Voyons la gamme des valeurs d'énumération: [dcl.enum]/7
Pour une énumération dont le sous-jacent est de type fixe, les valeurs de l'énumération sont les valeurs du type sous-jacent.
Par conséquent, pour data[0] == 100
, la valeur est spécifiée(*), et non à un Comportement indéterminé (UB) est impliqué. Plus généralement, comme vous le lancez à partir du type sous-jacent pour le type d'énumération, sans aucune valeur en data[0]
peut conduire à l'AC pour l' static_cast
.
(*) char
est nécessaire d'être au moins 8 bits de large, mais n'est pas obligatoire pour être unsigned
. La valeur maximale stockable est nécessaire d'être au moins 127
conformément à l'Annexe E de la Norme C99.
Comparer à [expr]/4
Si, lors de l'évaluation d'une expression, le résultat n'est pas définie mathématiquement ou pas dans la gamme des représentable valeurs pour son type, le comportement est indéfini.
Donc, ce pourrait facilement conduire à l'UB si la valeur était assez grand, par exemple, static_cast<Color>(10000);
.
Maintenant, l' switch
déclaration:
[stmt.commutateur]/2
La condition doit être de type intégral, type d'énumération, de classe ou de type. [...] Intégrale les promotions sont effectuées.
[conv.bal]/4
Un prvalue d'un non délimité type d'énumération dont le sous-jacent est de type fixe (7.2) peut être converti en un prvalue de son type sous-jacent. En outre, si la promotion intégrale peut être appliqué à son type sous-jacent, un prvalue d'un non délimité type d'énumération dont le sous-jacent est de type fixe peut également être converti en un prvalue de l'promu type sous-jacent.
Remarque: Le type sous-jacent d'une étendue enum w/o enum-de base est de int
, pour les non délimité enums le type sous-jacent est de la mise en œuvre définies, mais qui est nécessaire pour être plus petit que int
si int
peut contenir les valeurs de tous les agents recenseurs
Pour une énumération non délimité, ce qui nous amène à /1
Un prvalue d'un entier de type autre que bool
, char16_t
, char32_t
ou wchar_t
dont la conversion d'entier rang (4.13) est inférieur au rang d' int
peut être converti en prvalue de type int
si int
peut représenter toutes les valeurs du type de source; sinon, la source prvalue peut être converti en prvalue de type unsigned int
.
Dans le cas d'une non délimité énumération, nous traiterait int
s ici. Pour l'étendue des énumérations (enum class
et enum struct
), aucune partie intégrante de la promotion s'applique. En quelque sorte, la promotion intégrale ne conduit pas à UB, soit, comme la valeur stockée dans la gamme du type sous-jacent et dans la gamme de int
.
[stmt.commutateur]/5
Lorsque l' switch
instruction est exécutée, sa condition est évaluée et comparée avec chaque cas constant. Si l'une de ces constantes est égale à la valeur de l'état, le contrôle est passé à l'instruction suivant la correspondance case
label. Si aucun case
constante correspond à la condition, et si il y a un default
label, le contrôle passe à l'état marqué par l' default
label.
L' default
de l'étiquette doit être frappé.
Remarque: On pourrait prendre un autre regard sur l'opérateur de comparaison, mais il n'est pas utilisé explicitement dans la "comparaison". En fait, il n'y a aucun indice qu'elle introduirait UB pour l'étendue ou non délimité les énumérations dans notre cas.
En bonus, la norme apporter aucune garantie quant à ce sujet, mais avec la plaine enum?
Si oui ou non l' enum
l'étendue de ne pas faire de différence. Cependant, il y a une différence si oui ou non le type sous-jacent est fixe. Le complet [decl.enum]/7 est:
Pour une énumération dont le sous-jacent est de type fixe, les valeurs de l'énumération sont les valeurs du type sous-jacent. Sinon, pour une énumération où emin est le plus petit agent recenseur et emax est le plus grand, les valeurs de l'énumération sont les valeurs dans la plage bmin à bmax, définis comme suit: Laissez - K
être 1
pour un complément à deux de la représentation et de l' 0
pour un complément ou un signe-amplitude de la représentation. bmax est la plus petite valeur supérieure ou égale à max(|emin| − K
, |emax|) et égale à 2M − 1, où M
est un entier non négatif. bmin est égale à zéro si emin est non-négative et (bmax + K
) autrement.
Heureusement, votre enum la plus petite de l'agent recenseur est - red = 0x1
, alors max(|emin| − K
, |emax|) est égal à |emax| en tout cas, qui est - yellow = 0x2
. La plus petite valeur supérieure ou égale à 2
, ce qui est égal à 2M - 1 pour un entier positif M
est 3
(22 - 1). (Je pense que l'intention est de permettre la plage de mesure de 1-bit-étapes). Il s'ensuit que bmax est - 3
et bmin est - 0
.
Par conséquent, 100
serait en dehors de la plage de l'enum, et l' static_cast
serait de produire une valeur quelconque, ce qui pourrait conduire à l'AC par [expr]/4.