2012-01-03 58 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); }