Wie kann man Code Kopie durch Template ersetzen?



  • volkard schrieb:

    Virtual foo schrieb:

    Benutze einfach virtuelle Funktionen. Nichts anders versuchst du gerade nachzubauen...

    jo, die do_thing_1() und do_thing_1() virtual in die Base und alles ist gut.
    geht supi schnell.

    das template geht auch, aber das tut dann nicht mehr als 2^32 ifs hintereinander. nöö, das wird nicht gut. nichtmal rtti würde viel bringen. da müßte die basis auch virtuell sein, ach ist sie ja eh schon. und das muss sie eh, wenn du die objekte in einer gemeinsamen liste verwaltest.

    undokumentiert, undefiniert, nur für böse buben könntest du den vptr anschauen und eine hashtable benutzen. mit dem erfolg, daß du zwar ne gescheit laufzeit hast, aber nur für den potenziellen fall eines aufrufs mal die 2^32 klassen erzeugst.

    musst die basis ändern und gegebenefalls eben den chef davon überzeugen.

    die Klassen A<N>, B<N> und Base kommen von einem Library. do_thing_1() und do_thing_2 sind leider keine virtuelle Funktion in Base(). Die Base Klasse hat andere Funktionalität, die hier zu meinem Zweck nicht dargestellt sind.

    Es sieht so aus, dass ich 2^32 Mal schreiben muss, um alle möglichen Fälle abzudecken. Schade!! 😞 😞

    Trotzdem vielen Dank.

    /Kai



  • Vielleicht wäre was möglich, aber solange der Kontext ein großes Geheimnis ist, natürlich nicht. Das geht dann für 100€/h.



  • volkard schrieb:

    Übungsaufgabe vom Prof? Dann fehlt mehr Kontext, um zu ahnen, auf was er hinauswill.

    Wenns von einem Prof käme könnte der vielleicht einen vptr-Hack erwarten. Standardkonform geht das jedenfalls nur mit den 2^17 ifs (weil unsigned nur von 0 bis 2^16 gehen muss).

    @tjroamer: Wenn du wenigstens die Signatur in std::vector<std::shared_ptr<thing_dispatcher*>> ändern könntest, hättest du noch eine kleine Chance (sofern du die Erstellung der Liste beeinflussen kannst).

    Es sieht so aus, dass ich 2^32 Mal schreiben muss, um alle möglichen Fälle abzudecken.

    Ach nein, da ist ein Troll am Werk. Hat sich erledigt.



  • Sone schrieb:

    volkard schrieb:

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion

    Bitte die vollständige Anforderung schreiben. Immer wieder einen halben Satz zu kriegen, der alles umwirft, das ist nicht fein.

    Wovon redest du?

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion [...] func(std::vector<Base*> &obj_list)[...] anbieten, um andere sie aufrufen zu können.

    Sorry, vielleicht habe ich nicht klar geschrieben. Jetzt ist die konkrete Anforderung:

    **Meine Klasse muss den Usern die Funktion

    void func(std::vector<Base*> *obj_list);
    

    zur Verfügung stellen. Die Funktion muss je nach der Subklasse do_thing_1() oder do_thing_2() richtig aufrufen.
    **

    Gruß,

    Kai



  • tjroamer schrieb:

    Sone schrieb:

    volkard schrieb:

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion

    Bitte die vollständige Anforderung schreiben. Immer wieder einen halben Satz zu kriegen, der alles umwirft, das ist nicht fein.

    Wovon redest du?

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion [...] func(std::vector<Base*> &obj_list)[...] anbieten, um andere sie aufrufen zu können.

    Sorry, vielleicht habe ich nicht klar geschrieben. Jetzt ist die konkrete Anforderung:

    **Meine Klasse muss den Usern die Funktion

    void func(std::vector<Base*> *obj_list);
    

    zur Verfügung stellen. Die Funktion muss je nach der Subklasse do_thing_1() oder do_thing_2() richtig aufrufen.
    **

    Gruß,

    Kai

    Süßer, wir haben den Code von Base immer noch nicht. Sind wenigstens do_thing_1 und do_thing_2 dort virtuell? Dann würde doch RTTI reichen.



  • BöserBube schrieb:

    volkard schrieb:

    Übungsaufgabe vom Prof? Dann fehlt mehr Kontext, um zu ahnen, auf was er hinauswill.

    Wenns von einem Prof käme könnte der vielleicht einen vptr-Hack erwarten. Standardkonform geht das jedenfalls nur mit den 2^17 ifs (weil unsigned nur von 0 bis 2^16 gehen muss).

    @tjroamer: Wenn du wenigstens die Signatur in std::vector<std::shared_ptr<thing_dispatcher*>> ändern könntest, hättest du noch eine kleine Chance (sofern du die Erstellung der Liste beeinflussen kannst).

    Es sieht so aus, dass ich 2^32 Mal schreiben muss, um alle möglichen Fälle abzudecken.

    Ach nein, da ist ein Troll am Werk. Hat sich erledigt.

    ich denke, ich muss aufgeben, der Parameter std::vector<Base*> ist leider nicht änderbar. Vielen Dank an euch allen für eure Zeit und gute Nacht!

    Gruß,

    Kai



  • volkard schrieb:

    tjroamer schrieb:

    Sone schrieb:

    volkard schrieb:

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion

    Bitte die vollständige Anforderung schreiben. Immer wieder einen halben Satz zu kriegen, der alles umwirft, das ist nicht fein.

    Wovon redest du?

    tjroamer schrieb:

    Die Anforderung ist: meine Klasse muss die public Funktion [...] func(std::vector<Base*> &obj_list)[...] anbieten, um andere sie aufrufen zu können.

    Sorry, vielleicht habe ich nicht klar geschrieben. Jetzt ist die konkrete Anforderung:

    **Meine Klasse muss den Usern die Funktion

    void func(std::vector<Base*> *obj_list);
    

    zur Verfügung stellen. Die Funktion muss je nach der Subklasse do_thing_1() oder do_thing_2() richtig aufrufen.
    **

    Gruß,

    Kai

    Süßer, wir haben den Code von Base immer noch nicht. Sind wenigstens do_thing_1 und do_thing_2 dort virtuell? Dann würde doch RTTI reichen.

    die Klasse Base und A<N>, B<N> sehen so aus:

    class Base
    {
    public:
      Base() {}
      virtual const char* kind();
      virtual const char* name();
      virtual ~Base();
    };
    
    template<unsigned int N>
    class A: public Base
    {
    public:
      A() {}
      void do_thing_1()
      {
        // do thing_1 depending on the N
      }
    
      virtual const char* kind() { return "A"; }
      virtual const char* name() { return "A"; }
    };
    
    template<unsigned int N>
    class B: public Base
    {
    public:
      B() {}
      void do_thing_2()
      {
        // do thing_2 depending on the N
      }
    
      virtual const char* kind() { return "B"; }
      virtual const char* name() { return "B"; }
    };
    

    do_thing_1() und do_thing_2() sind keine virtual 😞 😞



  • Aber Hase! Da sind ja weder do_thing_1 oder ~_2 in der Basisklasse deklariert, geschweige denn virtuell!

    Übrigens, die sind so klein? In dem Fall sei doch ein ganz Böser Bezlebub' und schreib die zwei Zeilen da rein - ich nehme die Verantwortung auf mich:

    virtual void do_thing_1() = 0;
    virtual void do_thing_2() = 0;
    


  • Sone schrieb:

    Aber Hase! Da sind ja weder do_thing_1 oder ~_2 in der Basisklasse deklariert, geschweige denn virtuell!

    Übrigens, die sind so klein? In dem Fall sei doch ein ganz Böser Bezlebub' und schreib die zwei Zeilen da rein - ich nehme die Verantwortung auf mich:

    virtual void do_thing_1() = 0;
    virtual void do_thing_2() = 0;
    

    anscheinend gibt es keinen anderen Weg. OK, ich versuche auf diesen Weg zu gehen. Vielen Dank.

    Gruß,

    Kai


  • Mod

    tjroamer schrieb:

    Das ist fast unmöglich, 2^32 Möglichkeiten aufzulisten.

    Das ist nicht dein Problem. Dein Problem ist, dass du 2^32+ verschiedene Funktionen hast.



  • camper schrieb:

    tjroamer schrieb:

    Das ist fast unmöglich, 2^32 Möglichkeiten aufzulisten.

    Das ist nicht dein Problem. Dein Problem ist, dass du 2^32+ verschiedene Funktionen hast.

    Fast ein wenig ironisch - Stroustrup schreibt noch, Templates sind gut, um den Maschinencode zu verkürzen 🤡
    Edit: Oder so ähnlich.



  • camper schrieb:

    tjroamer schrieb:

    Das ist fast unmöglich, 2^32 Möglichkeiten aufzulisten.

    Das ist nicht dein Problem. Dein Problem ist, dass du 2^32+ verschiedene Funktionen hast.

    die Funktion operate() ist als template definiert. Hier ist kein Problem. Der User kann folgenden Code schreiben:

    A<13> a_13();
    B<1000> b_1000();
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    

    MyClass muss solchen Code beherrschen. Das ist mein Problem.

    Gruß,

    /Kai



  • A<13> a_13();//er wird
    B<1000> b_1000();//sich wundern
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);//hier
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    


  • volkard schrieb:

    A<13> a_13();//er wird
    B<1000> b_1000();//sich wundern
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);//hier
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    

    gibt es hier einen Tippfehler oder wie?

    Gruß,

    Kai



  • Ich sehe es sofort. :stolz: 😃

    Edit:

    tjroamer schrieb:

    volkard schrieb:

    A<13> a_13();//er wird
    B<1000> b_1000();//sich wundern
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);//hier
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    

    gibt es hier einen Tippfehler oder wie?

    Das sind Funktionsdeklarationen.
    Guckstdu.



  • Sone schrieb:

    Ich sehe es sofort. :stolz: 😃

    Edit:

    tjroamer schrieb:

    volkard schrieb:

    A<13> a_13();//er wird
    B<1000> b_1000();//sich wundern
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);//hier
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    

    gibt es hier einen Tippfehler oder wie?

    Das sind Funktionsdeklarationen.
    Guckstdu.

    OK. Wahrscheinlich habe ich zu einfach geschrieben. Ich wollte schreiben, a_13 und b_1000 sind zwei Klassenobjekten.

    sollte sein:

    A<13> a_13;
    B<1000> b_1000;
    

    Gruß,

    /Kai



  • tjroamer schrieb:

    camper schrieb:

    tjroamer schrieb:

    Das ist fast unmöglich, 2^32 Möglichkeiten aufzulisten.

    Das ist nicht dein Problem. Dein Problem ist, dass du 2^32+ verschiedene Funktionen hast.

    die Funktion operate() ist als template definiert. Hier ist kein Problem. Der User kann folgenden Code schreiben:

    A<13> a_13();
    B<1000> b_1000();
    
    std::vector<Base*> obj_list;
    obj_list.push_back(&a_13);
    obj_list.push_back(&b_1000);
    
    MyClass myclass();
    
    myclass.func(obj_list);
    

    MyClass muss solchen Code beherrschen. Das ist mein Problem.

    Gruß,

    /Kai

    Aber der User ist bei Euch und kann auch angewiesen werden, die Liste ein wenig anders zu bauen?

    Zum Beispiel ist die Liste ein Template-Listen-Ding, was die Typen der Elemente alle kennt? //Am besten, aber für Dich am schwierigsten und schränkt die Benutzer am meisten ein.

    Oder dürfen wir einen Wrapper um A und B bauen, der zusätzlich die Adresse der wichtigen Funktion kennt und nur solche Objekte darf der User anlegen? //Naja, häßlich.

    Oder auch nur den Zwang, wenn er ein A<13> benutzt, muß er auch

    registerVptrAndFunc<A<13>>();
    

    mindestens einmal im Programm aufrufen? //Stört den Benutzer vermutlich am wenigsten und ist auch schnell gebastelt. Leider compilerabhängige Tricks.



  • tjroamer schrieb:

    die Funktion operate() ist als template definiert.

    Um das Template geht es nicht. Sondern um die daraus instantiierten Funktionen.

    Ich hab grad mal im Anhang B (N3337) nachgeguckt - komisch. Sollte doch irgendwie impliziert sein, dass....



  • Wir gehen davon aus, daß die Benutzer nur ein paar, vielleicht mal 50 A- und B-Klassen in einem Projekt benutzt, das sind dann 100 Funktionen. Ok, wenn er sie braucht. Der Compiler erzeugt sie.
    Aber wenn Du anmeldest, 2^32 Funktionen zu brauchen, indem Du in lauter if-Zeigen eine der Adressen anfragst, machste die ausführbarre Datei recht groß.
    Wäre die erste 400GB große exe-Datei, die ich sehen würde.
    Mach mal.



  • volkard schrieb:

    Wir gehen davon aus, daß die Benutzer nur ein paar, vielleicht mal 50 A- und B-Klassen in einem Projekt benutzt, das sind dann 100 Funktionen. Ok, wenn er sie braucht. Der Compiler erzeugt sie.
    Aber wenn Du anmeldest, 2^32 Funktionen zu brauchen, indem Du in lauter if-Zeigen eine der Adressen anfragst, machste die ausführbarre Datei recht groß.
    Wäre die erste 400GB große exe-Datei, die ich sehen würde.
    Mach mal.

    Ja, der Nutzer verwendet nur normalerweise nur bis zur 512 . Ich kann 512*2 if-anweisung manuell schreiben. Ich habe gefragt weil ich dumm fand wenn man solchen hässlichen code schreiben muss. Aber man muss so tun wenn nichts andere geht.


Anmelden zum Antworten