Template und Funktionswiederverwendung



  • hallo zusammen

    Folgendes Problem... ich habe Interface IA und IB:IA ... und ich muss dazu Klassen implementieren (für ein Framework, das wir bauen).

    Also baue ich Implementation MA und MB:MA ... (oder, würde ich gerne)... jetzt, wenn MA von IA ableitet und MB von IB, haben wir ein Problem, weil IB schon von IA ableitet. (IA ist also mehrfach in MB drin, einmal über die Ableitung von MA, einmal über IB.)

    konkret:

    class IA {};
    class IB : IA {};

    class MA : IA {};
    class MB : MA, IB {}; // hier komme ich nicht weiter

    also nutz ich Templates um das zu umgehen...

    class IA {};
    class IB : IA {};

    template<class I>
    class MA : I {};

    template<class I>
    class MB : MA<I>, I {};

    ... soweit so gut. Das Problem ist jetzt nur, dass ich am Ende in der DLL, die ich baue, ein MA<IA> und ein MA<IB> drin ist. Und die sind vollkommen identisch (eigentlich). Hier ist alles doppelt hineinkompiliert.

    Frage... gibt's da irgend eine Lösung, um das in den Griff zu bekommen? ... meine IA, IB sind übrigens nur reine vtables (enthalten also nur virtual-Funktionen). ... daher habe ich mir mal überlegt, ob ich nicht einfach die vtables manuell "zurecht biegen" könnte und dann einfach Zeiger vom Typ MA<IA>* und MA<IB>* caste auf... z.B. MA_impl* und da implementiere ich dann die eigentlichen Funktionen und hab die dann nur einmal. (wobei, "casten" ist nicht der richtige Ausdruck... ich würde einfach den Funktionszeiger, der MA<IA>* als ersten Parameter will, mit einem ersetzen, der MA_impl* als ersten Parameter will... also, etwas unsauber).

    Oder, wär das zu mühsam? ... oder hat jemand einen anderen Vorschlag oder eine Lösung, wie man so etwas hinbekommen kann, dass da nicht die Implementationen explodieren? Denn spätestens, wenn ich 100 mal MA<x> als implementation habe, wird das ganze super unsinnig...

    Rudolf



  • @meiru sagte in Template und Funktionswiederverwendung:

    Also baue ich Implementation MA und MB:MA ... (oder, würde ich gerne)... jetzt, wenn MA von IA ableitet und MB von IB, haben wir ein Problem, weil IB schon von IA ableitet. (IA ist also mehrfach in MB drin, einmal über die Ableitung von MA, einmal über IB.)
    konkret:
    class IA {};
    class IB : IA {};
    class MA : IA {};
    class MB : MA, IB {}; // hier komme ich nicht weiter

    Dafür gibt es die virtualAbleitung:

    class IB : virtual IA {};
    
    class MA : virtual IA {};
    

    Wobei ich mehrfach Vererbung, auch wenn C++ sie unterstützt, nicht schön finde und auch noch nie selber gebraucht habe, glaube ich.

    @meiru sagte in Template und Funktionswiederverwendung:

    Das Problem ist jetzt nur, dass ich am Ende in der DLL, die ich baue, ein MA<IA> und ein MA<IB> drin ist

    Joa, was hast du erwartet? MA<IA> und MA<IB> sind 2 verschiedene Typen. Hat halt alles seine Vor- und Nachteile.

    Deine Lösung nennst du ja selber "unsauber". So lange du mit anderen "sauberen" Varianten hinkommst, wo ist das Problem?



  • @Schlangenmensch sagte in Template und Funktionswiederverwendung:

    Deine Lösung nennst du ja selber "unsauber". So lange du mit anderen "sauberen" Varianten hinkommst, wo ist das Problem?

    Das Problem ist, dass ich am Ende eine DLL habe, die 20 MB gross ist statt nur 200 KB... und das finde ich nicht so super toll... darum geht's eigentlich.

    Und von wegen "unsauber"... ich frage mich, ob das echt "unsauber" ist, wenn ich ausnutze, dass ich den Standard kenne und binär selber was daran drehe... na ja... muss mir das nochmal überlegen.



  • @meiru
    Das extreme Aufblasen der Grösse kannst du so verhindern:

    class IA {
    public:
         virtual void a() = 0;
    };
    
    class AImpl {
    public:
         void a(); // NICHT inline!
    };
    
    template <class Interface>
    class MA : public Interface, AImpl {
         void a() override {
            AImpl::a();
         }
    }
    

    Falls du mit link-time-code-generation/whole-program-optimization compilierst, dann pack noch ein BOOST_NOINLINE o.ä. mit dran.

    meine IA, IB sind übrigens nur reine vtables (enthalten also nur virtual-Funktionen). ... daher habe ich mir mal überlegt, ob ich nicht einfach die vtables manuell "zurecht biegen" könnte und dann einfach Zeiger vom Typ MA<IA>* und MA<IB>* caste auf... z.B. MA_impl* und da implementiere ich dann die eigentlichen Funktionen und hab die dann nur einmal.

    ich frage mich, ob das echt "unsauber" ist, wenn ich ausnutze, dass ich den Standard kenne und binär selber was daran drehe

    Wenn du auf Schmerzen stehst, dann mach das ruhig so.

    Aber ernsthaft: lass bloss die Finger von sowas. Das macht nur Ärger.



  • @hustbaer sagte in Template und Funktionswiederverwendung:

    Wenn du auf Schmerzen stehst, dann mach das ruhig so.

    Aber ernsthaft: lass bloss die Finger von sowas. Das macht nur Ärger.

    danke für die Tips... aber, mal ehrlich... COM... also der MIDL-compiler (und auch ein Compiler, den wir hier intern entwickelt haben für eine eigene RPC-Lösung) ... die bauen alle für C eine vtable auf

    ich habe bisher immer nur in C++ die Implementation gemacht... aber eigentlich sollte man ja auch gleich einfach eine C-Implementierung für eine COM-Schnittstelle hinbekommen und dann... dann hätte man das doch schon? ...

    na, mal sehen... aber probieren tue ich's auf jeden Fall... bin grad zwischen zwei Projekten und hab etwas Lust auf verrückte Sachen 🙂



  • ach ne... ist ja noch viel einfacher... och... sowas von langweilig...

    class IA {};
    class IB : IA {};

    class MA {};
    class MB : MA {};

    ... solange ich IA und MA gleich aufbaue von den Funktionen her und auch IB und MB identisch gestalte, kann ich das Zeug ja einfach casten. Weil die Struktur der vtables ja gleich ist (sonst würde COM ja nicht funktionieren) ...



  • Ich gehe davon aus dass es dich spätestens bei dynamic_cast aufpracken wird.



  • @hustbaer sagte in Template und Funktionswiederverwendung:

    aufpracken

    Wasndas?



  • stimmt, das wär wohl so... aber ich nutze das nur an einer Stelle, an der das sowieso nicht erlaubt ist... es geht nämlich sowieso um Schnittstellen-Objekte wie bei COM, die ich zurückgebe... und da war das noch nie eine Option 🙂



  • @DocShoe sagte in Template und Funktionswiederverwendung:

    @hustbaer sagte in Template und Funktionswiederverwendung:

    aufpracken

    Wasndas?

    Wörtlich: stürzen.
    Umgangssprachlich: damit wird es dich aufpracken = damit wirst du auf die Nase fallen.


Anmelden zum Antworten