Frage zu Pointer Array.



  • hallo,
    ich schreibe gerade ein Program, aber finde sehr aufwendig, Pointer Array zuzuweisen.
    Das Problem ist wie folgendes:
    aus unterschiedlichen Versionen von Spec wurde solche Code von einem Tool automatisch generiert:

    myclass FrameClass_0_1;
    myclass FrameClass_0_2;
    myclass FrameClass_0_3;
    myclass FrameClass_0_4;
    myclass FrameClass_0_5;
    myclass FrameClass_0_6;
    

    ich muss FrameClass_0_1 usw. zugreifen, um die Methode von myclass aufzurufen. Ich will nicht jedes abfragen, welche Index von FrameClass ich zugreifen möchte, sondern ich habe eine Pointer Array definiert. Mein Code sieht so aus:

    class newclass {
        myclass *FrameClass_0[6];
        // constructor
        newclass::newclass()
        {
            FrameClass_0[0] = &FrameClass_0_1;
            FrameClass_0[1] = &FrameClass_0_2;
            FrameClass_0[2] = &FrameClass_0_3;
            FrameClass_0[3] = &FrameClass_0_4;
            FrameClass_0[4] = &FrameClass_0_5;
            FrameClass_0[5] = &FrameClass_0_6;
        }
    
        void newclass::myfunc(int i)
        {
            FrameClass_0[i]->method();
        }
    }
    

    Das funktioniert im moment gut. Aber ich finde, das ist nicht elegant, weil ich tansend von solchen Variablen habe, ich muss in Constructor soviele Code schreiben. Ich habe den Vorteil von automatische generierte Code verloren. Es ist sehr leicht einen Fehler zu machen.

    Ich erwarte, ich kann alle Pointer Array Zuweisung in eine Loop einpacken.

    for(int i=0; i<6; ++i) {
            FrameClass_0[i] = &FrameClass_0_/i/;
        }
    

    aber das kann stimmt nicht funktionieren. Weiss jemand wie ich eleganter den Code schreiben kann?
    Mit C Makro kann ich leider nicht hinkriegen, weil Index 0-5 sind im Laufzeit erst erkennbar.

    Vielen Dank für eure Hilfe vorab.

    /Kenny



  • Du kannst mit einem std::vector zumindest etwas mehr Sicherheit gewinnen.

    #include <vector>
    typedef std::vector<class myclass *> ClassVec;
    
    ClassVec vec;
    
    class newclass {
        ClassVec vec;
    
        // constructor
        newclass::newclass()
        {
            vec.push_back(FrameClass_0_1);
            vec.push_back(FrameClass_0_2);
            vec.push_back(FrameClass_0_3);
            vec.push_back(FrameClass_0_4);
            vec.push_back(FrameClass_0_5);
            vec.push_back(FrameClass_0_6);
        }
    
        void newclass::myfunc(int i)
        {
            vec[i]->method();
        }
    }
    

    Aber mehr ist wohl nicht drinne...



  • Zeile 4 ist natürlich überflüssig und gehört dort nicht hin, sry.



  • ghjghjghj schrieb:

    Du kannst mit einem std::vector zumindest etwas mehr Sicherheit gewinnen.

    #include <vector>
    typedef std::vector<class myclass *> ClassVec;
    
    ClassVec vec;
    
    class newclass {
        ClassVec vec;
    
        // constructor
        newclass::newclass()
        {
            vec.push_back(FrameClass_0_1);
            vec.push_back(FrameClass_0_2);
            vec.push_back(FrameClass_0_3);
            vec.push_back(FrameClass_0_4);
            vec.push_back(FrameClass_0_5);
            vec.push_back(FrameClass_0_6);
        }
    
        void newclass::myfunc(int i)
        {
            vec[i]->method();
        }
    }
    

    Aber mehr ist wohl nicht drinne...

    das ist richtig. Mit Vector kann man mehre Sicherheit gewinnen.
    Gibt es ein einfache Form um diese Code zuschreiben?
    Wie gesagt, habe ich tansende solchen Variablen. Ich muss ehe manuell alle push_back schreiben.
    Kann man mit Makro das vereinfachen?

    /Kenny



  • tjroamer schrieb:

    ghjghjghj schrieb:

    Du kannst mit einem std::vector zumindest etwas mehr Sicherheit gewinnen.

    #include <vector>
    typedef std::vector<class myclass *> ClassVec;
    
    ClassVec vec;
    
    class newclass {
        ClassVec vec;
    
        // constructor
        newclass::newclass()
        {
            vec.push_back(FrameClass_0_1);
            vec.push_back(FrameClass_0_2);
            vec.push_back(FrameClass_0_3);
            vec.push_back(FrameClass_0_4);
            vec.push_back(FrameClass_0_5);
            vec.push_back(FrameClass_0_6);
        }
    
        void newclass::myfunc(int i)
        {
            vec[i]->method();
        }
    }
    

    Aber mehr ist wohl nicht drinne...

    das ist richtig. Mit Vector kann man mehre Sicherheit gewinnen.
    Gibt es ein einfache Form um diese Code zuschreiben?
    Wie gesagt, habe ich tansende solchen Variablen. Ich muss ehe manuell alle push_back schreiben.
    Kann man mit Makro das vereinfachen?

    /Kenny

    Nein, nicht wirklich. Ich habe jedenfalls keine Idee und es gibt leider keine Schleifen für Makros...


  • Mod

    ghjghjghj schrieb:

    Nein, nicht wirklich. Ich habe jedenfalls keine Idee und es gibt leider keine Schleifen für Makros...

    Mit Makros geht das schon, Boost Preprocessor bietet da so einiges vorgefertigtes. Ist auch recht leicht selbst zu schreiben, aber wozu das Rad neu erfinden?

    Die wirkliche Frage ist aber natürlich, warum die FrameClass_0_X nicht schon in einem vector/array sind.



  • SeppJ schrieb:

    ghjghjghj schrieb:

    Nein, nicht wirklich. Ich habe jedenfalls keine Idee und es gibt leider keine Schleifen für Makros...

    Mit Makros geht das schon, Boost Preprocessor bietet da so einiges vorgefertigtes. Ist auch recht leicht selbst zu schreiben, aber wozu das Rad neu erfinden?

    Die wirkliche Frage ist aber natürlich, warum die FrameClass_0_X nicht schon in einem vector/array sind.

    wie nutzen ein Tool, das solche Code von eine Quelle automatisch generiert.
    Dies Tool kann aber keine Vector/Array generieren. Dies Tool wird generierte Code weiter verarbeiten, das kann ich leider nicht beeinflussen.

    Wie sieht der Preprocessor in Boost aus?

    Danke für den Hinweis.

    /Kenny


  • Mod

    Google nutzen ist schon schwer, was?

    hier ein Beispiel:

    #include <boost/preprocessor/cat.hpp>
    #include <boost/preprocessor/repetition/repeat_from_to.hpp>
    
    #define DECL(z, n, text) BOOST_PP_CAT(text, n) = n;
    
    BOOST_PP_REPEAT_FROM_TO(5, 10, DECL, int x)
       /*
          expands to:
          int x5 = 5; int x6 = 6; int x7 = 7;
          int x8 = 8; int x9 = 9;
       */
    


  • Lustig. Man nimmt native C++-Codegeneratoren, um mit den Erzeugnissen externer Tools überhaupt etwas anfangen zu können. 🙂



  • soweit habe ich erfolgreich mit BOOST_PP_REPEAT_... mein Code umgeschrieben.

    #define DECLX_IF_1D(z, n, text) text.push_back(&BOOST_PP_CAT(text, BOOST_PP_CAT(_, BOOST_PP_IF(n, B, A))));
    
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_IF_1D, y)
    // generiert: y.push_back(&y_A); y.push_back(&y_B);
    
    #define DECLX_1D(z, n, text) text.push_back(&BOOST_PP_CAT(text, BOOST_PP_CAT(_, n)));
    
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_1D, x)
    // generiert: x.push_back(&x_0); x.push_back(&x_1);
    

    aber es fehlt mir noch einiges:
    ich habe folgende Variablen:

    mybfclass x_0_mybf;
    mybfclass x_1_mybf;
    ...
    mybfclass1 x_0_mybf1;
    mybfclass1 x_1_mybf1;
    ...
    mybfclass2 x_0_mybf2;
    mybfclass2 x_1_mybf2;
    ...
    
    // ich habe eine Vector definiert
    vector<mybfclass*> x_mybf;
    vector<mybfclass1*> x_mybf1;
    vector<mybfclass2*> x_mybf2;
    

    um x_mybf zu befüllen, muss ich noch ein zusätzliches Makro definieren

    #define DECLX_mybf(z, n, text) BOOST_PP_CAT(text, BOOST_PP_CAT(_, mybf)).push_back(&BOOST_PP_CAT(text, BOOST_PP_CAT(BOOST_PP_CAT(_, n), BOOST_PP_CAT(_, mybf))));
    
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_mybf, x);
    // generiert: x_mybf.push_back(&x_0_mybf); x_mybf.push_back(&x_1_mybf);
    

    dann muss ich noch DECLX_mybf1 und DECL_mybf2 definieren.

    ich habe ziemlich viele solche Variablen. Ich muss noch viele Makros definieren, um zu automatisieren. Weil inne Makro DECLX_mybf von BOOST_PP_REPORT_FROM_TO nur ein Argument (x) akzeptieren kann.

    trotzdem hat dies Makro mir sehr viel geholfen.

    Vielen Dank für den Vorschlag.

    /Kenny


  • Mod

    Boost Preprocessor kennt auch Argumentenlisten. Da brauchst du dann nur ein Makro für alle Variablen.



  • SeppJ schrieb:

    Boost Preprocessor kennt auch Argumentenlisten. Da brauchst du dann nur ein Makro für alle Variablen.

    ich kenne Boost preprocessor leider nicht so gut. Ich habe das Makro geschaut, leider konnte ich kein passendes Makro für

    #define DECLX_mybf(z, n, text) BOOST_PP_CAT(text, BOOST_PP_CAT(_, mybf)).push_back(&BOOST_PP_CAT(text, BOOST_PP_CAT(BOOST_PP_CAT(_, n), BOOST_PP_CAT(_, mybf))));
    
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_mybf, x);
    // generiert: x_mybf.push_back(&x_0_mybf); x_mybf.push_back(&x_1_mybf);
    

    finden. 😞

    Kannst du mehren Hinweis mir geben?

    Danke.

    Viele Grüße,

    /Kenny



  • sowohl

    BOOST_PP_REPEAT(count, macro, data)
    

    als auch

    BOOST_PP_REPEAT_FROM_TO(first, last, macro, data)
    

    können nur ein Makroform

    macro(z, n, data)
    

    akzeptieren.

    Welche Makro kann ich nutzen, um mehr als ein Argument zu geben?

    Danke.

    /Kenny



  • mybfclass x_0_mybf;
    mybfclass x_1_mybf;
    ...
    mybfclass1 x_0_mybf1;
    mybfclass1 x_1_mybf1;
    ...
    mybfclass2 x_0_mybf2;
    mybfclass2 x_1_mybf2;
    ...
    

    Für sowas kannst du die Makros verschachteln. Ähnlich wie bei einer doppelten Schleife gehst du zuerst den einen Index durch, dann den anderen.

    Für den Spezialfall, dass beim Index 0 keine Null steht, sondern nichts, kannst du dir sowas einrichten:

    #define NUMBER(N) BOOST_PP_IF(BOOST_PP_EQUAL(N, 0), , N)
    #define DECL(Z, N, DATA) BOOST_PP_CAT(Decl, NUMBER(N))
    
    int main()
    {
    	BOOST_PP_REPEAT(4, DECL, )
    }
    

    Expandiert zu:

    int main()
    {
    	Decl Decl1 Decl2 Decl3
    }
    

    Man hat eigentlich nicht wenige Möglichkeiten zur Präprozessor-Metaprogrammierung. 😉


  • Mod

    Mit der Argumentenliste meinte ich, dass man eine Liste als ein Argument geben kann. Oder eine Sequence, weil die einfacher zu handhaben sind. Und die Sequence lässt man dann vom eigentlichen Makro wieder in die einzelnen Argumente zerpflücken. Funktioniert ziemlich gut.

    @Nexus: Das Verschachteln von Schleifen geht (zumindest bei boost) oftmals nicht. Zumindest wenn man den gleichen Schleifentyp im Inneren und im Äußeren benutzt. Dann muss man stattdessen beispielsweise eine for-Schleife innerhalb einer while-Schleife machen. Das funktioniert dann aber ganz ausgezeichnet.



  • SeppJ schrieb:

    Mit der Argumentenliste meinte ich, dass man eine Liste als ein Argument geben kann. Oder eine Sequence, weil die einfacher zu handhaben sind. Und die Sequence lässt man dann vom eigentlichen Makro wieder in die einzelnen Argumente zerpflücken. Funktioniert ziemlich gut.

    @Nexus: Das Verschachteln von Schleifen geht (zumindest bei boost) oftmals nicht. Zumindest wenn man den gleichen Schleifentyp im Inneren und im Äußeren benutzt. Dann muss man stattdessen beispielsweise eine for-Schleife innerhalb einer while-Schleife machen. Das funktioniert dann aber ganz ausgezeichnet.

    ich habe folgendes Makro mit Argumentlistmethode geschrieben, und es hat gut funktioniert:

    #define DECLX_BF(z, n, text) BOOST_PP_CAT(BOOST_PP_LIST_AT(text, 0), BOOST_PP_CAT(_, BOOST_PP_LIST_AT(text, 1))).push_back(\
    &BOOST_PP_CAT(BOOST_PP_LIST_AT(text, 0), BOOST_PP_CAT(_, BOOST_PP_CAT(n, BOOST_PP_CAT(_, BOOST_PP_LIST_AT(text, 1))))));
    
    // user code
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_BF, (x, (mybf, BOOST_PP_NIL)));
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_BF, (x, (mybf1, BOOST_PP_NIL)));
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_BF, (x, (mybf2, BOOST_PP_NIL)));
    // generiert: x_mybf.push_back(&x_0_mybf); x_mybf.push_back(&x_1_mybf); 
    // und x_mybf1.push_back(&x_0_mybf1); x_mybf1.push_back(&x_1_mybf1);
    // und x_mybf2.push_back(&x_0_mybf2); x_mybf2.push_back(&x_1_mybf2);
    

    jetzt bekämpfe ich eine 2-dimensionale Array

    reg1[0][0] = &reg1_IFA_0;
    reg1[0][1] = &reg1_IFA_1;
    reg1[0][2] = &reg1_IFA_2;
    ...
    reg1[1][0] = &reg1_IFB_0;
    reg1[1][1] = &reg1_IFB_1;
    reg1[1][2] = &reg1_IFB_2;
    ...
    ich denke, es sollte leichte gemacht werden kann. Ich werde meine Lösung nochmal zum Review posten.

    vielen Dank für deinen Hinweis.

    /Kenny



  • SeppJ schrieb:

    @Nexus: Das Verschachteln von Schleifen geht (zumindest bei boost) oftmals nicht. Zumindest wenn man den gleichen Schleifentyp im Inneren und im Äußeren benutzt. Dann muss man stattdessen beispielsweise eine for-Schleife innerhalb einer while-Schleife machen. Das funktioniert dann aber ganz ausgezeichnet.

    Hm. Also mit dem folgenden Code habe ich keine Probleme:

    #include <boost/preprocessor/repetition.hpp>
    #include <iostream>
    
    #define INNER(Z, INNER_VAR, OUTER_VAR) std::cout << OUTER_VAR << " " << INNER_VAR << std::endl;
    #define OUTER(Z, OUTER_VAR, INNER_MAX) BOOST_PP_REPEAT(INNER_MAX, INNER, OUTER_VAR)
    
    #define CASCADED(OUTER_MAX, INNER_MAX) BOOST_PP_REPEAT(OUTER_MAX, OUTER, INNER_MAX)
    
    int main()
    {
    	CASCADED(5, 3)
    }
    

    Ich weiss nicht, ob du vielleicht das meinst, aber die Boost-Präprozessormagier schreiben auf ihrer Seite zu BOOST_PP_REPEAT_z :

    <a href= schrieb:

    BOOST_PP_REPEAT Dokumentation">Previously, this macro could not be used recursively inside BOOST_PP_REPEAT. This limitation no longer exists, as the library can automatically detect the next available repetition depth.


  • Mod

    Nexus schrieb:

    Ich weiss nicht, ob du vielleicht das meinst, aber die Boost-Präprozessormagier schreiben auf ihrer Seite zu BOOST_PP_REPEAT_z :

    <a href= schrieb:

    BOOST_PP_REPEAT Dokumentation">Previously, this macro could not be used recursively inside BOOST_PP_REPEAT. This limitation no longer exists, as the library can automatically detect the next available repetition depth.

    Ja, ist ein schon Weilchen her, dass ich das festgestellt hatte. Gut zu wissen.



  • habe endlich das Problem mit Argumentlist gelöst:

    ich habe folgendes geschrieben:

    #define DECLX_1D(z, n, text) BOOST_PP_LIST_AT(text, 1)[BOOST_PP_LIST_AT(text, 0)][n] = \
    &BOOST_PP_CAT(BOOST_PP_LIST_AT(text, 1), BOOST_PP_CAT(_, BOOST_PP_CAT(BOOST_PP_LIST_AT(text, 0), BOOST_PP_CAT(_, n))));
    #define DECLX_REG_2D(z, n, text) BOOST_PP_REPEAT_FROM_TO(0, BOOST_PP_LIST_AT(text, 0), DECLX_1D, (n, (BOOST_PP_LIST_AT(text, 1), BOOST_PP_NIL)));
    
    int reg_0_0 = 12;
    int reg_0_1 = 13;
    int reg_1_0 = 14;
    int reg_1_1 = 15;
    
    int *reg[2][2];
    
    BOOST_PP_REPEAT_FROM_TO(0, 2, DECLX_REG_2D, (2, (reg, BOOST_PP_NIL)));
    
    // generiert: reg[0][0] = &reg_0_0; reg[0][1] = &reg_0_1;
    // reg[1][0] = &reg_1_0; reg[1][1] = &reg_1_1;
    

    das Makro siehst einbisschen kompliziert aus, oder?

    Nexus: mit deiner Methode werde ich mal probieren. _z Version sieht aus erstem Blick gut aus.

    Danke für eure Hilfe, ich denke, ich kann meine Codemenge sehr stark reduzieren, und gleichzeitlich kann ich jetzt besser das Code verwalten.

    /Kenny


  • Mod

    tjroamer schrieb:

    das Makro siehst einbisschen kompliziert aus, oder?

    Ja, aus meiner Erfahrung ist das bei der Präprozessormetaprogrammierung immer so. Aber solch ein Makro schreibt man einmal und versteckt es dann irgendwo in einem Header und dann sieht alles wieder ordentlich aus.


Anmelden zum Antworten