3 回答

TA貢獻1770條經驗 獲得超3個贊
一個不錯的折衷方法是這樣的:
struct Flintstones {
enum E {
Fred,
Barney,
Wilma
};
};
Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;
從版本上來說,它不是類型安全的,但是用法比標準枚舉更好,并且在需要時仍可以利用整數轉換。

TA貢獻1784條經驗 獲得超9個贊
我個人使用的是typesafe枚舉用法的改編版本。它沒有提供您在編輯中陳述的所有五個“要求”,但無論如何我還是非常不同意其中的一些。例如,我看不到Prio#4(將值轉換為字符串)與類型安全有何關系。無論如何,大多數時間字符串表示形式的單個值都應與類型的定義分開(考慮一下i18n的簡單原因)。Prio#5(迭代,它是可選的)是我想看到的枚舉中自然發生的最好的事情之一,因此令您感到遺憾的是,它在您的請求中顯示為“可選”,但似乎可以通過以下方式更好地解決一個單獨的迭代系統,例如begin/end 函數或enum_iterator,這使它們可與STL和C ++ 11 foreach無縫協作。
OTOH這個簡單的成語很好地提供了Prio#3 Prio#1,這是因為它實際上只會包裝enum帶有更多類型信息的。更不用說這是一個非常簡單的解決方案,在很大程度上不需要任何外部依賴標頭,因此很容易攜帶。它還具有使枚舉范圍為a-la-C ++ 11的優點:
// This doesn't compile, and if it did it wouldn't work anyway
enum colors { salmon, .... };
enum fishes { salmon, .... };
// This, however, works seamlessly.
struct colors_def { enum type { salmon, .... }; };
struct fishes_def { enum type { salmon, .... }; };
typedef typesafe_enum<colors_def> colors;
typedef typesafe_enum<fishes_def> fishes;
解決方案提供的唯一“漏洞”是,它無法解決無法阻止enum將不同類型的s(或an enum和int)直接進行比較的事實,因為直接使用值時會強制執行隱式轉換至int:
if (colors::salmon == fishes::salmon) { .../* Ooops! */... }
但是到目前為止,我發現可以通過簡單地與編譯器進行更好的比較來解決這些問題,例如,顯式提供一個可以比較任意兩種不同enum類型的運算符,然后強制其失敗:
// I'm using backports of C++11 utilities like static_assert and enable_if
template <typename Enum1, typename Enum2>
typename enable_if< (is_enum<Enum1>::value && is_enum<Enum2>::value) && (false == is_same<Enum1,Enum2>::value) , bool >
::type operator== (Enum1, Enum2) {
static_assert (false, "Comparing enumerations of different types!");
}
盡管到目前為止似乎還沒有破壞代碼,并且確實可以不處理其他問題而明確地處理特定問題,但是我不確定這是“ 應該 ”做的事情(我懷疑它會干擾enum已參與其他地方聲明的轉換運算符;我很樂意收到對此的評論)。
將此與上面的類型安全習慣相結合,就可以enum class在操作性(可讀性和可維護性)方面相對接近C ++ 11 ,而不必做任何過于晦澀的事情。而且我不得不承認這樣做很有趣,我從沒想過要問編譯器是否在處理enums ...
- 3 回答
- 0 關注
- 677 瀏覽
添加回答
舉報