2012-02-26 28 views
20

我正在使用作用域枚舉來枚舉我正在實現的某個狀態機中的狀態。例如,讓我們這樣說:作用域枚舉等價於「使用namespace X」嗎?

enum class CatState 
{ 
    sleeping, 
    napping, 
    resting 
}; 

在我的cpp文件中,我定義了一個狀態轉移表,我想使用的東西相當於using namespace X這樣我就不需要前綴與所有我的狀態名稱CatState::。換句話說,我想用sleeping而不是CatState::sleeping。我的轉換表有很多列,所以避免使用CatState::前綴會使事情更加緊湊和可讀。

那麼,有沒有辦法避免必須一直輸入CatState::


是啊,是啊,我已經意識到using namespace的陷阱。如果有強類型枚舉的等價物,我保證只在我的cpp實現文件中的有限範圍內使用它,而不是用於邪惡。

+0

你真的需要一個'enum class',還是'enum'呢? – netcoder 2012-02-26 04:06:30

+0

它最初是一個普通的'enum',但我正在轉換我的代碼以使用C++ 11功能。我喜歡使用'enum class'來強化類型安全的想法。 – 2012-02-26 04:09:36

回答

11

那麼,有沒有辦法避免必須一直鍵入CatState::

沒有。就像沒有必要爲靜態類成員鍵入ClassName::一樣。你不能說using typename ClassName,然後得到內部。強類型enum s也是如此。

您當然可以不使用enum class語法,只需使用常規的enum即可。但是,你失去了強大的打字。

應該指出,使用弱類型枚舉ALL_CAPS的原因之一是爲了避免名稱衝突。一旦我們有完整的範圍和強大的打字,一個枚舉的名稱是唯一標識,不能與其他名稱衝突。能夠將這些名稱帶入名稱空間範圍將重新引入此問題。因此,您可能希望再次使用ALL_CAPS來幫助消除名稱歧義。

+1

+1謝謝。我在想象強大的枚舉類似於命名空間,但將它看作是(某種程度上)類更有意義。 – 2012-02-26 04:02:03

8

你可能會考慮使用typedef縮短合格的名稱:

typedef CatState C; 

或者,如果列是,他們可以很容易地生成一種方式重複的,你可以考慮使用宏來生成每個在表格中的行,這可以導致非常簡潔(和更容易閱讀)的代碼。

+0

所以你是說沒有相當於使用枚舉的'namespace'?如果是這樣的話,那麼一個簡短的typedef對我來說似乎是最好的解決方案。 – 2012-02-26 03:49:11

+0

不是我知道的,沒有。您可能能夠爲每個枚舉器使用using聲明(例如'使用CatState :: sleeping;'等),但我不是100%確定的。如果代碼是高度重複的,但我強烈推薦一個宏。 – 2012-02-26 03:51:45

+0

+1我最終使用了你的typedef建議,但是Nicol給了我的問題直接的答案。我希望我能接受這兩個答案。 – 2012-02-26 04:04:22

2

Nicol的回答是正確的:該語言旨在讓您總是限定範圍的普查員(除了在enum { }範圍內)。

然而,here is a technique我想出了在所選擇的類中無法顯示的「範圍」枚舉數。從技術上講,這些統計員是無法比擬的,所以他們仍然會隱式轉換爲int。 (不像你說的那樣是「強類型」)。儘管如此,在成語中,它們是在名稱後面使用範圍操作符來訪問的,因此在語法上沒有區別 - 因此它需要C++ 11。

#define IMPORTABLE_ENUM(TYPENAME, ...) \ 
\ 
struct import_ ## TYPENAME { \ 
    enum TYPENAME { \ 
     __VA_ARGS__ \ 
    }; \ 
}; \ 
\ 
typedef import_ ## TYPENAME :: TYPENAME TYPENAME; 

// usage: 
IMPORTABLE_ENUM (duck, huey, dewey, louie) 

duck d = duck::dewey; // can't use unscoped enumerators here 

struct duck_madness : private import_duck { // but inside a derived class 
    duck who_did_it() { return huey; } // qualification is unnecessary 
}; 
2

我也很想有這種可能性,我覺得這個限制很煩人。程序員決定使用哪些功能通常是最好的。無論是顯式範圍還是更方便的方式。如果你限制程序員,爲了方便起見,他會刪除整個功能,或者創建醜陋的解決方法,比如以下基於模板的安全枚舉類型。編譯時沒有優化會產生一些開銷。

template<class _Enum> 
class type_safe_enum 
{ 
private: 
    _Enum m_EnumValue; 
    operator int(); 
public: 
    inline operator _Enum() const { return m_EnumValue; } 
    inline void operator =(_Enum x) { m_EnumValue = x; } 
}; 

enum _MY_ENUM 
{ 
    Value1, 
    Value2 
}; 

enum _MY_ENUM2 
{ 
    Value3, 
    Value4 
}; 

typedef type_safe_enum<_MY_ENUM> MY_ENUM; 

void TestMyEnum() 
{ 
    MY_ENUM myEnum; 
    int x; 

    myEnum = Value1; // ok 
    // myEnum = Value3; // compilation error 
    // myEnum = 0; // compilation error 
    // x = myEnum; // compilation error 

} 
+1

您的'_Enum'和其他'_ [A-Z] +'標識符導致未定義的行爲,請參閱[有關下劃線的規則](http://stackoverflow.com/a/228797/673852)。也就是說,所有以下劃線開頭的標識符以及大寫字母或其他下劃線總是保留用於任何用途。 '如果程序在保留的上下文中聲明或定義了一個標識符,那麼行爲是不確定的。 – Ruslan 2016-01-04 19:57:03

+0

我想你不是來自Windows世界,否則你會知道MS違反了大部分結構標記的標準。我沒有說,使用這個代碼,因爲它是你的個人項目。這些標識符是保留的,這樣*普通*程序員就可以遵守規則,並且不會與系統開發者發生衝突。它們是爲系統開發人員和像我這樣的瘋狂的屁股dickheads保留的,他們是做自己的東西的。我編寫系統頭文件,引導加載程序和操作系統內核,所以這些規則不適合我。比違反這個規則更糟糕的是使用標準的C函數,比如strcpy或asctime。 – Timo 2016-01-06 23:37:16