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
?
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
?
Sie können versuchen, das folgende Makro zu definieren:
#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))
Jetzt können Sie es verwenden:
enum Count { zero, one, two, three };
for_range (Count, c, zero, three)
{
cout << "forward: " << c << endl;
}
Sie kann verwendet werden, um vorwärts und rückwärts durch vorzeichenlose Zahlen, Ganzzahlen, Enums und Zeichen zu iterieren:
for_range (unsigned, i, 10,0)
{
cout << "backwards i: " << i << endl;
}
for_range (char, c, 'z','a')
{
cout << c << endl;
}
Trotz seiner umständlichen Definition ist er sehr gut optimiert. Ich habe mir den Disassembler in VC++ angesehen. Der Code ist extrem effizient. Lassen Sie sich nicht von den drei for-Anweisungen abschrecken: Der Compiler erzeugt nach der Optimierung nur eine einzige Schleife! Sie können sogar eingeschlossene Schleifen definieren:
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;
}
Sie können natürlich nicht durch Aufzählungstypen mit Lücken iterieren.
Hier sind einige sehr lesenswerte und leicht verständliche Ansätze, sowohl für schwach getippt C und C++ regulär enum
s, et stark getippt C++ enum class
es.
Ich empfehle die Kompilierung aller folgenden Beispiele mit -Wall -Wextra -Werror
. Dies gibt Ihnen die zusätzliche Sicherheit, dass Sie, wenn Sie vergessen, einen Enum-Wert in der switch
Fall wird Ihr Compiler einen Kompilierfehler auslösen ! Dies zwingt Sie dazu, Ihre Enum-Definition und die Switch-Cases synchron zu halten, was eine zusätzliche Sicherheitsmaßnahme für Ihren Code darstellt. Dieser Tipp funktioniert so lange, wie Sie:
switch
Fall, unddefault
Fall wechseln.-Wall -Wextra -Werror
Flaggen.Ich empfehle Ihnen, alle 3 Punkte zu befolgen, da dies eine gute Praxis ist und besseren Code erzeugt.
enum
:C-Definition (dies gilt auch für C++):
typedef enum my_error_type_e
{
MY_ERROR_TYPE_SOMETHING_1 = 0,
MY_ERROR_TYPE_SOMETHING_2,
MY_ERROR_TYPE_SOMETHING_3,
MY_ERROR_TYPE_SOMETHING_4,
MY_ERROR_TYPE_SOMETHING_5,
/// Not a valid value; this is the number of members in this enum
MY_ERROR_TYPE_count,
// helpers for iterating over the enum
MY_ERROR_TYPE_begin = 0,
MY_ERROR_TYPE_end = MY_ERROR_TYPE_count,
} my_error_type_t;
C++ Definition:
enum my_error_type_t
{
MY_ERROR_TYPE_SOMETHING_1 = 0,
MY_ERROR_TYPE_SOMETHING_2,
MY_ERROR_TYPE_SOMETHING_3,
MY_ERROR_TYPE_SOMETHING_4,
MY_ERROR_TYPE_SOMETHING_5,
/// Not a valid value; this is the number of members in this enum
MY_ERROR_TYPE_count,
// helpers for iterating over the enum
MY_ERROR_TYPE_begin = 0,
MY_ERROR_TYPE_end = MY_ERROR_TYPE_count,
};
C oder C++-Iteration über diese Schwach getippt enum:
Hinweis: Das Inkrementieren einer Aufzählung durch my_error_type++
es no erlaubt - nicht einmal bei Enums im C-Stil, also müssen wir dies stattdessen tun: my_error_type = (my_error_type_t)(my_error_type + 1)
. Beachten Sie, dass my_error_type + 1
ist erlaubt, da diese schwache Aufzählung automatisch in eine int
hier, um diesen Zusatz zu ermöglichen, ohne dass er manuell in einen int wie diesen umgewandelt werden muss: my_error_type = (my_error_type_t)((int)my_error_type + 1)
.
for (my_error_type_t my_error_type = MY_ERROR_TYPE_begin;
my_error_type < MY_ERROR_TYPE_end;
my_error_type = (my_error_type_t)(my_error_type + 1))
{
switch (my_error_type)
{
case MY_ERROR_TYPE_SOMETHING_1:
break;
case MY_ERROR_TYPE_SOMETHING_2:
break;
case MY_ERROR_TYPE_SOMETHING_3:
break;
case MY_ERROR_TYPE_SOMETHING_4:
break;
case MY_ERROR_TYPE_SOMETHING_5:
break;
case MY_ERROR_TYPE_count:
// This case will never be reached.
break;
}
}
enum class
:C++ Definition:
enum class my_error_type_t
{
SOMETHING_1 = 0,
SOMETHING_2,
SOMETHING_3,
SOMETHING_4,
SOMETHING_5,
/// Not a valid value; this is the number of members in this enum
count,
// helpers for iterating over the enum
begin = 0,
end = count,
};
C++-Iteration über diese stark getippt enum:
Beachten Sie die zusätzliche (size_t)
Besetzung (oder (int)
wäre auch akzeptabel) erforderlich, um die enum class
variabel! Ich habe mich auch für die Verwendung der C++-ähnlichen static_cast<my_error_type_t>
hier, sondern ein C-Stil (my_error_type_t)
Guss, wie oben beschrieben, wäre auch in Ordnung gewesen.
for (my_error_type_t my_error_type = my_error_type_t::begin;
my_error_type < my_error_type_t::end;
my_error_type = static_cast<my_error_type_t>((size_t)my_error_type + 1))
{
switch (my_error_type)
{
case my_error_type_t::SOMETHING_1:
break;
case my_error_type_t::SOMETHING_2:
break;
case my_error_type_t::SOMETHING_3:
break;
case my_error_type_t::SOMETHING_4:
break;
case my_error_type_t::SOMETHING_5:
break;
case my_error_type_t::count:
// This case will never be reached.
break;
}
}
Beachten Sie auch das Scoping. In der C++ stark getippt enum class
Ich habe my_error_type_t::
für den Zugriff auf jede scoped enum class
Mitglied. Aber im C-Stil schwach getippt regelmäßig enum
kann, wie ich gezeigt habe, eine sehr ähnliche Einteilung erreicht werden, indem man einfach jedem enum
Mitgliedsname mit MY_ERROR_TYPE_
. Die Tatsache, dass die C++ stark getippt enum class
Der Zusatz "Scoping" bringt keinen wirklichen Mehrwert - es ist wirklich nur eine persönliche Vorliebe in dieser Hinsicht. Und die Tatsache, dass die C++ stark getippt enum class
hat eine zusätzliche Typensicherheit, die Vor- und Nachteile hat. Es kann Ihnen in einigen Fällen helfen, aber es macht auf jeden Fall die Inkrementierung der Aufzählung und Iteration über sie ein pain-in-the-butt, die, ehrlich gesagt, bedeutet es seine Arbeit tut. Indem man es härter zur Erhöhung der skalierten enum class
Variable wie eine Ganzzahl, die C++ stark getippt enum class
tut genau das, wofür es entwickelt wurde . Ob Sie nun wollen Dieses Verhalten ist Ihnen überlassen. Ich persönlich mache häufig no wollen dieses Verhalten, und so ist es nicht ungewöhnlich, dass ich es vorziehe, Enums im Stil von C auch in C++ zu verwenden.
enum class
es ( stark getippt Enums) und reguläre enum
s ( schwach getippt enums) in C++: Wie konvertiert man automatisch stark typisierte enum in int?-Wall -Wextra -Werror
und andere Bauoptionen von meinem eRCaGuy_hello_world Repo.Hier ist eine andere Lösung, die nur für zusammenhängende Enums funktioniert. Es gibt die erwartete Iteration, mit Ausnahme der Hässlichkeit im Inkrement, wo es hingehört, denn das ist, was in C++ kaputt ist.
enum Bar {
One = 1,
Two,
Three,
End_Bar // Marker for end of enum;
};
for (Bar foo = One; foo < End_Bar; foo = Bar(foo + 1))
{
// ...
}
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.