在C ++中使用连续值迭代枚举的首选简单方法是什么?我之前发现了关于这个主题的SO问题,涉及创建自定义operator++
等,但这看起来有些过分。到目前为止,我提出的最好的是:
enum {
FOO,
BAR,
BLECH,
NUM_ENUMS
} MyEnum;
//for (MyEnum m = FOO; m < NUM_ENUMS; ++m) // compile error
// ...
//for (MyEnum m = FOO; m < NUM_ENUMS; m = m + 1) // compile error
// ...
for (MyEnum m = FOO; m < NUM_ENUMS; m = MyEnum(m + 1)) // OK ?
...
从编码风格的角度看这是否合理,是否可能产生警告(g++ -Wall ...
对此感到满意)?
答案 0 :(得分:14)
确实很安全。
这将是未定义的:MyEnum(int(NUM_ENUMS) + 1)
因为hold(4)的值将大于枚举可以表示的值([0,3]);由于您确保m
严格低于NUM_ENUMS
,因此使用MyEnum(m + 1)
是安全的。
另一方面,请注意您会遇到自定义枚举的问题,例如:
enum OtherEnum {
Foo = -1,
Bar = 2,
Baz = 8,
NUM_OTHERENUM
};
所以这不是一般做法。
我建议生成的数组代替迭代:
MyEnum const Values[] = { FOO, BAR, BLECH };
请注意,它很容易从枚举的定义生成,并且还避免使用无意义的值污染接口(业务方面)。
答案 1 :(得分:1)
就像Matthieu所说,这样做是完全安全的,并且不会违反C ++标准。
作为旁注,重载++运算符over enum不仅是一种矫枉过正,而且还有其他人已经说过的问题(例如,如果enum的值不是线性的)
因此,您需要的不是定义运算符++,而是迭代器。
我通过deft_code从这里regarding enums改编了以下解决方案,但略微适合您的示例。
template< typename T >
class Enum
{
public:
class Iterator
{
public:
Iterator( int value ) :
m_value( value )
{ }
T operator*( void ) const
{
return (T)m_value;
}
void operator++( void )
{
++m_value;
}
bool operator!=( Iterator rhs )
{
return m_value != rhs.m_value;
}
private:
int m_value;
};
};
template< typename T >
typename Enum<T>::Iterator begin( Enum<T> )
{
return typename Enum<T>::Iterator( (int)T::First );
}
template< typename T >
typename Enum<T>::Iterator end( Enum<T> )
{
return typename Enum<T>::Iterator( ((int)T::Last) + 1 );
}
enum class MyEnum
{
FOO,
BAR,
BLECH,
NUM_ENUMS
};
int main()
{
for( auto e: Enum<MyEnum>() )
{
std::cout << ((int)e) << std::endl;
}
}
对你来说,这可能仍然是一种矫枉过正,但它更清洁。另一段代码,但更优雅的方法是here。将来有可能在C ++ 11中引入的枚举类可能在标准中有一个迭代器。
更新:由于您更新了我们您的值是连续的以及C API(?)所需的事实,因此上述内容将不合适