char[] to enum mithilfe des Präprozessors
-
Hallo zusammen,
ich kodiere eine Liste von Topics intern als enum. Ein Topic ist zunächst nichts anderes als ein String. Im folgenden Beispiel verwende ich drei Topics, nämlich TOPIC_1, TOPIC_2, TOPIC_3. Alle Topics sind zur Kompilierzeit bekannt:
#define FOREACH_MESSAGE_TYPE(C) C(TOPIC_1) C(TOPIC_2) C(TOPIC_3) #define GENERATE_ENUM(x) x, enum message_type { FOREACH_MESSAGE_TYPE(GENERATE_ENUM) }; int main() { enum message_type current_topic = TOPIC_2; printf("%d\n", current_topic); return 0; }
Nun möchte ich die TOPICs am liebsten in einer externen Datei verwalten, sodass man diese einfach anpassen kann. Besteht die Möglichkeit, mithilfe des Präprozessors, das enum message_type anhand solch einer Datei zu generieren?
Bis jetzt wandelt mir ein kleines Script einfach den Dateiinhalt in entsprechenden C-Code um, jedoch frage ich mich, ob es auch schöner (sprich ohne zusätzliches Script) geht.
Über Anregungen wäre ich dankbar.
Viele Grüße
-
Ich würde bei einem Script bleiben, da die Arbeit mit der generierten Datei mit "normaler" Syntax den meisten Leute wesentlich einfacher fallen wird.
-
Wenn in der externen Datei die Werte einfach auch mit Komma separiert sind, dann würde es einfach so funktionieren:
enum message_type { #include "message_types.txt" };
-
@freakC sagte in char[] to enum mithilfe des Präprozessors:
#define FOREACH_MESSAGE_TYPE(C) C(TOPIC_1) C(TOPIC_2) C(TOPIC_3)
Besteht die Möglichkeit, mithilfe des Präprozessors, das enum message_type anhand solch einer Datei zu generieren?
Du kannst das
#define FOREACH_MESSAGE_TYPE
in ein eigenes Header-File packen. Damit es etwas übersichtlicher wird kannst du es mit Zeilenumbrüchen formatieren:#define FOREACH_MESSAGE_TYPE(C) \ C(TOPIC_1) \ C(TOPIC_2) \ C(TOPIC_3) \ // end FOREACH_MESSAGE_TYPE
Dabei musst du nur aufpassen dass kein weiteres Zeichen nach dem
\
mehr kommt - nichtmal ein Leerzeichen.
-
@hustbaer: Die beiden
#define
-Zeilen sind doch unsinnig. Warum dann nicht direktTOPIC_1, TOPIC_2, TOPIC_3
in denenum
-Body schreiben?
-
@Th69
Das ist ein X-Makro (bzw. eine leicht abgewandelte Form davon).
Die verwendet man normalerweise wenn man die Liste mehrfach braucht.
z.B. um automatisch eine "to-string" oder "from-string" Funktion für den enum zu implementieren.#define FOREACH_FOO(X) X(TOPIC_1) X(TOPIC_2) X(TOPIC_3) #define GENERATE_ENUM(name) name, enum Foo { FOREACH_FOO(GENERATE_ENUM) }; #define GENERATE_TO_STRING(name) case name: return #name; char const* fooToString(Foo f) { switch (f) { FOREACH_FOO(GENERATE_TO_STRING) } } #define GENERATE_FROM_STRING(name) if (strcmp(s, #name) == 0) return name; Foo fooFromString(char const* s) { FOREACH_FOO(GENERATE_FROM_STRING) throw std::invalid_argument("meh"); } // ...
-
Okay, danke für eure Hinweise.
Und ja, ich verwende die Makros vor allem für die Rückübersetzung des Enums in einen String.
Viele Grüße