Wie kann ich eine enum-Klasse in einem booleschen Kontext?
Habe ich einige generische code, der funktioniert mit den flags angegeben, die mit C++11 enum class
Arten. In einem Schritt, ich würde gerne wissen, ob irgendwelche bits im flag gesetzt sind. Derzeit bin ich mit dem code:
if (flags != static_cast<E>(0)) //Works, but ugly.
Konnte ich mich auch zwingen Benutzer, um geben Sie einen bestimmten Namen für einen all-null-Feld, das ist mehr lesbar, aber schränkt meine Namenskonventionen auf jeden es zu benutzen:
if (flags != E::none) //Works, if you manually define none = 0.
Aber weder dieser liest sich so schön wie die traditionellen:
if (flags) //Doesn't work with class enums.
Ist es möglich, geben Sie eine benutzerdefinierte Funktion auswerten eine Klasse enum in einem booleschen Kontext?
- Gibt es einen bestimmten Grund, warum Sie nicht verwenden können, binäre flags? Sie sind sauber und effizient. Jedenfalls, enum-Klasse können keine Werte in zahlen umgewandelt werden. Sie haben auf die use-flags != E::keine wenn Sie aufzählen. Sie wissen, können Sie nur eine nicht-enum-Klasse und mit static const int was = 1, static const int whatever_else = 2...usw. und überlastung nur wenige Betreiber.
- flags", was bedeutet was, bools? Als bitfields sind Sie oft IB/UB und mit der regelmäßigen Ausrichtung, ich würde nicht nennen Sie effizient, noch sauber, wenn ich brauche zu kopieren mehrere Dateien auf einmal. Ich sehe nicht den Wert in was static ints, konnte ich nur mit einem enum-und zumindest ein wenig Typ-Sicherheit.
- "Ich konnte nur mit einem enum-und zumindest ein wenig Typ-Sicherheit." Dann müssen Sie akzeptieren, dass zusammen mit, dass Sie nicht mehr zu sprechen, über die bits.
- Nein, habe ich nicht; eines der grundlegenden Punkte der enum-Klassen ist, dass Sie typesafe Möglichkeiten der Benennung einer bestimmten (set) - Wert-Darstellung(en). Es ist absolut gut zu sprechen, sowohl von bits und Typ-Sicherheit.
- Sie reden über bits, die von bestimmten benannten Konstanten, sicher, aber nicht über die enum-Wert im Allgemeinen. Dies ist durch design und eine Gute Sache.
- Enum-Klassen entfernen der implizite cast auf int, aber nicht verstecken oder ändern Sie den Wert der Repräsentation. Sie noch den Wert angeben, buchstäblich, können Sie immer noch static_cast eher als reinterpret_cast, und Sie können immer noch std::underlying_type.
- In der Tat, wir Stimmen alle dafür. Aber diese Dinge existieren nur, um von enum zu den zugrunde liegenden Typ und zurück, nicht zu gehen von einem bestimmten Allgemeinen Wert des zugrunde liegende Typ der Enumeration.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, aber nicht automatisch. Manuell aufrufen einer Funktion ist immer noch eleganter als die anderen alternativen.
Wählen Sie einfach eine nette Funktion name, wie
any
und umzusetzen. Überlast Auflösung stellen Sie sicher, Ihre Funktion spielt gut mit allen anderen.Sieht nett genug, um mich.
Update:, wenn Sie wollen diese anwenden, um verschiedene enumeration-Typen, kann es sein, Vorlagen:
Ich habe mit dieser Art von Mechanismus auch für andere Dinge, und nie auf irgendwelche Nebenwirkungen oder Probleme :v) .
Könnten Sie überspringen Sie die Eigenschaft, und legen Sie die SFINAE Zustand zu so etwas wie
enum_type::none == enum_type::none
nur überprüfen Sie das Vorhandensein vonnone
und der Gleichheits-operator, aber das wäre weniger explizite und sicher.Wie @RMatin sagt. Aber Sie könnten zu einer überlastung
operator!
So dass Sie verwenden können, die
!!e
idiomWenn Sie ein flags-Feld (dh: ein Bitfeld) ich würde stark beraten Sie nicht verwenden
enum class
für bitfields.Stark typisierte enums vorhanden sein stark typisierte. Es macht die Enumeratoren in etwas mehr als nur benannte Konstante Ganzzahlen, die den Weg regelmäßig enums sind. Die Idee ist, dass, wenn Sie eine variable eines
enum class
geben, so ist Ihr Inhalt sollte immer genau mit einem von der enumerator-Werte. Das ist, warum gibt es keine implizite Konvertierung von oder zu den integer-Typen.Aber das ist nicht das, was du tust. Du nimmst ein Bitfeld, das ist eine Komposition von Enumerators Werte. Diese Komposition ist nicht selbst eines dieser Werte; es ist eine Kombination von Ihnen. Daher sind Sie liegen, wenn Sie sagen, dass Sie unter der
enum class
Art; Sie sind wirklich nur für eine vorzeichenlose Ganzzahl, die könnte einer derenum class
aufgelistet.Beispiel:
val
in diesem Fall nicht enthaltenFirst
,Second
oderThird
. Sie haben verloren starke Typisierung, da Sie nicht enthalten keine der Arten.enum class
Werte nicht implizit konvertiert werden können, um bool; Sie können nicht implizit in Ganzzahlen konvertiert; und Sie können nicht implizit haben die meisten mathematischen Operationen auf diese. Sie sind undurchsichtig Werte.Und damit sind Sie ungeeignet für die Verwendung als bitfields. Der Versuch, mit
enum class
in solch unangemessener Weise führt das nur zu viel Gießen. Verwenden Sie einfach regelmäßig alteenum
und sparen Sie sich den Schmerz.enum
s sind ideal für Gruppen von flags. Das problem mit der ideone Beispiel ist, dass dieoperator|
überlastung fehlt.enum
Typen definiert sind, Folgen Sie den Wert Semantik der zugrunde liegende Typ, und wenn das unterstützt die bitweise Arithmetik, geben Sicherheit und rechnerische Sicherheit sind beide optimiert.enum class
es nicht.enum class
Werte Folgen nicht Wert-Semantik. Sie sind stark typisierte; Sie sind nur für die Speicherung von einer der Enumerationswerte. So kann man nicht einfach jede Mathe auf Sie. Beachten Sie, dass die Ideaone code funktioniert, wenn Sie es ändern, umenum
eher alsenum class
. Es ist auch illegal, die zahlen speichern, in einerenum class
Variablen ohne expliziten cast. Also selbst wennoperator|
gearbeitet, Sie müssen noch eine Besetzung, nur um speichern Sie die resultierende Wert.enum class
statt einerenum
? Wenn Sie nur gehen, um cast away alle die starke Typisierung, es gibt wirklich keinen Sinn, es zu benutzen.e1 | e2
für old-style-Zähler setzt auf die Umwandlung inint
ersten. Es gibt keine Beziehung "Wert-Semantik" von einem enum-Typ gibt.enum class
ist nur in der Regel sicherer alsenum
. Es würde eine Menge Arbeit, um wirklich alle beseitigen zusätzliche Sicherheit.enum
hat keine überladene operator für jetzt, so wickeln Sie es in einclass
oderstruct
.Nein, nicht so. Konvertierung müssen die Betreiber Mitglieder, und Enumerationen, die keine Mitglieder haben. Ich denke, das beste, was Sie tun können, ist der Vergleich mit
none
oder, wenn es nicht einenone
enumerator, wickeln Sie diestatic_cast
in einer Funktion.Ich in der Regel überladen unärer
+
Betreiber für flag-wieenum classes
, so dass ich Folgendes tun können:Ein kurzes Beispiel für enum-flags unten.
ENUM_FLAGS(T) ist ein makro, definiert in enum_flags.h (weniger als 100 Zeilen, frei verwenden, ohne Einschränkungen).