Design Problem: Zugriff auf RAII Resource
-
@knivil:
Meinst du folgendes?class BitmapDeleter { public: void operator()(HANDLE* Bitmap) { DeleteBitmap(*Bitmap); delete Bitmap; } }; class MeineGUI { private: std::unique_ptr<HANDLE, BitmapDeleter> FacadeBitmap; public: MeinGui() : FacadeBitmap(new HANDLE(LoadBitmap("bbb"))) { } };
-
Ich verstehe nicht, wieso das Fenster nicht einfach Ownership von der Bitmap-Klasse haben soll und die Bitmap-Klasse Ownership vom Handle. Dann hat das Fenster doch gleichzeitig Ownership vom Handle.
HANDLE ist als PVOID definiert, also würde ich mit new/delete hier überhaupt nicht rumhantieren.
-
Ja, aber der Punkt ist, dass unique_ptr einen Pointer dranhängt an HANDLE.
Das heißt man muss das HANDLE selber entweder via new erzeugen oder remove_ptr auf HANDLE klatschen und dann einfach nur LoadBitmap übergeben.
-
Bitte ein Bit schrieb:
class BitmapDeleter { public: void operator()(HANDLE* Bitmap) { DeleteBitmap(*Bitmap); delete Bitmap; } }; class MeineGUI { private: std::unique_ptr<HANDLE, BitmapDeleter> FacadeBitmap; public: MeinGui() : FacadeBitmap(new HANDLE(LoadBitmap("bbb"))) //A { } };Du hast in Zeile A ein Ressourcenleck. Wer gibt die Bitmap wieder frei, wenn
new HANDLEfehlschlägt? Es ist nämlich nicht vorgeschrieben, dass die Speicheranforderung beinewvor der Auswertung der Konstruktorargumente stattfindet.
Außerdem bietet es sich im Deleter an, aufnullptrzu prüfen.std::shared_ptrruft den nämlich auch mitnullptrauf.
Und es wäre vielleicht schön bei Fehlschlag vonLoadBitmapzu werfen.Was ist das Problem an
unique_ptr<std::remove_pointer<HANDLE>::type, BitmapDeleter>? Der Typ vonHANDLEwird sich doch niemals ändern.typedef std::unique_ptr<std::remove_pointer<HANDLE>::type, BitmapDeleter> bitmap_handle; bitmap_handle load_bitmap(char const *s) { bitmap_handle result{LoadBitmap(s)}; if (!result) { throw std::runtime_error(...); //oder so } return result; }
-
Erstmals danke für die Info's!

Was ist das Problem an unique_ptr<std::remove_pointer<HANDLE>::type, BitmapDeleter>?
Ich kenne mich leider nicht so gut mit der STL aus. Ich kenne die ganzen Standardcontainer. Aber Dinge wie std::remove_pointer sind noch Neuland für mich.
Ich musste jetzt erstmals schauen wie ich aus *bitmap_handle wieder ein HANDLE bekomme. Genauer gesagt nutze ich HBITMAP.
-
Bitte ein Bit schrieb:
Aber Dinge wie std::remove_pointer sind noch Neuland für mich.
LOL
-
Also wenn du mich fragst ist Variante 1 in deinem Anfangsposting the way to go, wenn du nur einen RAII Wrapper für ein rohes HBITMAP haben willst (ich würd überhaupt einfach eine User Defined Conversion nach HBITMAP machen und fertig). Der Sinn von einem std::remove_pointer<HANDLE> will sich mir außerdem nicht erschließen, das sieht mir eher aus wie der Versuch, die Grundidee eines HANDLE zu untergraben...
-
dot schrieb:
Der Sinn von einem std::remove_pointer<HANDLE> will sich mir außerdem nicht erschließen, das sieht mir eher aus wie der Versuch, die Grundidee eines HANDLE zu untergraben...
Ne, da holt man den Pointer nur vorher ausm Typen raus, damit unique_ptr ihn später wieder dran kleben kann. Das passt schon so. unique_handle wäre natürlich schöner, aber das gibt's ja noch nicht.
-
cooky451 schrieb:
dot schrieb:
Der Sinn von einem std::remove_pointer<HANDLE> will sich mir außerdem nicht erschließen, das sieht mir eher aus wie der Versuch, die Grundidee eines HANDLE zu untergraben...
Ne, da holt man den Pointer nur vorher ausm Typen raus, damit unique_ptr ihn später wieder dran kleben kann. Das passt schon so.
Das alles funktioniert aber nur unter der Voraussetzung, dass HANDLE tatsächlich ein Pointertyp ist, was in der Praxis natürlich so ist; dennoch: imo ein extrem unsauberer Hack. unique_handle o.ä. ist viel zu schnell geschrieben, als dass derartiger Missbrauch von unique_ptr irgendwie zu rechtfertigen wäre...
-
Das hatte ich schon befürchtet. Ich kenne auch Handle Implementierungen, welche nur einen Index auf einer Tabelle darstellen.
Also ist die erste Lösung doch nicht so schlecht.