范圍enum(Scoped enum)
枚舉使我們可以將一組整型常量組合在一起姆另。與類一樣臼予,每個枚舉定義一個新類型撩轰。枚舉是文本類型胯甩。
C++有兩種枚舉:范圍和非范圍昧廷。新標(biāo)準(zhǔn)引入了范圍枚舉。我們使用關(guān)鍵字enum class
(或等價的enum struct
)定義一個范圍枚舉偎箫,后面跟著枚舉名稱和用大括號括起來的以逗號分隔的枚舉器列表木柬。分號跟在大括號后面:
Code:
enum class open_modes {input, output, append};
這里我們定義了一個名為open_modes
的枚舉類型,它有三個枚舉器:input
淹办,output
和append
眉枕。
我們通過省略class
(或struct
)關(guān)鍵字來定義一個不帶范圍的枚舉。枚舉名稱在非范圍枚舉中是可選的:
Code:
enum color {red, yellow, green}; // unscoped enumeration
// unnamed, unscoped enum
enum {floatPrec = 6, doublePrec = 10, double_doublePrec = 10};
如果枚舉未命名怜森,則只能將該類型的對象定義為枚舉定義的一部分速挑。與類定義一樣,我們可以在結(jié)束枚舉定義的大括號和分號之間提供一個用逗號分隔的聲明符列表副硅。
指定用于保存enum的類型
盡管每個枚舉定義了一個唯一的類型姥宝,但它由一個內(nèi)置的整型表示。在新標(biāo)準(zhǔn)下恐疲,我們可以通過在枚舉名稱后面加上冒號和要使用的類型的名稱來指定該類型腊满。
Code:
enum intValues : unsigned long long {
charTyp = 255, shortTyp = 65535, intTyp = 65535,
longTyp = 4294967295UL,
long_longTyp = 18446744073709551615ULL
};
如果不指定基礎(chǔ)類型,那么默認(rèn)情況下流纹,范圍枚舉的基礎(chǔ)類型為int
糜烹。非范圍枚舉沒有默認(rèn)值倘潜;我們只知道基礎(chǔ)類型足夠大缝其,可以容納枚舉器值诫睬。當(dāng)指定了基礎(chǔ)類型(包括為范圍枚舉隱式指定)時重斑,枚舉器的值太大药版,不適合該類型是錯誤的缀皱。
由于能夠指定枚舉的基礎(chǔ)類型呻此,我們可以控制不同實(shí)現(xiàn)中使用的類型备禀。我們可以確信壁公,在一個實(shí)現(xiàn)下編譯的程序在另一個實(shí)現(xiàn)上編譯時會生成相同的代碼感论。
enum的前向聲明
根據(jù)新標(biāo)準(zhǔn),我們可以前向聲明enum
紊册。enum
前向聲明必須(隱式或顯式地)指定枚舉的基礎(chǔ)大斜纫蕖:
Code:
// forward declaration of unscoped enum named intValues
enum intValues : unsigned long long; // unscoped, must specify a type
enum class open_modes; // scoped enums can use int by default
因?yàn)榉欠秶杜e沒有默認(rèn)大小,所以每個聲明都必須包含該枚舉的大小囊陡。我們可以聲明一個范圍枚舉芳绩,而不指定大小,在這種情況下撞反,大小被隱式定義為int
妥色。
與任何聲明一樣,給定枚舉的所有聲明和定義必須相互匹配遏片。對于枚舉嘹害,此要求意味著枚舉的大小必須在所有聲明和枚舉定義中相同撮竿。
此外,我們不能在一個上下文中將名稱聲明為非范圍枚舉笔呀,并在以后將其重新聲明為范圍枚舉:
Code:
// error: declarations and definition must agree whether the enum is scoped or unscoped
enum class intValues;
enum intValues; // error: intValues previously declared as scoped enum
enum intValues : long; // error: intValues previously declared as int
標(biāo)準(zhǔn)庫mem_fn類模板
要使用function
幢踏,我們必須提供要調(diào)用的成員的調(diào)用簽名。相反凿可,我們可以使用另一個庫工具mem_fn
讓編譯器來推斷成員的類型惑折,該工具在頭文件<functional>
中定義授账。與function
一樣枯跑,mem_fn
從指向成員的指針生成可調(diào)用對象。與function
不同白热,mem_fn
將從指向成員的指針類型推導(dǎo)出可調(diào)用類型:
Code:
find_if(svec.begin(), svec.end(), mem_fn(&string::empty));
這里我們使用mem_fn(&string::empty)
生成一個可調(diào)用對象敛助,該對象接受一個字符串參數(shù)并返回一個bool
。
mem_fn
生成的可調(diào)用對象可以在對象或指針上調(diào)用:
Code:
auto f = mem_fn(&string::empty); // f takes a string or a string*
f(*svec.begin()); // ok: passes a string object; f uses .* to call empty
f(&svec[0]); // ok: passes a pointer to string; f uses .-> to call empty
實(shí)際上屋确,我們可以將mem_fn
想象成它使用重載的函數(shù)調(diào)用操作符生成一個可調(diào)用的函數(shù)纳击,一個接受string*
,另一個接受string&
攻臀。
參考文獻(xiàn)
[1] Lippman S B , Josée Lajoie, Moo B E . C++ Primer (5th Edition)[J]. 2013.