在c++中迭代连续枚举值的最简单方法

Simplest method for iterating through contiguous enum values in C++

本文关键字:最简单 方法 枚举 连续 c++ 迭代      更新时间:2023-10-16

在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 ...似乎对此感到高兴)?

确实安全。

这将是未定义的:MyEnum(int(NUM_ENUMS) + 1),因为要保存的值(4)将大于enum所能表示的值([0,3]);因为你确保m严格低于NUM_ENUMS,所以使用MyEnum(m + 1)是安全的。

另一方面,请注意,使用自定义枚举会有问题,例如:
enum OtherEnum {
    Foo = -1,
    Bar = 2,
    Baz = 8,
    NUM_OTHERENUM
};

所以这不是一个通用的做法。

我建议对生成的数组进行迭代:

MyEnum const Values[] = { FOO, BAR, BLECH };

请注意,它很容易从枚举的定义中生成,并且还可以避免使用无意义的值(业务方面)污染接口。

就像Matthieu说的那样,这样做是完全安全的,并且不会以任何方式违反c++标准。

作为旁注,在enum上重载++操作符不仅是多余的,而且存在其他人已经声明的问题(例如,如果enum的值不是线性的)

因此,您需要的不是定义操作符++,而是定义一个迭代器。

对于deft_code中的枚举,我采用了下面的解决方案,但稍微针对您的示例进行了调整。

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;
   }
}

这对你来说可能仍然是多余的,但它更干净。另一段代码,但更优雅的方法在这里。将来c++ 11中引入的枚举类有可能在标准中包含一个迭代器。

update:由于您更新了我们,您的值是连续的,并且它是C API(?)所需的事实,那么以上将不适合