std::unique_ptr-Implementierung



  • asfdlol schrieb:

    Hallo.

    Ich brauche für das Implementieren meiner C++03-Bibliothek std::unique_ptr s (zumindest gestaltet es das wesentlich eleganter). Wie sich erahnen lässt sollte dabei noch immer die Kompatibilität zu C++03 bestehend bleiben, weswegen ich ihn mir selbst implementiere.

    Spontan würde ich sagen: ohne rvalue-Referenzen geht das nicht



  • manni66 schrieb:

    asfdlol schrieb:

    Hallo.

    Ich brauche für das Implementieren meiner C++03-Bibliothek std::unique_ptr s (zumindest gestaltet es das wesentlich eleganter). Wie sich erahnen lässt sollte dabei noch immer die Kompatibilität zu C++03 bestehend bleiben, weswegen ich ihn mir selbst implementiere.

    Spontan würde ich sagen: ohne rvalue-Referenzen geht das nicht

    Klar, siehe boost.move.



  • Kellerautomat schrieb:

    manni66 schrieb:

    asfdlol schrieb:

    Hallo.

    Ich brauche für das Implementieren meiner C++03-Bibliothek std::unique_ptr s (zumindest gestaltet es das wesentlich eleganter). Wie sich erahnen lässt sollte dabei noch immer die Kompatibilität zu C++03 bestehend bleiben, weswegen ich ihn mir selbst implementiere.

    Spontan würde ich sagen: ohne rvalue-Referenzen geht das nicht

    Klar, siehe boost.move.

    Interessant!

    Und es gibt schon einen fertigen unique_ptr in boost ...
    Oder hier https://github.com/helloworld922/unique_ptr



  • HalliHallo schrieb:

    hast du das beachtet?

    Hast du den OP gelesen? Ich hab ja genau nach dem Sinn dahinter gefragt und ob man das nicht ein wenig lockern kann.



  • @asfdlol
    T* und U* sind nicht verwandt, nichtmal wenn T und U verwandt sind.
    Genau so sind T[42] und U[42] nicht verwandt, auch wenn T und U verwandt sind.
    Das ist der Grund.



  • hustbaer schrieb:

    T* und U* sind nicht verwandt, nichtmal wenn T und U verwandt sind.

    U* ist in T* konvertierbar wenn U von T abgeleitet ist (sorry, ich verstehe nicht ganz was du mit "verwandt" meinst). Und infolgedessen funktioniert auch std::unique_ptr<Base> Ptr(new Derived); .

    hustbaer schrieb:

    Genau so sind T[42] und U[42] nicht verwandt, auch wenn T und U verwandt sind.

    Aber man könnte U[42] mit einem T* wie ein T[42] benutzen, sofern U von T abgeleitet und gleich gross ist, was aber von der Standardbibliothek nicht erlaubt wird. Und wieso das explizit verboten wird obwohl es meiner Einsicht nach Sinn macht ist der Kern meiner Frage.



  • asfdlol schrieb:

    Aber man könnte U[42] mit einem T* wie ein T[42] benutzen, sofern U von T abgeleitet und gleich gross ist [...]

    Nope, da liegt dein Denkfehler, das kann man nicht machen (das wäre undefiniertes Verhalten). Dass ein Array implizit in einen Pointer auf das erste Element umgewandelt werden kann und ein U* implizit in einen T* umgewandelt werden kann, heißt nicht, dass ein U* das selbe ist wie ein T* oder ein Array aus U das selbe ist wie ein Array aus T oder gar, dass ein Array aus U einfach so in einen U* und weiter in einen T* gewandelt werden kann und dieser dann auf das erste Element zeigt...


  • Mod

    asfdlol schrieb:

    hustbaer schrieb:

    Genau so sind T[42] und U[42] nicht verwandt, auch wenn T und U verwandt sind.

    Aber man könnte U[42] mit einem T* wie ein T[42] benutzen, sofern U von T abgeleitet und gleich gross ist, was aber von der Standardbibliothek nicht erlaubt wird. Und wieso das explizit verboten wird obwohl es meiner Einsicht nach Sinn macht ist der Kern meiner Frage.

    Vermutlich weil es gefährlich und ungewöhnlich ist. Um das zuzulassen, müsste auf jeden Fall ein eigener Deleter verwendet werden (man könnte vielleicht die Delete-Spezifikation so erweitern, dass sie signalisiert, ob mit abgeleiteten Typen gearbeitet werden kann - kannst du ja gerne dem Standardkomittee vorschlagen). Ungewöhnlich ist es deshalb, weil die Größe von Objekten (oder deren Gleichheit) typischerweise nicht die Basis von Designentscheidungen ist.

    Ich bin nicht sicher ob die Verwendung von T[] als U[] unter den genannten Bedingungen in einer Umgebung zulässig ist, die "strict pointer safety" (3.7.4.3) implementiert. Bin mit diesem Teil des Standards nicht besonders vertraut.



  • Ist es nicht eher das Problem, dass man Arrays nicht polymorphisch behandeln kann?
    Schließlich ist Pointerarithmetik statisch mit sizeof(elem_type).



  • asfdlol schrieb:

    hustbaer schrieb:

    T* und U* sind nicht verwandt, nichtmal wenn T und U verwandt sind.

    U* ist in T* konvertierbar wenn U von T abgeleitet ist (sorry, ich verstehe nicht ganz was du mit "verwandt" meinst). Und infolgedessen funktioniert auch std::unique_ptr<Base> Ptr(new Derived); .

    Ich verstehe nicht was es an "nicht verwandt" nicht zu verstehen gibt. Nicht verwandt halt 🤡

    Base und Derived sind verwandt, ja. Deswegen kann man Derived* zu Base* konvertieren.

    Aber Base* und Derived* sind nicht verwandt. Deswegen kann man Derived** nicht zu Base** konvertieren.



  • Nathan schrieb:

    Schließlich ist Pointerarithmetik statisch mit sizeof(elem_type).

    Das ist kein Problem, denn die Typen sind ja

    asfdlol schrieb:

    gleich gross

    .

    hustbaer schrieb:

    Ich verstehe nicht was es an "nicht verwandt" nicht zu verstehen gibt. Nicht verwandt halt 🤡

    Base und Derived sind verwandt, ja. Deswegen kann man Derived* zu Base* konvertieren.

    Ah, jetzt verstehe ich was du mit verwandt meinst (dass sie in einem polymorphen Verhältnis stehen). Sorry, hab mich unnötig dumm angestellt; ist eigentlich offensichtlich, dass das gemeint ist.

    hustbaer schrieb:

    Aber Base* und Derived* sind nicht verwandt. Deswegen kann man Derived** nicht zu Base** konvertieren.

    Ja, das ergibt Sinn. Aber da diese Konvertierung ja nirgends benutzt wird (stets bloss Derived* zu Base* ), ist das irrelevant, oder? Oder möchtest du mir damit den Designfehler aufzeigen (wie als du vorhin gesagt hast, dass T[n] und U[n] nicht verwandt sind)?



  • asfdlol schrieb:

    hustbaer schrieb:

    Aber Base* und Derived* sind nicht verwandt. Deswegen kann man Derived** nicht zu Base** konvertieren.

    Ja, das ergibt Sinn. Aber da diese Konvertierung ja nirgends benutzt wird (stets bloss Derived* zu Base* ), ist das irrelevant, oder?

    Naja nö, es würde Derived(*)[N] in Base(*)[N] konvertiert. Und das geht halt auch net.

    error: cannot convert ‘Derived (*)[10]’ to ‘Base (*)[10]’ in assignment
      bp = dp;
    

Anmelden zum Antworten