Grösse von enums
-
Skym0sh0 schrieb:
die idee mit Macros find ich auch cool dazu auch ne frage
Da würd ich vorsichtig sein. Nur um einen
Last-Enumerator nicht hinzuschreiben das Ganzeenumzu obfuscaten lohnt sich vielleicht nicht. Vor allem wenn andere den Code lesen (oder du nach einiger Zeit), kommen vielleicht Fragen und Unklarheiten auf.Skym0sh0 schrieb:
wieso das struct
Damit du qualifizierte Bezeichner hast: Statt
Color a = Green;nimmst du
Color::Type a = Color::Green;Damit verhinderst du auch Namenskonflikte.
Skym0sh0 schrieb:
zu enums noch
wenn ich die enum einträge selbst mit zahlen versehe, dann wird der nächste eintrag ohne explizite zahl um eins einfach erhört?!?Ja. Jeder Enumerator hat den Wert des Vorgängers + 1, wenn nichts angegeben wird. Der erste Enumerator entspräche dann dem Wert 0.
-
Ich schlag einfach mal Metaprogrammierung vor, weil ich die
Idee eigentlich gar nicht sooo schlecht finde:#include<iostream> template<typename T> int enumSize(const T& t){ throw "size not available for enum"; } enum foo { eins, zwei, drei }; template<> int enumSize(const foo& t){ return 3; } enum bar { rot, blau }; template<> int enumSize(const bar& t){ return 2; } int main() { std::cout << enumSize(eins) << std::endl; std::cout << enumSize(rot) << std::endl; return 0; }Ausgabe:
3 2Gruß,
XSpilleEDIT: Kann ich eigentlich irgendwie einen aussagekräftigen Compiler-Fehler erzwingen statt des Werfen einer Exception?
-
#error Ganz böser schlimmer Fehler!
-
XSpille schrieb:
EDIT: Kann ich eigentlich irgendwie einen aussagekräftigen Compiler-Fehler erzwingen statt des Werfen einer Exception?
Indem man die allgemeine Variante nur deklariert aber nicht definiert. Im Übrigen kann man sich aber den Zirkus mit den Templates sparen, da man das auch über ganz normale Funktionsüberladung hinbekommt. Trotzdem ist es aber unhandlich, weil man für jedes enum eine eigene Funktion schreiben muss.
-
XSpille schrieb:
Ich schlag einfach mal Metaprogrammierung vor, weil ich die
Idee eigentlich gar nicht sooo schlecht finde:#include<iostream> template<typename T> int enumSize(const T& t){ throw "size not available for enum"; } enum foo { eins, zwei, drei }; template<> int enumSize(const foo& t){ return 3; } enum bar { rot, blau }; template<> int enumSize(const bar& t){ return 2; } int main() { std::cout << enumSize(eins) << std::endl; std::cout << enumSize(rot) << std::endl; return 0; }Du mischst hier gerade zwei Konzepte: Funktionsüberladung und Type-Traits. Wenn schon würde ich wegen der Compilezeit-Auswertung zu Traits tendieren, aber das hat gegenüber eines
Count-Enumerators nur Nachteile. Du brauchst zusätzlichen Code, verkomplizierst das Ganze für nichts und riskierst sehr schnell Inkonsistenzen. Von daher würde ich diesen Ansatz in der Praxis nicht verwenden.
-
Mit einem static_assert geht das. Entweder selber schreiben oder vom Compiler das nutzen (falls vorhanden).
-
RedPuma schrieb:
#error Ganz böser schlimmer Fehler!
Da Preprozessordirektiven vorm Compilieren ausgeführt werden,
kriegt man den Fehler dann immeripsec schrieb:
Indem man die allgemeine Variante nur deklariert aber nicht definiert.
hmm... Kein Kommentar... Manchmal steht man auf dem Schlauch

-
Wenn ich das richtig verstanden habe, meinst du das mit dem
Type traits Ansatz so (auch wenn du ihn nicht verwenden würdest):#include<iostream> template<typename T> int enumSize(); enum foo { eins, zwei, drei }; template<> int enumSize<foo>(){ return 3; } enum bar { rot, blau }; template<> int enumSize<bar>(){ return 2; } int main() { std::cout << enumSize<foo>() << std::endl; std::cout << enumSize<bar>() << std::endl; return 0; }Sehe ich das richtig?
-
Fast. Funktionen kannst du nicht zur Kompilierzeit ausführen, deshalb greift man zu Metafunktionen (Klassen, die zur Metaprogrammierung verwendet werden).
enum A {...}; enum B {...}; template <typename Enum> struct EnumSize; template <> struct EnumSize<A> { static const size_t value = 4; }; template <> struct EnumSize<B> { static const size_t value = 5; };
-
Nexus schrieb:
Fast. Funktionen kannst du nicht zur Kompilierzeit ausführen, deshalb greift man zu Metafunktionen (Klassen, die zur Metaprogrammierung verwendet werden).
enum A {...}; enum B {...}; template <typename Enum> struct EnumSize; template <> struct EnumSize<A> { static const size_t value = 4; }; template <> struct EnumSize<B> { static const size_t value = 5; };MERCI!!!