VS2013.4 variadic macros: std::array<std::string,.. füllen



  • Hallo!

    Wie man im Code sehen kann, hätte ich gerne in type[0] "E1" und in type[1] "E2" stehen.
    Ist das irgendwie möglich?

    Leider steht so in type[0] "E1, E2" und type[1] ist leer:

    #define EXPAND(x) x
    #define ARG_N(_1,_2,_3,_4,_5,_6,N,...) N
    #define NARG_(...) EXPAND(ARG_N(__VA_ARGS__))
    #define NARG(...) NARG_(__VA_ARGS__,6,5,4,3,2,1,0)
    
    #define DefineClass(name, ...) \
    class name \
    { \
    public: \
    	std::array<std::string, NARG(__VA_ARGS__)> type; \
    public: \
    	enum Type \
    	{ \
    		__VA_ARGS__ \
    	}; \
    	name() : type({#__VA_ARGS__}){ } \
    };
    
    DefineClass(Test1, E1, E2);
    
    int main()
    {
    	Test1 t;
    
    	cout << t.type[0] << endl; // "E1, E2"
    	cout << t.type[1] << endl; // "" (leer)
    }
    

    Eine weitere Frage noch: Geht das mit dem NARG(__VA_ARGS__) als array-Größe noch einfacher?

    Danke!



  • Ahh, sry, ich hätte das enum drin lassen sollen.
    Ich möchte nämlich sowohl ein enum als auch ein string-array erstellen.

    Es kommt also noch Folgendes in die Klasse (das funktioniert):

    enum Type \
    { \
    	__VA_ARGS__ \
    }; \*/
    


  • Hmm, ich mach das jetzt so:

    #define EXPAND(x) x
    #define ARG_N(_1,_2,_3,_4,_5,_6,N,...) N
    #define NARG(...) EXPAND(ARG_N(__VA_ARGS__,6,5,4,3,2,1,0))
    
    #define DefineClass(name, ...) \
    class name##_hlp \
    { \
    public: \
    	std::array<std::wstring, NARG(__VA_ARGS__)> type; \
    	name##_hlp() : type({{L#__VA_ARGS__}}){ auto t = Tokenize(type[0], L','); int c = 0; for(auto x : t) type[c++] = TrimString(x); } \
    }; \
    name##_hlp _##name##_hlp; \
    class name \
    { \
    public: \
    	enum Type \
    	{ \
    		__VA_ARGS__ \
    	}; \
    public: \
    	name() { } \
    	std::wstring GetStr(unsigned int type) { return _##name##_hlp.type[type];} \
    };
    
    DefineClass(Test1, E1, E2, E3);
    DefineClass(Test2, E4, F5);
    
    int main()
    {
    	Test1 t;
    	Test2 t2;
    
    	wcout << t.GetStr(Test1::E2) << endl; // "E2" juhuu
    	wcout << t2.GetStr(Test2::F5) << endl; // "F5"
    }
    

    Ist zwar irgendwie etwas unschön, aber immerhin nur an einer Stelle 😃
    Außerdem wird das Array so nur einmalig beim Programmstart mit Tokenize/TrimString initialisiert, und nicht mit jeder Instanz von Test1 etc.

    Weiß wer wie's besser geht? 🙂



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum Compiler- und IDE-Forum in das Forum C++ (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Anmelden zum Antworten