Funktion soll unique_ptr<T> und T* nehmen koennen


  • Mod

    hustbaer schrieb:

    Und auch das ist für mich nicht klar.

    Das war eine Parodie auf Shade. 😉



  • Shade Of Mine schrieb:

    Weil du staenkern willst, ist mir durch aus klar 🙂

    Nein. Weil ich dich für überheblich und reichlich stur halte. Was du mit diesem Beitrag wieder bestätigst. Du weisst einfach alles besser, auch wenn du total daneben liegst.

    Shade Of Mine schrieb:

    Und jetzt bist du eingeschnappt weil ich deine "Loesung" uebergangen habe.

    Kommt drauf an was du damit meinst. Wenn du meinst dass ich eingeschnappt bin weil du so getan hast als ob ich überhaupt nichts zum Thema geschrieben hätte, dann ja. Weil ich das für unhöflich halte.

    Shade Of Mine schrieb:

    Aber das sind eben diese Trivialitaeten mit denen ich mich nicht wirklich befassen will: die Fragestellung war, geht es einfacher als alle set-Funktionen doppelt zu schreiben. Und da ist die Antwort ein klares: Nein. Und warum ich deinen "Beitrag" mit keiner Antwort gewuerdigt habe, erklaert sich wohl von selbst, oder?

    Nein, tut es nicht.
    Bei deiner Frage bin ich mal einfach davon ausgegangen dass du es nicht 1x oder 2x brauchst, sondern mehrfach. Weil die Frage ob man sich eine 1-zeilige Forwarding-Funktion sparen kann sonst irgendwie lächerlich ist.
    Und wenn man es mehrfach braucht würde ich sagen ist mein Vorschlag immer noch der kürzeste.

    Shade Of Mine schrieb:

    Eine andere Trivialitaet ist, dass new nichts boeses ist. Wir sagen das Anfaengern gerne weil es gut ist sie davon abzuhalten new zu verwenden. Aber wenn man sich ein bisschen auskennt erkennt man schnell das new ansich kein Problem ist, das Problem ist delete und ownership.

    Ja, genau, das Problem ist delete und Ownership. Und weil es naiv wäre anzunehmen, dass jeder, der Code liest welcher dein Interface verwendet, dein Interface in und auswendig kennt, ist es halt blöd wenn da einfach nur foo.setBar(new Bar()); steht. Weil man dann eben nicht sieht ob setBar die Ownership übernimmt oder nicht. Klar, wenn man nur verstehen will was abgeht und einfach mal davon ausgehen kann dass es passt ist das nicht schlimm. Wenn man Fehler sucht ist das aber sehr lästig. Hast du schonmal Fehler in Code von anderen Leuten gesucht? Wo du dir nicht sicher sein konntest ob die bestimmte Dinge verstanden bzw. sich darum geschert haben?

    Und auch beim Schreiben von Code ist es lästig wenn man immer wissen muss welche Funktionen Ownership übernehmen und welche nicht.

    Wenn setBar dagegen einen unique_ptr nimmt ist die Sache klar. Das spart Kopfschmerzen und verringert die Chance Schlampigkeitsfehler zu machen.

    Shade Of Mine schrieb:

    Mach einen eigenen Thread auf, dann erklaere ich dir vielleicht wie gutes API Design aussieht

    So viel zum Thema überheblich 🙄

    Shade Of Mine schrieb:

    und warum man nicht die Implementierungsdetails komplett In-Your-Face ins Interface packt.

    unique_ptr ist also ein Implementierungsdetail. Wow. Letztlich geht es um die Information "hier wird Ownership transferiert", und die sollte verdammtnochmal ins Interface. Weil die Doku kaum jemand liest. Und die wenigen Doku-Leser auch mal was überlesen oder vergessen. Wenn du der (mir unverständlichen) Meinung bist dass unique_ptr ein Implementierungsdetail sei, dann mach eine eigene Klasse dafür. Ist std::string für dich auch ein Implemeniterungsdetail?

    Oder ist dir vielleicht nicht bekannt dass es da eine Funktion
    http://en.cppreference.com/w/cpp/memory/unique_ptr/release
    gibt? Heisst: unique_ptr im Interface sagt nix darüber aus wie deine Library/Klasse/... das Objekt weiterhin verwalten wird. Es sagt nur: Ich übernehme Ownership. Und das ist ja wohl ganz klar kein Implemeniterungsdetail. Nichtmal wenn die Klasse dann intern wirklich unique_ptr verwendet. Mal ganz abgesehen davon dass du ja sowieso den 2. Overload mit unique_ptr hast. Der ja wohl auch zum Interface gehört. Womit das angebliche Implementierungsdetail sowieso schon im Interface ist.

    Und guck, jetzt hab ich dir was über API Design erzählt. Wow, Shocker.

    Shade Of Mine schrieb:

    (Schocker: Design Entscheidungen sind Abhaengig vom Kontext. 😮 Mind Blown, nicht wahr?)

    Uiiiii, danke für die Aufklärung.

    Shade Of Mine schrieb:

    ...

    Vielleicht artet es auch jedes mal wenn du eine Frage stellst so aus, weil du einfach so stur bist, und meinst alles besser zu wissen? Auch wenn dir mehrere erfahrene, gute Entwickler sagen dass sie ganz entschieden anderer Meinung sind?



  • ps:
    Die Variante von theta ist mM. unnötig kompliziert. Das selbe erreichst du mit

    class Variable 
    { 
    public: 
         template <typename T> 
         void setType(T&& type) 
         { 
             m_type = std::unique_ptr<Type>(std::forward<T>(type));
         } 
    
    private: 
         std::unique_ptr<Type> m_type; 
    };
    

    Und vom Prinzip her macht die Lösung nicht viel was anderes als was ich vorgeschlagen habe.

    Nur dass mit meiner Variante (die ursprüngliche, nicht die hier gezeigte forward -Sache) die setType Funktionen ... naja, kürzer werden. Und vor allem kein Template sein müssen. Also ganz klar dass meine Variante kein Wort aber die von theta ein Danke verdient.

    Bullshit.



  • hustbaer schrieb:

    ps:
    Die Variante von theta ist mM. unnötig kompliziert. Das selbe erreichst du mit

    ...
    

    Oha, stimmt natürlich - hätte ich auch selber draufkommen können. 🙄


  • Mod

    Shade Of Mine schrieb:

    Eine andere Trivialitaet ist, dass new nichts boeses ist. Wir sagen das Anfaengern gerne weil es gut ist sie davon abzuhalten new zu verwenden. Aber wenn man sich ein bisschen auskennt erkennt man schnell das new ansich kein Problem ist, das Problem ist delete und ownership.

    Doch, rohes new provoziert Luecken im Ownership, erzeugt auf die Dauer bugs und sollte komplett durch make_* ersetzt werden.

    Mach nen eigenen Thead auf, dann erklaere ich dir RAII.



  • Verständnisfrage, weil ich mit C++14 noch nicht besonders viel gemacht habe: Sollte das im Original-Posting nicht eine rvalue-Referenz sein? Also

    void setType(unique_ptr<Type>&& type) {
    

    statt

    void setType(unique_ptr<Type>& type) {
    

    Sonst wird aus einer lvalue-Referenz gemoved, was irgendwie nicht richtig aussieht. Soweit ich das verstehe, funktioniert das schon (also kein undefined behavior oder sowas). Meine Frage ist eher, ob das was normales ist, unique_ptr als lvalue-Referenz zu übergeben, weil das dann eher wie auto_ptr wirkt.



  • Ja, vollkommen richtig. Von L-Value-Referenz-Parametern moven ist böse.
    Ich hab das auch schon kurz angesprochen, nur nicht weiter erklärt. Hätte ich vermutlich machen sollen.

    hustbaer schrieb:

    Wobei ich auch die normale Referenz bei deinem unique_ptr Setter suboptimal finde. Ich würde da eher nen by-value oder && Parameter erwarten.

    ps:

    Christoph schrieb:

    Meine Frage ist eher, ob das was normales ist, unique_ptr als lvalue-Referenz zu übergeben, weil das dann eher wie auto_ptr wirkt.

    In der Form, also wenn der unique_ptr "konsumiert" wird, ist das nicht normal.
    Bei Output-Parametern würde ich sagen ist es OK (ob man überhaupt Output-Parameter verwenden sollte ist ne eigene, davon unabhängige Frage).



  • Christoph schrieb:

    Verständnisfrage, weil ich mit C++14 noch nicht besonders viel gemacht habe: Sollte das im Original-Posting nicht eine rvalue-Referenz sein? Also

    void setType(unique_ptr<Type>&& type) {
    

    So sollte man es machen (wird in einigen Posts hier auch schon gesagt), es war im Original aber als Referenz beabsichtigt.



  • manni66 schrieb:

    es war im Original aber als Referenz beabsichtigt.

    Bin ich mir nicht sicher.
    Woraus schliesst du dass das so ist?



  • hustbaer schrieb:

    manni66 schrieb:

    es war im Original aber als Referenz beabsichtigt.

    Bin ich mir nicht sicher.
    Woraus schliesst du dass das so ist?

    Hm, hatte ich so im Kopf, ich kann jetzt aber auch nichts entsprechendes mehr finden.


Anmelden zum Antworten