Gesucht: Mapping Konstante -(compiletime)-> string -(runtime)-> Konstante && Konstante -(compiletime)->
-
Folgendes Szenario:
Ich habe eine Handvoll Eventklassen, die jeweils aus 1) einem Tag ("Category") und b) einem Datenfeld bestehen, wobei das Datenfeld von Event zu Event unteschiedliche Typen hat, abhängig vom Tag. Beispiel:
Klasse ServerEvent, mapping: Tag SEVT1 -> void Tag SEVT2 -> string Tag SEVT3 -> int Klasse ClientEvent, mapping: Tag CEVT1 -> bool Tag CEVT2 -> FooBar ...Hab ich soweit ganz gut umsetzen können, wobei das Tag jeweils ein eigenes Enum ist, das Mapping wird über ein passendes Template (Traits) gepflegt. Der Nachteil: ich muss die Deklarationen der verschiedenen Tags (enum-Werte) zuerst schreiben und getrennt davon das Mapping, muss also jeden enum-Wert zweimal angeben:
struct ClientEventCategory_t { enum ValueType { PING, CUSTOM, /* ... */ }; struct ErrorUnmappedDataType; template <ValueType enumerator> struct Traits { typedef ErrorUnmappedDataType type; }; }; #define CATEGORY_MAP(cat, thetype) \ template<> \ struct ClientEventCategory_t::Traits<ClientEventCategory_t::cat> \ { \ typedef thetype type; \ } CATEGORY_MAP(PING, void); CATEGORY_MAP(CUSTOM, std::string); /* ... */ #undef CATEGORY_MAPDie eigentliche Definition der Event-Klasse erfolgt dann simpel über Instanziierung eines fertigen EventBase-Templates mit dem struct.
Was mir jetzt noch fehlt: Serialisierung/Deserialisierung der Events, ich möchte sie als xmls abspeichern/verschicken können. Dazu bräuchte ich ein weiteres Mapping Tag<->String, wobei die eine Richtung Tag->String zur Compilezeit möglich sein sollte, die andere zur Laufzeit. Ich hatte an eine map gedacht, die durch dynamische Initialisierung von irgendwelchen statischen Konstanten belegt wird. Das bedeutet aber, dass ich jeden Tag ein bis zwei weitere Male erwähnen muss - zur Belegung der Map und für das Compiletime-Mapping. Der Wartbarkeit wegen hätte ich am Liebsten aber, dass eine einmalige Erwähnung des Tags schon genügen würde, mit einem entsprechend komplexeren Makro. Mir ist dabei klar, dass die Tags dann keine enum-Werte mehr sein können sondern irgendwelche statischen Konstanten sein müssten.
Erschwerend kommt zum Ganzen hinzu, dass ich unter MSVC2010 entwickle und deshalb constexpr etc. nicht verfügbar sind.
Ich hoffe die Idee kommt in etwa rüber - hat jemand Vorsachläge? Der Wunschcode sieht in etwa so aus:DEFINE_EVENT_CLASS(ClientEvent) { ADD_TAG(PING, void); ADD_TAG(CUSTOM, std::string); /* ... */ };
-
Guck Dir mal
BOOST_FUSION_DEFINE_STRUCTaus, naja,boost.fusionan. Da sollte der passende Code drin stehen.PS: Den enum würde ich dabei allerdings direkt aus dem Tags erzeugen und dann über die Eventklasse exponieren.
-
Seien wir doch mal ehrlich pumuckl. Mit über 6000 Posts hätte ich jetzt erwartet, dass du wenigstens einmal irgendwo das Wort Reflections benutzt.
Zumindest kommt mir so vor als würdest du um dieses Problem herumarbeiten.
Lösungsansätze:
1. Nutzung von entspr. serialisierungs-Frameworks wie boost serialization.2. Nutzung von einem Code-Generator.
Bei unserer Game-Engine liegen die Event-Typen und entspr. Enums als Primär-Quelle in XML vor. Aus dem XML werden dann verschiedene C++-Klassen/Code generiert, bspw. Enum-Listen.
Läßt sich in Visual Studio wunderbar einbinden, als Pre-Compile-Step.
-
nurf schrieb:
Seien wir doch mal ehrlich pumuckl. Mit über 6000 Posts hätte ich jetzt erwartet, dass du wenigstens einmal irgendwo das Wort Reflections benutzt.
Hätte ich nicht erwartet. Ganz und gar nicht mit diesem s am Ende.