Variable mit selben Groß und Kleingeschreiben in Macro



  • Lass so einen Spass bleiben. Du verlierst sämtlichen Überblick und dein Code ist schwer zu debuggen und absolut nicht anpassungsfähig, also individualisierbar.



  • für diejenigen, die den Präprozessor nicht aus ideologischen Gründen ablehnen, geht auch folgendes. das verschachtelte MAKESTR hängt mit der internen Arbeitsweise des Präprozessors zusammen

    #define BIG_LETTER_a A
    #define BIG_LETTER_b B
    #define BIG_LETTER_p P
    #define BIG_LETTER_w W
    
    #define BIG_LETTER(X) BIG_LETTER_ ## X
    
    #define MAKESTR_(X) # X
    #define MAKESTR(X) MAKESTR_(X)
    #define CONC1(X,Y) X ## Y
    #define CONC2(X,Y) BIG_LETTER(X) ## Y
    
    struct eFruit
    {
        enum Enum
        {
            Apple,
            Banana,
            Watermelon,
            Pear
        };
    };
    
    struct FruitBase {std::string name; eFruit::Enum type;};
    
    #define MAKE_FRUIT(X,Y) template <typename T> struct CONC1(X,Y) : public FruitBase \
    { \
      CONC1(X,Y)() \
      { \
        name = MAKESTR(CONC1(X,Y)); \
        type = eFruit::CONC2(X,Y); \
      } \
    }
    
    MAKE_FRUIT(a,pple);
    MAKE_FRUIT(b,anana);
    MAKE_FRUIT(w,atermelon);
    MAKE_FRUIT(p,ear);
    

    expandiert (cl /P) sieht es dann so aus:

    template <typename T> struct apple : public FruitBase { apple() { name = "apple"; type = eFruit::Apple; } };
    template <typename T> struct banana : public FruitBase { banana() { name = "banana"; type = eFruit::Banana; } };
    template <typename T> struct watermelon : public FruitBase { watermelon() { name = "watermelon"; type = eFruit::Watermelon; } };
    template <typename T> struct pear : public FruitBase { pear() { name = "pear"; type = eFruit::Pear; } };
    


  • ...



  • Wieso einfach wenns kompliziert auch geht, nen?

    Einfach:

    MAKE_FRUIT(apple, eFruit::Apple)
    


  • hustbaer schrieb:

    Wieso einfach wenns kompliziert auch geht, nen?

    Einfach:

    MAKE_FRUIT(apple, eFruit::Apple)
    

    ich denke, dass es auch irgendwie mit

    MAKE_FRUIT(apple);
    

    geht - boost hat ja eine sehr schöne preprocessor library (http://www.boostpro.com/mplbook/preprocessor.html) und dd++ hat glaube ich dazu schon die richtige Richtung eingeschlagen - aber

    MAKE_FRUIT(apple, eFruit::Apple)
    

    scheint tatsächlich am sinnvollsten zu sein - stifte am wenigsten Verwirrung - es wäre schön wenn man auch noch verhindern könnte das jemand

    MAKE_FRUIT(apple, eFruit::Banana)
    

    macht - ob man das irgendwie mit einem static_assert hinbekommt...



  • Agin34 schrieb:

    hustbaer schrieb:

    Wieso einfach wenns kompliziert auch geht, nen?

    Einfach:

    MAKE_FRUIT(apple, eFruit::Apple)
    

    ich denke, dass es auch irgendwie mit

    MAKE_FRUIT(apple);
    

    geht - boost hat ja eine sehr schöne preprocessor library (http://www.boostpro.com/mplbook/preprocessor.html) und dd++ hat glaube ich dazu schon die richtige Richtung eingeschlagen

    Ich bin mir ziemlich sicher dass es nicht geht.
    Der C++ PP bietet zwar Operatoren mit dem man zwei Tokens zusammenpappen kann, aber soweit ich weiss keine Möglichkeit ein Token in mehrere Teile zu zerlegen.

    - aber

    MAKE_FRUIT(apple, eFruit::Apple)
    

    scheint tatsächlich am sinnvollsten zu sein - stifte am wenigsten Verwirrung

    Ja.
    Mit "einfach" meine ich ja nicht (nur) einfach anzuwenden, sondern auch einfach zu schreiben, zu warten und vor allem zu verstehen wenn man den Code liest.
    Selbst wenn es eine Boost.PP Lösung geben sollte (was ich wie gesagt bezweifle) ist davon auszugehen dass diese nicht gerade einfach zu schreiben und/oder verstehen wäre.

    - es wäre schön wenn man auch noch verhindern könnte das jemand

    MAKE_FRUIT(apple, eFruit::Banana)
    

    macht - ob man das irgendwie mit einem static_assert hinbekommt...

    Also mir fallen da nur extrem hässliche Lösungen ein, und ganz spontan auch nichts was ohne constexpr auskommen würde.



  • hustbaer schrieb:

    Der C++ PP bietet zwar Operatoren mit dem man zwei Tokens zusammenpappen kann, aber soweit ich weiss keine Möglichkeit ein Token in mehrere Teile zu zerlegen.

    Natürlich ist das möglich bis zu einer festen Länge. 😉

    #define HEAD_aaa a
    #define HEAD_aaA a
    #define HEAD_aAa a
    #define HEAD_aAA a
    #define HEAD_Aaa A
    #define HEAD_AaA A
    #define HEAD_AAa A
    #define HEAD_AAA A
    //...
    
    #define TAIL_aaa aa
    #define TAIL_aaA aA
    #define TAIL_aAa Aa
    #define TAIL_aAA AA
    #define TAIL_Aaa aa
    #define TAIL_AaA aA
    #define TAIL_AAa Aa
    #define TAIL_AAA AA
    //...
    
    #define TO_UPPER_a A
    #define TO_UPPER_A A
    //...
    
    #define CAPITALIZE5(head, tail) head ## tail
    #define CAPITALIZE4(head, tail) CAPITALIZE5(head, tail)
    #define CAPITALIZE3(head, tail) CAPITALIZE4(TO_UPPER_ ## head, tail)
    #define CAPITALIZE2(head, tail) CAPITALIZE3(head, tail)
    #define CAPITALIZE(x) CAPITALIZE2(HEAD_ ## x, TAIL_ ## x)
    
    #define AAA 3
    #define Aaa 4
    
    static_assert(CAPITALIZE(aAA) == AAA, "");
    static_assert(CAPITALIZE(AAA) == AAA, "");
    
    static_assert(CAPITALIZE(aaa) == Aaa, "");
    static_assert(CAPITALIZE(Aaa) == Aaa, "");
    


  • ich mache es jetzt so:

    MAKE_FRUIT(apple, eFruit::Apple);
    

    in meinen "echten" Code gibt es genau drei verschiedenen Schreibweisen - das Makro sieht dort etwa so aus:

    MAKE_FRUIT(Apple, apple, eFruit::Apple);
    

    wie gesagt ist dies am einfachsten zu verstehen, warten, etc.

    Allerdings könnte man jetzt noch auf Basis des Obigen Makros noch ein Helpermakro zur verfügung stehen, das das obige makro einfach aufruft - in Pseudocode etwa so:

    MAKE_FRUIT_LAZY_TYPER(X) \
    MAKE_FRUIT( Uppercase(X), Lowercase(X), eFruit::X);
    
    // Verwendung:
    MAKE_FRUIT_LAZY_TYPER(Apple);
    

    Den Code von TyRoXx kann man z. B. für alle Buchstaben und einer festen länge von 15 Zeichen mit z. B. python Skript generieren... muss mal sehen ob ich diesen Aufwand betreibe - auf jeden fall wäre es eine Nette C++ Übung um den Präprozessor kennenzulernen



  • Agin34 schrieb:

    z. B. python Skript generieren...

    dann generierse doch gleich alles komplett .



  • Agin34 schrieb:

    Den Code von TyRoXx kann man z. B. für alle Buchstaben und einer festen länge von 15 Zeichen mit z. B. python Skript generieren... muss mal sehen ob ich diesen Aufwand betreibe - auf jeden fall wäre es eine Nette C++ Übung um den Präprozessor kennenzulernen

    Dir ist schon klar dass das resultierende File vermutlich grösser wäre als der gesamte auf der Erde verfügbare Speicherplatz...?



  • Shade Of Mine schrieb:

    dann generierse doch gleich alles komplett .

    das ist die andere Möglichkeit. mit C++ oder Python oder ... einen kleinen Codegenerator schreiben und als Custombuildstep (wie Qt/moc) in das Buildsystem einbauen



  • hustbaer schrieb:

    Dir ist schon klar dass das resultierende File vermutlich grösser wäre als der gesamte auf der Erde verfügbare Speicherplatz...?

    ja ist mir direkt nach dem Posting eingefallen 😉 - bin mir relativ sicher, dass es schon irgendwie schöner gehen muss...


Anmelden zum Antworten