Standarda göre renk nedir?
C ++ 11 ve C ++ 14 Standartlarından alıntı ile cevaplama:
[Expr.static.cast] / 10
Bir integral veya numaralandırma türünün değeri açıkça bir numaralandırma türüne dönüştürülebilir. Orijinal değer numaralandırma değerleri (7.2) aralığındaysa değer değişmez. Aksi takdirde, ortaya çıkan değer belirtilmez (ve bu aralıkta olmayabilir).
Numaralandırma değerlerinin aralığına bakalım : [dcl.enum] / 7
Temel türü sabit olan bir numaralandırma için, numaralandırmanın değerleri temeldeki türün değerleridir.
CWG 1766'dan (C ++ 11, C ++ 14) önce
Bu nedenle, data[0] == 100
sonuçta elde edilen değer belirtilir (*) ve Tanımsız Davranış (UB) dahil edilmez . Daha genel olarak, altta yatan türden numaralandırma türüne döküm yaptığınızda, için hiçbir değer data[0]
UB'ye neden olamaz static_cast
.
CWG 1766'dan sonra (C ++ 17)
Bkz. CWG hatası 1766 . Eğer şimdi çok [expr.static.cast] p10 paragraf, güçlendirilmiştir olabilir dışarıda enum türüne bir enum gösterilebilen aralığıdır bir değer dağıtmak eğer UB çağırmak. Bu data[0]
, sayımın altında yatan türden olduğu için , söz konusu senaryo için hala geçerli değildir (yukarıya bakın).
CWG 1766'nın Standartta bir kusur olarak kabul edildiğini, bu nedenle derleyici uygulayıcılarının C ++ 11 ve C ++ 14 derleme modlarına başvurmaları kabul edildiğini lütfen unutmayın.
(*) char
en az 8 bit genişlikte olması gerekir, ancak olması gerekmez unsigned
. Saklanabilir maksimum değerin en azından 127
C99 Standardının Ek E'sine uygun olması gerekir .
[İfade] / 4 ile karşılaştır
Bir ifadenin değerlendirilmesi sırasında sonuç, matematiksel olarak tanımlanmazsa veya türü için temsil edilebilir değerler aralığında değilse, davranış tanımsızdır.
CWG 1766'dan önce, dönüşüm integrali türü -> numaralandırma türü belirtilmemiş bir değer üretebilir . Soru şudur: Belirtilmemiş bir değer, türü için temsil edilebilir değerlerin dışında olabilir mi? Cevabın hayır olduğuna inanıyorum - cevap evet olsaydı, "bu işlem belirtilmemiş bir değer üretir" ile "bu işlem tanımlanmamış davranışa sahiptir" arasında imzalanmış türler için aldığınız garantilerde herhangi bir fark olmazdı.
Bu nedenle, cwg 1766 kadar önceden bile static_cast<Color>(10000)
olur olup UB çağırmak; ama CWG 1766 sonrasında, bu does UB çağırmak.
Şimdi switch
ifade:
[Stmt.switch] / 2
Koşul, integral tipte, numaralandırma tipinde veya sınıf tipinde olmalıdır. [...] İntegral tanıtımlar yapılır.
[Conv.prom] / 4
Altta yatan türü sabit olan (7,2) kapatılmamış numaralandırma türünün bir değeri , altta yatan türün bir değerine dönüştürülebilir. Üstelik, altta yatan tipine integral yükselme uygulanabiliyorsa, altta yatan tipi sabit olan, örtüsüz bir numaralandırma tipinin bir değeri, yükseltilmiş alttaki tipin bir değerine dönüştürülebilir.
Not: Enum-baz içermeyen kapsamlandırılmış bir enum tipi int
. Unscoped çeteleler için temel tipi uygulama tanımlı, fakat daha büyük olmayacaktır int
eğer int
tüm enumerator'ın değer içerebilir.
Bir İçin unscoped numaralandırma , bu potansiyel müşteriler bize / 1'e
Başka bir tamsayıdır tip bir prvalue bool
, char16_t
, char32_t
ya da wchar_t
olan bir tamsayı dönüşüm sıralaması (4.13) daha az bir sıralaması daha int
tipte bir prvalue dönüştürülebilir int
ise int
, kaynak türü bütün değerlerini temsil edebilir; Aksi takdirde, kaynak değer bir tür değere dönüştürülebilir unsigned int
.
İşlenmemiş bir numaralandırma söz konusu olduğunda, int
burada s ile ilgileniriz . For kapsamına sahip numaralandırma ( enum class
ve enum struct
), hiçbir ayrılmaz promosyon uygular. Saklı değer, altta yatan türün aralığında ve aralığında olduğu için, hiçbir şekilde, tümleşik tanıtım da UB'ye yol açmaz int
.
[Stmt.switch] / 5
İfade switch
yürütüldüğünde durumu değerlendirilir ve her durum sabiti ile karşılaştırılır. Vaka sabitlerinden biri koşulun değerine eşitse, kontrol eşleşen case
etiketi izleyen ifadeye iletilir . Hayır ise case
sabit durumu ile eşleşir ve bir varsa default
etiket, kontrol tarafından etiketli açıklamaya geçer default
etiket.
default
Etiket isabet edilmelidir.
Not: Karşılaştırma operatörüne bir kez daha bakılabilir, ancak atıfta bulunulan "karşılaştırma" da açıkça kullanılmaz. Aslında, bizim durumumuzda kapsamlandırılmış ya da örtülmemiş numaralandırmalar için UB'yi getireceğine dair bir ipucu yoktur.
Bir bonus olarak, standart bununla ilgili olarak düz numaralandırma ile herhangi bir garanti veriyor mu?
Olsun ya da olmasın enum
burada herhangi bir fark yaratmıyor kapsamı. Ancak, altta yatan türün sabit olup olmadığı bir fark yaratır. [Decl.enum] / 7'nin tamamı:
Temel türü sabit olan bir numaralandırma için, numaralandırmanın değerleri temeldeki türün değerleridir. Aksi durumda, bir sayım için , e az küçük Numaralayıcı ve bir E maksimum büyük olan, sayım değerleri değerleri aralığı içindedir b dakika için b maksimum şu şekilde tanımlanmıştır: Let K
olduğu 1
bir ikinin tümleyici gösteriminde ve 0
A kişinin tamamlayıcı veya işaret büyüklüğünde gösterimi. b max , max (| e min | - K
, | e max |) değerinden büyük veya ona eşit en küçük değerdir ve 2'ye eşittirM - 1 , buradaM
negatif olmayan bir tamsayıdır. e min negatifdeğilse b min sıfır,aksi takdirde - (b max + ) .K
Aşağıdaki numaralandırmaya bir göz atalım:
enum ColorUnfixed /* no fixed underlying type */
{
red = 0x1,
yellow = 0x2
}
Tüm kapsamlandırılmış numaralandırmaların altta yatan sabit türleri olduğu için bunu kapsamlandırılmış numaralandırma olarak tanımlayamayacağımızı unutmayın.
Neyse ki, ColorUnfixed
en küçük listeleyicisi olduğunu red = 0x1
, bu yüzden max (| E dk | - K
, | e maks |) eşittir etmek | e max | her durumda yellow = 0x2
. En küçük değeri büyük veya ona eşit 2
eşittir, 2 M - 1 bir pozitif tamsayı M
olduğu 3
( 2 2 - 1 ). (I niyet 1 bit adımda ölçüde sağlanmasına olanak veren bir olduğunu düşünüyorum.) O, aşağıdaki B max olduğu 3
ve Bmin olup 0
.
Bu nedenle, 100
bir aralığının dışında olabilir ColorUnfixed
ve static_cast
DDI 1766 sonra cwg 1766 önce tanımlanmamış değeri ve tanımlanmamış davranışı üretecektir.
char
, bu nedenle "Orijinal değer numaralandırma değerleri (7.2) aralığındaysa değer değişmez." geçerlidir.