방금 ++ 또는 +=와 같은 열거 형에 표준 수학 연산자를 사용할 수 없다는 것을 알았습니다.
그렇다면 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;
}
C++11 은 대체 실제로 함께 있다. 간단한 템플라이스트 먹어서나 사용자 정의 반복자가.
enum class foo {
one,
two,
three
};
이 일반 코드가 매우 효율적으로 수행할 트릭, 일반 배치하십시오 헤더입니다 it& # 39, ll 경배하되 반복할 경우 너회들 이넘 할 수 있습니다.
#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;
사용 후 범위를 반복할 수 있습니다.
for (foo i : fooIterator() ) { //notice the parentheses!
do_stuff(i);
}
너무 복잡한 이러한 솔루션, i do like that.
enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};
const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };
for (NodePosition pos : NodePositionVector) {
...
}
저는 가끔 do it like that
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))
{}
enum class myenumtype {
MYENUM_FIRST,
MYENUM_OTHER,
MYENUM_LAST
}
for(myenumtype myenum = myenumtype::MYENUM_FIRST;
myenum != myenumtype::MYENUM_LAST;
myenum = static_cast<myenumtype>(static_cast<int>(myenum) + 1)) {
do_whatever(myenum)
}
다음 매크로 정의 할 수 있습니다.
#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++ 역어셈블러 바라보았다. 이 코드는 매우 효율적인. # 39 don& 미룰 수 없는, 그러나 위해 3 개 명령문입니다: 하나만 깔의 컴파일러에서 루프 최적화 후! 루프 인클로우저된 정의할 수도 있습니다.
unsigned p[4][5];
for_range (Count, i, zero,three)
for_range(unsigned int, j, 4, 0)
{
p[i][j] = static_cast<unsigned>(i)+j;
}
여러분은 분명히 열거됩니다 유형 및 갭스 반복할 수 없습니다.
이넘 더럽히지 않는 경우) 는 최종 카운트입니다 있습니다 싶은 항목 (때문에 아마도 당신이 또한 list. 이넘 있는 스위치의 경우 그 다음 컴파일러에서 경고자로서 너 않은 카운트입니다), 이 작업을 수행할 수 있습니다.
enum Colour {Red, Green, Blue};
const Colour LastColour = Blue;
Colour co(0);
while (true) {
// do stuff with co
// ...
if (co == LastColour) break;
co = Colour(co+1);
}
typedef enum{
first = 2,
second = 6,
third = 17
}MyEnum;
static const int enumItems[] = {
first,
second,
third
}
static const int EnumLength = sizeof(enumItems) / sizeof(int);
for(int i = 0; i < EnumLength; i++){
//Do something with enumItems[i]
}
Ms 의 컴파일러에도:
#define inc_enum(i) ((decltype(i)) ((int)i + 1))
enum enumtype { one, two, three, count};
for(enumtype i = one; i < count; i = inc_enum(i))
{
dostuff(i);
}
참고: 이는 단순한 템플라이스트 비해 훨씬 적은 코드 사용자 정의 반복자가 대답.
'를 사용하여 작업할 수 있습니다' 대신 '데클티페 afaq afnor mgcc 메리 페로프 don& # 39 이 순간, t, but I' 핸디 컴파일러와의 가능한지 정리합니다.
enum Bar {
One = 1,
Two,
Three,
End_Bar // Marker for end of enum;
};
for (Bar foo = One; foo < End_Bar; foo = Bar(foo + 1))
{
// ...
}
"'c++컴파일러는 이넘 class A { a0 = 0, a3, a4 = 3 = 4 }; a, 3> 콘스테스파르 std::array<; ALL_A a3 는 a4 는}, {a0 은, // 콘스테스파르 가 중요합니다.
은 a: ALL_A) { 표준용량 코트 < < (a = a = a4 는 a0 은) 경우;; (a), int> static_cast<; } "'
할 수 없이 'a' 는 콘스테스파르 표준용량 어레이입니다 비순차적 이넘 어레이입니다 의해 컴파일러와의 인스턴스화되지 있다. # 39 에 최적화 및 작성하든지 compiler& 셨으며 따라 이 같은 휴리스틱 array& 시행하십시오 # 39 의 주소입니다.
I found that '실험', '내' 가 있는 경우에는 위의 어레이입니다 빼냅니다 최적화합니다 g++ 9.1 o3 2 값 또는 비순차적 적지 순차인지 값 (내가 테스트됨 최대 6). 그러나 이 경우 '만 있는 경우' 는 성명을 발표했다. (난 다시 기술서임을 비교하는 정수 값 보다 큰 모든 요소를 순차인지 어레이입니다 및 it 린린드 이터레이션은 불구하고 되니그들 기술입니까 제외된 있지만 이 경우, 값을 메모리에 기술서임을 경우 그냥 아웃해야 씌워진.) 또한 비순차적 [1 건 (https://godbolt.org/z/XuGtoc) 에서 5 의 값을 린린드 이넘]. 이 때문에 깊은 관련이 있다는 의심이 홀수입니다 비헤이비어는 휴리스틱 캐시합니다 및 분기 예측.
이것은 https://partner. microsoft. 대한 간단한 테스트를 이터레이션에 고드볼트 보여주는 어레이입니다 해서 항상 프레젠테이션이든 인스턴스화됩니다.
이 기술은 지속적으로 가격이 두 배로 열거합니다 먹어서나 이넘 요소를 동시에.
이넘 경우, 예를 들어 있다는 것을 알고 있던 순차인지 Qt: 키 값을 이넘 수 있습니다.
Qt::Key shortcut_key = Qt::Key_0;
for (int idx = 0; etc...) {
....
if (shortcut_key <= Qt::Key_9) {
fileMenu->addAction("abc", this, SLOT(onNewTab()),
QKeySequence(Qt::CTRL + shortcut_key));
shortcut_key = (Qt::Key) (shortcut_key + 1);
}
}
작동하잖아 강타했다.
그냥 배열입니다 정수 및 루프 만들었지만, 마지막 요소를 만들어 놓고 어레이입니다 말하도다 종료하십시오 찼음을 - 1 과 이 시간을 사용합니다.
만약 이넘은:
enum MyEnumType{Hay=12,Grass=42,Beer=39};
어레이입니다 만듭니다.
int Array[] = {Hay,Grass,Beer,-1};
for (int h = 0; Array[h] != -1; h++){
doStuff( (MyEnumType) Array[h] );
}
이 언약보다는 break down 상관 없이 정수 표현에서 deltamove - 1 확인란 충돌하지 한 요소를 물론이겠지.