Ausnahmesichere kovariante Rückgabetypen



  • Wobei ich meinen letzten Post wieder zurücknehmen muss, ich hab mir natürlich was dabei gedacht. clone() hat nicht notwendigerweise immer einen covariant return type und die Variante mit decltype() funktioniert eben auch, wenn dem nicht so ist...



  • ? Ich habe doch eine saubere Möglichkeit genannt:

    struct Base { 
        unique_ptr<Base> clone() const { return cloneMe(); } 
    private:
        virtual Base* cloneMe() const { return new Base(*this); }
    }; 
    
    struct Derived : Base { 
        unique_ptr<Derived> clone() const { return cloneMe(); } 
    private:
        virtual Derived* cloneMe() const { return new Derived(*this); }
    };
    

    So muss du deinen bestehenden Client-Code auch nicht anpassen.



  • KasF schrieb:

    ? Ich habe doch eine saubere Möglichkeit genannt

    Dann hab ich das falsch verstanden. Ich dachte clone würde bei jeder Klasse anders heissen.
    An das hab ich gar nicht gedacht, top 👍



  • Ist natürlich auch eine Lösung, hat halt den Nachteil, dass man in jeder Klasse, die ein kovariates clone() unterstützten soll die entsprechende Methode extra definieren muss. Der Vorteil ist wiederum, dass es keinen Weg gibt, ein Objekt nicht über std::unique_ptr zu klonen, beim anderen Ansatz müsste man dafür über friend arbeiten...



  • dot schrieb:

    Ist natürlich auch eine Lösung, hat halt den Nachteil, dass man in jeder Klasse, die ein kovariates clone() unterstützten soll die entsprechende Methode extra definieren muss.

    Ach, ein STRG+R tuts auch 😉 Es ist halt eine Änderung im Code gewünscht und die erfordert eben Arbeit, da kommt man nicht drumherum. Hauptsache der Client erleidet daraus keinen Nachteil.



  • Ist ja angeblich eh guter Stil. 😉
    http://www.gotw.ca/publications/mill18.htm

    Herb Sutter schrieb:

    Guideline #2: Prefer to make virtual functions private.



  • KasF schrieb:

    unique_ptr<Base> clone() const { return cloneMe(); } 
    unique_ptr<Derived> clone() const { return cloneMe(); }
    

    Da scheine ich ja was vergessen zu haben 🙂 Einfach return unique_ptr<T>(cloneMe()) daraus machen. Btw, corian welchen Compiler benutzt, dass du schon make_unique hast?



  • KasF schrieb:

    Da scheine ich ja was vergessen zu haben 🙂 Einfach return unique_ptr<T>(cloneMe()) daraus machen. Btw, corian welchen Compiler benutzt, dass du schon make_unique hast?

    Das make_unique hab ich mir selber geschrieben.
    Ein return {cloneMe()}; reicht auch übrigens schon.



  • corian schrieb:

    Ein return {cloneMe()}; reicht auch übrigens schon.

    unique_ptr's Konstruktor ist explicit, zumindest sollte es das bei dir sein und folgedessen obiger Code nicht funktionieren. Wenn das oben bei dir wirklich funktioniert, dann blitzt und donnert es aber gewaltig mit der RAII-Philosophie.



  • KasF schrieb:

    corian schrieb:

    Ein return {cloneMe()}; reicht auch übrigens schon.

    unique_ptr's Konstruktor ist explicit, zumindest sollte es das bei dir sein und folgedessen obiger Code nicht funktionieren. Wenn das oben bei dir wirklich funktioniert, dann blitzt und donnert es aber gewaltig mit der RAII-Philosophie.

    Ich war mir vorhin nicht sicher, ob diese Syntax wirklich nicht mit explicit Konstruktoren nutzbar ist und habe das nachgeguckt. Ein "return {...};" ist eine copy-list-initialization. Mit dieser kann man keine explicit Konstruktoren aufrufen. Du hast also Recht.


Anmelden zum Antworten