"move-ctor" mit anderem Parametertyp möglich?



  • Vielen Dank für die schnelle Antwort!

    cooky451 schrieb:

    1. Nein, du kannst vector nicht beibringen dass er seinen Kram nicht delete[]en soll.

    Das hätte ich natürlich einfach mal ausprobieren können 🤡, trotzdem danke!


  • Mod

    1. Nein, du kannst vector nicht beibringen dass er seinen Kram nicht delete[]en soll.

    🤡
    Edit: Nein, ist natuerlich Unsinn.



  • Wenn das wirklich gewünscht ist, kann das Verhalten mit relativ wenig Overhead bereitgestellt werden.

    Pseudocode:

    template <class C>
    struct basic_storage {
      virtual T* data()=0;
      virtual size_t size()=0;
      virtual ~basic_storage(){}
    };
    template <class C>
    struct container_storage : basic_storage<C> {
      C storage;
      container_storage(C&& c) : storage(std::move(c)); }
      T* data() { return storage.data(); }
      size_t size() { return storage.size(); }
    };
    template <class T>
    struct default_storage_holder : basic_storage {
      ...
    };
    template<class T>
    class MyContainer
    {
        T* data_;
        size_t size_;
        std::unique_ptr<basic_storage<T> > storage_holder;
    
        void init()
        {
           data_ = storage_holder->data();
           size_ = storage_holder->size();
        }
    
    public:
        MyContainer(std::vector&& rhs)
        : storage_holder(new container_storage_holder(std::move(rhs)))
        { init(); }
        MyContainer(size_t n)
        : storage_holder(new default_storage_holder(n))
        { init(); }
    
        ...
    };
    

    Wenn du den Allocator im Typ mitführst (was etwas Umständlicher ist, aber bei sehr vielen sehr kleinen Vektoren [was man besser vermeiden sollte] einen Unterschied machen kann), kann das Type-Erasure umgangen werden.

    PS:

    Arcoth schrieb:

    Edit: Nein, ist natuerlich Unsinn.

    So stimmt zumindest schon die Formulierung 👍


  • Mod

    natürlich schrieb:

    ...

    Toll, du haeltst dann einfach intern einen zweiten vector , damit waere das lediglich ein Adapter.

    Edit: Nein, das koennte in der Tat das sein, was der TE wollte. Die Frage ist, was dieser ueberhaupt braucht - bzw. welches Problem er damit loest.



  • Biete einen Konstruktor an, der eine Iterator-Range nimmt. Dann kann der Benutzer immer noch mit std::move_iterator Elemente aus einem anderen Container verschieben.

    Die interne Datenstruktur verschiedener Container zu verschieben ist meist unmöglich (da du keinen Zugriff hast und sie sich unterscheidet).



  • Datendieb schrieb:

    3. Gibt es überhaupt Fälle, in denen ein Konstruktor dieses Typs (nimmt rValue-reference eines anderen Typs) in Ordnung wäre?

    Ich nehme an dass die Frage unabhängig vom konkreten Fall "Container" zu verstehen ist.

    Dann: ja, klar. Ich könnte mir z.B. vorstellen dass man zwecks Kapselung ein und die selben Daten einmal in "editierbarer" und einmal in "nur lesbarer" Form haben möchte.

    Könnten verschiedenste Dinge sein, z.B. irgendwelche Datenobjekte mit Business-Rules, 3D-Meshes - was auch immer.
    Einen Grossteil davon könnte man noch mit const erschlagen. Aber die "nur lesbare" Form könnte vielleicht deutlich weniger Dependencies haben, und verwendet werden um an Modulgrenzen den Dependency-Wildwuchs einzudämmen.
    Wenn man die Objekte dann von einer Form in die andere bringen kann, und die interne Repräsentation gleich ist, dann kann so ein "konsumierender Konvertierungskonstruktor" schon Sinn machen.

    Bzw. eine andere Sache wo const nicht ausreicht wäre wenn man nur einen Teil der Daten der "editierbaren" Form übernehmen will -- weil diverse Hilfsobjekte/Indexe/Einträge in der "nur lesbaren" Form nicht nötig sind. Dann kann die nur lesbare Form die editierbare beklauen, und einfach alles freigeben was sie nicht braucht.

    Oder ein FileLogger wo ich das zu Output-File beim Konstruieren des Loggers "reinmoven" kann hätte auch so einen Konstruktor. Wäre semantisch dann zwar kein Kopierkonstruktor mehr, formal aber genau das selbe (Rvalue Konvertierungskonstruktor halt).



  • Zunächst noch einmal danke für die Antworten und Anregungen!

    Arcoth schrieb:

    Nein, das koennte in der Tat das sein, was der TE wollte. Die Frage ist, was dieser ueberhaupt braucht - bzw. welches Problem er damit loest.

    Vielleicht noch einmal ein paar Worte zum Hintergrund:
    In den Softwaremodulen, an denen ich mitarbeite, werden selbst implementierte Container verwendet, sind an sehr vielen Stellen im Einsatz und haben gegenüber den STL-Containern einige Limitationen. In Fällen, in denen man die STL-Algorithmen gerne einsetzen würde, das aber nicht ohne weiteres kann, weil die Daten in einem eigenen Container liegen, werden dann oft einfach "STL-Kopien" erstellt und auf diesen gearbeitet.
    Ich hatte mir dann die Frage gestellt, ob sich zumindest in manchen Fällen die Kopien vermeiden ließen, indem man die Daten an einen STL-Container transferiert. Und weil das Thema move-semantics für mich recht neu ist, kamen auch ein paar grundsätzliche Fragen auf. So kam es zu diesem Thread.

    Vielleicht geht dieser Ansatz aber ohnehin in die komplett falsche Richtung und es müsste z.B. über die Iteratoren gehen...
    Wenn es diesbezüglich bessere Ideen gibt, höre ich mir die natürlich gerne an.


  • Mod

    In den Softwaremodulen, an denen ich mitarbeite, werden selbst implementierte Container verwendet, sind an sehr vielen Stellen im Einsatz und haben gegenüber den STL-Containern einige Limitationen.

    Warum zum Teufel schreibt ihr die STL neu?

    In Fällen, in denen man die STL-Algorithmen gerne einsetzen würde, das aber nicht ohne weiteres kann, weil die Daten in einem eigenen Container liegen

    Moment, das ist kein Grund. STL-Algorithmen arbeiten über Iteratoren, die kann jeder Container anbieten, auch über Zeiger. Gerade deswegen ist es ja so sexy.



  • Sexy finde ich iteratoren nicht greade. Flexibel ist es natürlich, und daher, wenn man diese Flexibilität mal braucht, praktisch.
    (So lange man es nicht braucht nervt es aber eher.)

    `boost::trim(str); // yeah

    std::sort(str.begin(), str.end()); // fuck off!`
    😉


  • Mod

    #define RANGE(r) (r).begin(), (r).end()
    
    std::sort(RANGE(str)); // fuck yeah!
    

    Moment! Wieso darf hustbaer das f-Wort schreiben, und ich nicht!? fuck !

    Edit: Natürlich besser:

    #define RANGE(r) std::begin(r), std::end(r)
    


  • Besserer:

    boost::sort(str)
    

  • Mod

    Ja, natürlich. Ich dachte, es ging hier um Standardmittel.



  • Arcoth schrieb:

    Moment! Wieso darf hustbaer das f-Wort schreiben, und ich nicht!? love !

    Dafür musst du mehr als 10K Beiträge haben.

    Ne, ernsthaft - guck einfach nach wie ich es gemacht hab, ist ja nicht schwer rauszufinden 😉


  • Mod

    Oh, ein sehr gewitzter Trick 👍


Anmelden zum Antworten