2012-01-03 189 views
1

我有幾個類似於下面的嵌套枚舉。我想要將isValid()函數定義爲儘可能接近enum定義。實際的代碼更加冗長,嵌套的命名空間和結構多層次。關於嵌套枚舉的C++操作

struct S 
{ 
    enum E { V1, V2 }; 
    /* ????? */ bool isValid(E e) { return e==V1 || e==V2; } 
}; 

template <typename Enum> 
bool legalValue(Enum e) 
{ 
    return isValid(e); 
} 

是否有可能使此代碼工作,而不必把isValid()在全局命名空間?

請不要評論isValid()是否是好的做法。這個問題同樣適用於希望覆蓋operator<<()以便能夠有效地傳輸枚舉值的人。在這種情況下,operator<<()的本質是否可以位於struct S的內部?

+1

我不確定這裏出現了什麼問題。只需使'isValid()'函數'static',並更改'legalValue()'函數來執行'return S :: isValid(e);',我認爲這應該編譯... – 2012-01-03 15:41:18

+0

這個想法是'legalValue ()'應該適用於任何具有關聯'isValid()'函數的'enum'。它不適用於嵌套'class'或'struct'的枚舉。 – paperjam 2012-01-03 15:43:20

+0

嘗試將枚舉放入命名空間中,而不是結構。這樣,ADL應該踢(我沒有測試過),你應該能夠調用isValid無論在聲明枚舉的名稱空間。 – paercebal 2012-01-03 15:44:54

回答

4

不,您必須將isValid移出struct。儘管如此,enum的定義可以保留在其中。

struct S 
{ 
    enum E { V1, V2 }; 
}; 

bool isValid(S::E e) { return e == S::V1 || e == S::V2; } 

template <typename Enum> 
bool legalValue(Enum e) 
{ 
    return isValid(e); 
} 
+0

OP的規定之一是「是否有可能使此代碼無需在全局命名空間中放置isValid()?」... – 2012-01-03 15:48:05

+0

謝謝,但我問是否有除此之外的解決方案。 – paperjam 2012-01-03 15:48:41

+1

@OliCharlesworth:我想答案是否定的;更新了答案,儘管我不能引用標準的合唱和詩歌。 – 2012-01-03 15:49:28

3

S::E無法找到S

如果S是一個命名空間,Koenig lookup會發現isValid即使它不是全局命名空間的一部分,但我覺得這不是你的意思。

1

如果這是標準的C++,即對C++ 2011,您可以轉發聲明嵌套枚舉:

struct S { enum E: int; }; 

enum S::E: int { V1, V2 }; 
bool isValid(S::E e) { return e == S::V1 || S::V2; } 

當然,你也不必窩枚舉成一個結構,以避免封閉範圍內的污染:不是你會使用

enum class S { V1, V2 }; 
bool isValid(S e) { return e == S::V1 || S::V2; } 

使用V1V2不合格的將是非法的。

1

這些可能是技術問題,但是製作isValid全局的另一選項是過載(或專用)legalValue

struct S 
{ 
    enum E { V1, V2 }; 
    static bool isValid(E e) { return e==V1 || e==V2; } 
}; 
bool legalValue(S::E e) { return S::isValid(e); } 

template <typename Enum> 
bool legalValue(Enum e) { return isValid(e); } 

另一種選擇是使isValid成爲全球朋友。儘管這與它只是一個免費的全球功能幾乎沒有任何區別。

struct S 
{ 
    enum E { V1, V2 }; 
    friend bool isValid(E e) { return e==V1 || e==V2; } 
}; 
template <typename Enum> 
bool legalValue(Enum e) { return isValid(e); }