429 Stimmen

Wie kann ich über eine Aufzählung iterieren?

Mir ist gerade aufgefallen, dass man die Standard-Mathematik-Operatoren nicht auf eine enum wie zum Beispiel ++ o += .

Wie kann man also am besten durch alle Werte in einer C++-Datei iterieren? enum ?

2voto

Scott M Punkte 552

Vorteile: Enums können beliebige Werte in beliebiger Reihenfolge enthalten, und es ist immer noch einfach, über sie zu iterieren. Namen und Werte werden einmal definiert, im ersten #define.

Nachteile: Wenn Sie es bei der Arbeit verwenden, brauchen Sie einen ganzen Absatz, um es Ihren Kollegen zu erklären. Und es ist ärgerlich, Speicher deklarieren zu müssen, um Ihrer Schleife etwas zu geben, über das sie iterieren kann, aber ich kenne keinen Workaround, der Sie nicht auf Enums mit benachbarten Werten beschränkt (und wenn das Enum immer benachbarte Werte haben wird, bringt Ihnen das Enum vielleicht sowieso nicht viel).

//create a, b, c, d as 0, 5, 6, 7
#define LIST x(a) x(b,=5) x(c) x(d)
#define x(n, ...) n __VA_ARGS__,
enum MyEnum {LIST}; //define the enum
#undef x //needed
#define x(n,...) n ,
MyEnum myWalkableEnum[] {LIST}; //define an iterable list of enum values
#undef x //neatness

int main()
{
  std::cout << d;
  for (auto z : myWalkableEnum)
    std::cout << z;
}
//outputs 70567

Der Trick, eine Liste mit einem undefinierten Makro-Wrapper zu deklarieren und dann den Wrapper in verschiedenen Situationen anders zu definieren, hat viele andere Anwendungen als diese.

2voto

Aryaman Gupta Punkte 639

Es gibt bereits eine Diskussion über std::initializer_list (C++11) in den Kommentaren. Ich erwähne ein Beispiel, um über die Aufzählung zu iterieren.

oder std::initializer_list und eine einfachere Syntax:

enum E {
    E1 = 4,
    E2 = 8,
    // ..
    En
};

constexpr std::initializer_list<E> all_E = {E1, E2, /*..*/ En};

und dann

for (auto e : all_E) {
    // Do job with e
}

Referenz Link

2voto

Niels Holst Punkte 496

Wenn Sie Ihre Aufzählung nicht mit einem abschließenden COUNT-Element verschmutzen möchten (denn wenn Sie die Aufzählung auch in einem Schalter verwenden, wird der Compiler Sie vielleicht vor einem fehlenden Fall COUNT: warnen), können Sie dies tun:

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

2voto

user2407277 Punkte 19

Für MS-Compiler:

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

Hinweis: Dies ist viel weniger Code als die einfache Antwort des benutzerdefinierten Iterators mit Vorlage.

Sie können dies mit GCC zum Laufen bringen, indem Sie typeof anstelle von decltype aber ich habe den Compiler im Moment nicht zur Hand, um sicherzustellen, dass er kompiliert.

1voto

LAL Punkte 472

In Bjarne Stroustrups Buch über die Programmiersprache C++ können Sie lesen, dass er vorschlägt, die operator++ für Ihr spezielles enum . enum sind benutzerdefinierte Typen, und für diese speziellen Situationen gibt es in der Sprache Überladungsoperatoren.

Sie können die folgenden Codes eingeben:

#include <iostream>
enum class Colors{red, green, blue};
Colors& operator++(Colors &c, int)
{
     switch(c)
     {
           case Colors::red:
               return c=Colors::green;
           case Colors::green:
               return c=Colors::blue;
           case Colors::blue:
               return c=Colors::red; // managing overflow
           default:
               throw std::exception(); // or do anything else to manage the error...
     }
}

int main()
{
    Colors c = Colors::red;
    // casting in int just for convenience of output. 
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    return 0;
}

Test-Code: http://cpp.sh/357gb

Beachten Sie, dass ich die enum class . Der Code funktioniert gut mit enum auch. Aber ich bevorzuge enum class da sie stark typisiert sind und verhindern können, dass wir bei der Kompilierung Fehler machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X