열거 형을 어떻게 반복 할 수 있습니까? + =와

방금 ++ 또는 + =와 같은 열거 형에서 표준 수학 연산자를 사용할 수 없다는 것을 알았습니다.

그렇다면 C ++ 열거 형의 모든 값을 반복하는 가장 좋은 방법은 무엇입니까?



답변

일반적인 방법은 다음과 같습니다.

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

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

열거 형 Last은 반복에 의해 건너 뛰기위한 것입니다. 이 “가짜” Last열거 형을 사용하면 새 열거 형을 추가 할 때마다 for 루프에서 종료 조건을 마지막 “실제”열거 형으로 업데이트 할 필요가 없습니다. 나중에 더 많은 열거 형을 추가하려면 마지막 전에 추가하십시오. 이 예제의 루프는 여전히 작동합니다.

물론 열거 형 값을 지정하면 다음과 같이 분류됩니다.

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

이것은 열거 형이 실제로 반복되지 않는다는 것을 보여줍니다. 열거 형을 처리하는 일반적인 방법은 스위치 문에서 열거 형을 사용하는 것입니다.

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

실제로 열거하려면 열거 형 값을 벡터에 채우고 반복하십시오. 지정된 열거 형 값도 올바르게 처리합니다.


답변

#include <iostream>
#include <algorithm>

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

답변

열거 형이 0으로 시작하고 증분이 항상 1 인 경우

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

for(int i=0; i<enumTypeEnd; i++)
{
   enumType eCurrent = (enumType) i;
}

그렇지 않다면 내가 유일하게 왜 같은 것을 만드는 것 같아

vector<enumType> vEnums;

항목을 추가하고 일반 반복자를 사용하십시오 ….


답변

c ++ 11을 사용하면 실제로 간단한 템플릿 화 된 사용자 정의 반복자를 작성하는 대안이 있습니다.

열거 형이 있다고 가정 해 봅시다

enum class foo {
  one,
  two,
  three
};

이 일반 코드는 트릭을 매우 효율적으로 수행합니다-일반 헤더에 배치하면 반복해야 할 열거 형에 대해 서비스를 제공합니다.

#include <type_traits>
template < typename C, C beginVal, C endVal>
class Iterator {
  typedef typename std::underlying_type<C>::type val_t;
  int val;
public:
  Iterator(const C & f) : val(static_cast<val_t>(f)) {}
  Iterator() : val(static_cast<val_t>(beginVal)) {}
  Iterator operator++() {
    ++val;
    return *this;
  }
  C operator*() { return static_cast<C>(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<foo, foo::one, foo::three> fooIterator;

그런 다음 range-for를 사용하여 반복 할 수 있습니다

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

열거 형에 공백이 없다는 가정은 여전히 ​​사실입니다. 열거 형 값을 저장하는 데 실제로 필요한 비트 수에 대한 가정은 없습니다 (std :: underlying_type 덕분)


답변

이 솔루션이 너무 복잡합니다.

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

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

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

답변

나는 종종 그런 식으로

    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 EAnimalCaps
    {
        E_First,
        E_None    = E_First,
        E_CanFly  = 0x1,
        E_CanWalk = 0x2
        E_CanSwim = 0x4,
        E_Last
    }

    class MyAnimal
    {
       EAnimalCaps m_Caps;
    }

    class Frog
    {
        Frog() :
            m_Caps(EAnimalCaps(E_CanWalk | E_CanSwim))
        {}
    }

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

답변

열거 형으로는 할 수 없습니다. 아마도 열거 형이 상황에 가장 적합하지 않을 수도 있습니다.

일반적인 규칙은 MAX와 같은 마지막 열거 형 값의 이름을 지정하고 int를 사용하여 루프를 제어하는 ​​데 사용하는 것입니다.