Nutzen von boost::scoped_ptr
-
Shade Of Mine schrieb:
Denn um ehrlich zu sein: impliziter Ownership transfer schmeckt mir garnicht... Expliziter ist dagegen aber wieder OK - wenn dir das lieber ist.
Ja, finde ich auch besser. Aber in C++98 gehts halt nicht so wirklich schön. Sowas kann man zwar schon machen:
NonCopyablePtr a, b; a = Move(b);Aber für Funktionsparameter und -rückgabewerte muss man wieder zu einem anderen, implizit movable Typen greifen (der gleiche wie der, der als Zwischenstation für die Konvertierung im oberen Code genommen wird).
Shade Of Mine schrieb:
In dem Fall haette ich ein Objekt aus dem sich ein auto_ptr generieren laesst. Also die Factory liefert keinen auto_ptr sondern eben einen auto_ptr_helper den ich in einen auto_ptr kopieren kann.
Aber
auto_ptr_helpertransferiert dann im Prinzip auch den Besitz, oder wie kann ich mir das vorstellen?
-
Shade Of Mine schrieb:
...
Endlich sagt es mal einer.

Bis eben war das in mir ein Kopfchaos, getrieben von
- Extrembeisbielen, wo man es wohl braucht,
- und der Erfahrung, daß ich es doch nie brauche, in der Tat nie, und
- der häufigen Empfehlung in Foren.Gerade war ich aufnahmefähig, weil ich mich vor Tagen dazu durchgerungen habe, boost::any generell abzulehnen, denn heterogene Container sind nur mit Vererbung sinnvoll, das angegebene Beispiel von Interpretern zieht nicht, weil die die Vererbung doch erst recht lieben...
-
Nexus schrieb:
Was würdest du in C++98 für Ownership-Transfer wie bei einer Factory verwenden?
shared_ptrhat manchmal unnötigen Overhead, rohe Zeiger sind eine Fehlerquelle und sagen nichts über Ownership aus.In C++ 98 (03) würde ICH dafür std::auto_ptr verwenden. Ausgenommen Fälle wo es kein Schaden ist gleich boost::shared_ptr zurückzugeben - oft kommt man damit gut aus.
Oder gucken ob boost mittlerweile was unique_ptr-ähnliches anzubieten hat, was auch mit C++ 98 (03) funktioniert.
-
Okay.
Hast du schon mal was von Boost.Move gehört? Unter anderem soll Move-Semantik für C++98 emuliert werden, das Ganze ist aber (noch?) keine offizielle Boost-Bibliothek. Ich habe gerade gesehen, dass in dem Zusammenhang ebenfalls gewisse Smart-Pointer erwähnt werden, sieht recht interessant aus

P.S. Boost.Interprocess scheint
unique_ptrundmove()zu enthalten, aber ich bin mir nicht sicher, ob sie eine Implementierung für C++98 haben.
-
Nexus schrieb:
Shade Of Mine schrieb:
In dem Fall haette ich ein Objekt aus dem sich ein auto_ptr generieren laesst. Also die Factory liefert keinen auto_ptr sondern eben einen auto_ptr_helper den ich in einen auto_ptr kopieren kann.
Aber
auto_ptr_helpertransferiert dann im Prinzip auch den Besitz, oder wie kann ich mir das vorstellen?Die Idee ist folgende. Das ist nicht nur auf Smartpointer hier reduziert sondern ein Idiom dass immer mal wieder vorkommt. Leider kenne ich keinen Namen dafür.
Ein smartpointer ist nicht kopierbar und kann den ownership nicht transferieren. Jetzt erstellen wir ein Objekt, dass sich selbst zerstört - wie wir eben aus mojo oder (vermutlich ist boost.Move nichts viel anderes als ein modernes mojo) kennen: wir können mit diesem Hilfsobjekt einen echten smartpointer erstellen. Sobald wir das machen stirbt das Objekt. Wir moven es also quasi in den smartpointer.
Der Vorteil ist der: in der Factory selber brauchen wir die Smartpointer fähigkeit ja nicht. Wir wollen nur den smartpointer nach aussen geben. Wir wollen aber nicht kopieren, sondern moven. Dieses helper-Objekt erlaubt uns das. Ich habe mich nicht viel mit c++0x befasst, uU ist das ganze mit einem
return std::move(autoPtr);
in der Factory Methode schon getan.Jedenfalls ist das Hauptproblem wie man den ownership transfer eliminieren kann und dennoch vernünftige Interfaces anbieten kann.
Aber erzähl mal was dein smartpointer so genau macht. Prinzipiell bin ich immer für speziellösungen zu begeistern und du hast oft super Ideen. Also erzähl mal was du so hast

-
Nexus schrieb:
Hast du schon mal was von Boost.Move gehört? Unter anderem soll Move-Semantik für C++98 emuliert werden
Lol, jetzt werden sie aber kindisch.
-
Shade Of Mine schrieb:
Also erzähl mal was du so hast

Zunächst habe ich einen Smart-Pointer mit Deep-Copy-Semantik. Er erkennt den dynamischen Typen und kann dadurch ohne
Clone()polymorph kopieren:CopiedPtr<Base> p(new Derived); CopiedPtr<Base> q = p; // kopiert Derived-ObjektNun kommt es manchmal vor, dass man den Besitz verschieben will, ohne die teure Kopie zu haben.
CopiedPtr<Base> r = Move(p); // verschiebt Derived-ObjektSemantisch äquivalent könnte man zwar
CopiedPtr<Base> r; Swap(p, r);schreiben, aber die Über- und Rückgabe von Funktionen ist damit unpraktisch. Ein
r.Reset(p.Release())geht auch nicht, weil man damit Typinformation verliert (
Release()gibt nurBase*zurück). Also habe ich mir überlegt, einen ZwischentypMovedPtr<T>zu erstellen, der das Objekt verschieben kann und die Typinformation bewahrt. Damit führt der Aufruf vonMove()zu den KonvertierungenCopiedPtr<Base> -> MovedPtr<Base> -> CopiedPtr<Base>. Nun kann man das Gleiche auch mit nichtkopierbaren Smart-Pointern machen, also ein explizites Move wie beistd::unique_ptr, aber mit C++98-Mitteln.ScopedPtr<Base> p(new Derived); ScopedPtr<Base> q = Move(p);Bei Funktionen muss man jedoch explizit
MovedPtrhinschreiben, wenn man zu/von ihnen Besitz transferieren will.MovedPtr<Base> Source(); void Sink(MovedPtr<Base> p);Mojo sagte mir bisher noch nichts. Scheint eine C++-Bibliothek von Andrei Alexandrescu zu sein, abgesehen vom Artikel bei Dr. Dobbs habe ich aber nicht viel dazu gefunden. Muss ich auch mal genauer anschauen, danke für die Erwähnung!