当前位置:  开发笔记 > 编程语言 > 正文

我如何迭代枚举?

如何解决《我如何迭代枚举?》经验,为你挑选了9个好方法。

我只是注意到你不能在枚举上使用标准数学运算符,如++或+ =

那么迭代C++枚举中所有值的最佳方法是什么?



1> andreas buyk..:

典型的方法如下:

enum Foo {
  One,
  Two,
  Three,
  Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
   Foo foo = static_cast(fooInt);
   // ...
}

当然,如果指定了枚举值,这会分解:

enum Foo {
  One = 1,
  Two = 9,
  Three = 4,
  Last
};

这说明枚举并不是真正意义上的迭代.处理枚举的典型方法是在switch语句中使用它.

switch ( foo )
{
    case One:
        // ..
        break;
    case Two:  // intentional fall-through
    case Three:
        // ..
        break;
    case Four:
        // ..
        break;
     default:
        assert( ! "Invalid Foo enum value" );
        break;
}

如果你真的想要枚举,将枚举值填入向量中并迭代它.这也将适当地处理指定的枚举值.


@Tony Last意味着被跳过.如果您想稍后添加更多枚举,请在Last ...之前添加它们.第一个示例中的循环仍然有效.通过使用"假的"Last枚举,每次要添加新枚举时,不必将for循环中的终止条件更新为最后一个"实际"枚举.
请注意,在示例的第一部分中,如果要使用"i"作为Foo枚举而不是int,则需要静态转换为:static_cast (i)
你也在循环中跳过Last.应该<=最后

2> The Failure ..:
#include 
#include 

namespace MyEnum
{
  enum Type
  {
    a = 100,
    b = 220,
    c = -1
  };

  static const Type All[] = { a, b, c };
}

void fun( const MyEnum::Type e )
{
  std::cout << e << std::endl;
}

int main()
{
  // all
  for ( const auto e : MyEnum::All )
    fun( e );

  // some
  for ( const auto e : { MyEnum::a, MyEnum::b } )
    fun( e );

  // all
  std::for_each( std::begin( MyEnum::All ), std::end( MyEnum::All ), fun );

  return 0;
}



3> João Augusto..:

如果你的枚举以0开头,则增量始终为1.

enum enumType 
{ 
    A = 0,
    B,
    C,
    enumTypeEnd
};

for(int i=0; i

如果不是,我想唯一的原因就是创造类似的东西

vector vEnums;

添加项目,并使用普通迭代器....



4> 小智..:

使用c ++ 11,实际上还有另一种选择:编写一个简单的模板化自定义迭代器.

让我们假设你的枚举是

enum class foo {
  one,
  two,
  three
};

这个通用代码可以非常高效地完成这一操作 - 放置在通用头文件中,它可以为您可能需要迭代的任何枚举提供服务:

#include 
template < typename C, C beginVal, C endVal>
class Iterator {
  typedef typename std::underlying_type::type val_t;
  int val;
public:
  Iterator(const C & f) : val(static_cast(f)) {}
  Iterator() : val(static_cast(beginVal)) {}
  Iterator operator++() {
    ++val;
    return *this;
  }
  C operator*() { return static_cast(val); }
  Iterator begin() { return *this; } //default ctor is good
  Iterator end() {
      static const Iterator endIter=++Iterator(endVal); // cache it
      return endIter;
  }
  bool operator!=(const Iterator& i) { return val != i.val; }
};

你需要专门化它

typedef Iterator fooIterator;

然后你可以使用range-for进行迭代

for (foo i : fooIterator() ) { //notice the parentheses!
   do_stuff(i);
}

你的枚举中没有间隙的假设仍然是正确的; 对存储枚举值实际需要的位数没有假设(感谢std :: underlying_type)


@lepe这就像说`std :: vector`不是通用的,因为`std :: vector <foo>`绑定到`foo`。
哦,我看到了这个问题-`foo operator *(){...`应该是`C operator *(){...`。

5> Enzojz..:

这些解决方案太复杂了,我喜欢这样:

enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};

const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };

for (NodePosition pos : NodePositionVector) {
...
}


我希望这是因为条目需要在两个地方维护.
@thegreatjedi自C ++ 11起,您甚至可以更加简单:for(auto pos:NodePositionVector){..}

6> Corey Trager..:

你不能用枚举.也许enum不是最适合你的情况.

一个常见的约定是将最后一个枚举值命名为MAX,并使用它来控制使用int的循环.



7> Niki..:

我经常这样做

    enum EMyEnum
    {
        E_First,
        E_Orange = E_First,
        E_Green,
        E_White,
        E_Blue,
        E_Last
    }

    for (EMyEnum i = E_First; i < E_Last; i = EMyEnum(i + 1))
    {}

或者如果不是连续的,但是使用常规步骤(例如位标志)

    enum EAnimal
    {
        E_First,
        E_None    = E_First,
        E_CanFly  = 0x1,
        E_CanWalk = 0x2
        E_CanSwim = 0x4,
        E_Last
    }

    for (EAnimali = E_First; i < E_Last; i = EAnimal(i << 1))
    {}



8> Mikhail Seme..:

您可以尝试定义以下宏:

#define for_range(_type, _param, _A1, _B1) for (bool _ok = true; _ok;)\
for (_type _start = _A1, _finish = _B1; _ok;)\
    for (int _step = 2*(((int)_finish)>(int)_start)-1;_ok;)\
         for (_type _param = _start; _ok ; \
 (_param != _finish ? \
           _param = static_cast<_type>(((int)_param)+_step) : _ok = false))

现在你可以使用它:

enum Count { zero, one, two, three }; 

    for_range (Count, c, zero, three)
    {
        cout << "forward: " << c << endl;
    }

它可用于通过无符号,整数,枚举和字符向后和向前迭代:

for_range (unsigned, i, 10,0)
{
    cout << "backwards i: " << i << endl;
}


for_range (char, c, 'z','a')
{
    cout << c << endl;
}

尽管定义很尴尬,但它的优化得非常好.我在VC++中查看了反汇编程序.代码非常有效.不要推迟但是三个for语句:编译器在优化后只会产生一个循环!您甚至可以定义封闭的循环:

unsigned p[4][5];

for_range (Count, i, zero,three)
    for_range(unsigned int, j, 4, 0)
    {   
        p[i][j] = static_cast(i)+j;
    }

你显然无法通过间隙迭代枚举类型.


`_A1`不是允许的名称,它是带有以下大写字母的前导下划线.

9> Riot..:

其他答案中未涉及的内容=如果您使用的是强类型C++ 11枚举,则不能使用+++ int使用它们.在这种情况下,需要一些更麻烦的解决方案:

enum class myenumtype {
  MYENUM_FIRST,
  MYENUM_OTHER,
  MYENUM_LAST
}

for(myenumtype myenum = myenumtype::MYENUM_FIRST;
    myenum != myenumtype::MYENUM_LAST;
    myenum = static_cast(static_cast(myenum) + 1)) {

  do_whatever(myenum)

}


...但是C++ 11引入了基于其他答案的范围.:-)
推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有