Default-Initialisierung eines void* mit -1
-
Danke Finnegan, aber mit type traits funktioniert das leider nicht. Die WINAPI ist da leider inkonsistent, manche Funktionen, die ein
HANDLE
als Rückgabewert haben, liefern 0 (nullptr) zurück, andere -1 (INVALID_HANDLE_VALUE). Den ungültigen Wert per type trait zu bestimmen geht nicht, weil ich anhand des HANDLE nicht bestimmen kann, welcher der beiden Werte jetzt gebraucht wird.
-
@DocShoe sagte in Default-Initialisierung eines void* mit -1:
Danke Finnegan, aber mit type traits funktioniert das leider nicht. Die WINAPI ist da leider inkonsistent, manche Funktionen, die ein
HANDLE
als Rückgabewert haben, liefern 0 (nullptr) zurück, andere -1 (INVALID_HANDLE_VALUE). Den ungültigen Wert per type trait zu bestimmen geht nicht, weil ich anhand des HANDLE nicht bestimmen kann, welcher der beiden Werte jetzt gebraucht wird.Dann übergebe den "Invalid Value"-Typen einfach per Template-Parameter:
template <typename ObjectType, typename InvalidValueType> class SharedObject { ... ObjectType Object = InvalidValueType::invalid_value; }; ... using SharedWin32Handle = SharedObject<HANDLE, SharedObjectTraits<HANDLE>>; // oder welchen Typen auch immer: using SharedWin32Handle2 = SharedObject<HANDLE, InvalidValueType2>; using SharedWin32Handle3 = SharedObject<HANDLE, InvalidValueType3>;
Praktisch ist auch, dass man in der Klasse, die man als zusätzlichen Template-Parameter übergibt (oder als Traits-Klasse definiert), z.B. auch den Code unterbringen kann, um das Handle wieder freizugeben. Ich vermute mal da gibt es in Win32 auch vercheidene Funtionen für, je nachem, was für eine Art Handle es ist (?).
-
Und da beißt sich die Katze wieder in den Schwanz:
Code auf C++ShellHat den Fehler jetzt aus der Holder-Klasse in die Type-Traits Klasse verschoben
-
@DocShoe sagte in Default-Initialisierung eines void* mit -1:
Und da beißt sich die Katze wieder in den Schwanz:
Code auf C++ShellHat den Fehler jetzt aus der Holder-Klasse in die Type-Traits Klasse verschoben
Ich hatte in meiner Traits-Lösung das hier verlinkt (unter "so lösen").
Du kannst nicht implizit von
int
nachvoid*
konvertieren. Du muss das schon explizit machen.Und btw.: Es sind zwei Fehler hier. Einmal die implizite Konvertierung und dann (was mich auch überrascht hat) dass
reinterpret_cast
(die naheliegende Lösung für die Konvertierung) nicht imconstexpr
-Kontext erlaubt ist.
-
Jau, geht
Jetzt muss ich mir mal Zeit nehmen und gucken, ob sich das so umsetzen lässt.
-
@Finnegan sagte in Default-Initialisierung eines void* mit -1:
Praktisch ist auch, dass man in der Klasse, die man als zusätzlichen Template-Parameter übergibt (oder als Traits-Klasse definiert), z.B. auch den Code unterbringen kann, um das Handle wieder freizugeben. Ich vermute mal da gibt es in Win32 auch vercheidene Funtionen für, je nachem, was für eine Art Handle es ist (?).
Ja, für sowas habe ich Allocator-Klassen, die als Template Parameter übergeben werden. Tun hier aber nichts zur Sache, also habe ich sie ausgelassen.
-
@DocShoe sagte in Default-Initialisierung eines void* mit -1:
@Finnegan sagte in Default-Initialisierung eines void* mit -1:
Praktisch ist auch, dass man in der Klasse, die man als zusätzlichen Template-Parameter übergibt (oder als Traits-Klasse definiert), z.B. auch den Code unterbringen kann, um das Handle wieder freizugeben. Ich vermute mal da gibt es in Win32 auch vercheidene Funtionen für, je nachem, was für eine Art Handle es ist (?).
Ja, für sowas habe ich Allocator-Klassen, die als Template Parameter übergeben werden. Tun hier aber nichts zur Sache, also habe ich sie ausgelassen.
Macht es vielleicht Sinn,
invalid_value
zu einemstatic
Member dieser Klassen zu machen? Nur so als Anregung - das könnte den Code etwas kompakter machen und einiges an Boilerplate reduzieren. Welcher Handle-Wert ungültig ist, hängt doch sicher an den Funktionen, mit denen man das Objekt, auf welches das Handle verweist, erstellt, a.k.a "Allokations"-Funktionen, wenn ich das richtig verstehe (?). Das klingt für mich erstmal so, als obinvalid_value
vom Design her gut in diese Allocator-Klassen passen würde.
-
Geht sogar noch einfacher
Ich habe ja vorhin die Allocator-Klasse erwähnt, die für die Freigabe des gehaltenen Objekts verantwortlich ist. Die bekommt jetzt einfach noch ne statische Methode, die den ungültigen Objekttyp zurückgibt.
Im ersten Ansatz sähe das jetzt so aus:#include <memory> struct HandleAllocator { static void release( HANDLE object ) { CloseHandle( object ); } static HANDLE invalid_object_value() { return INVALID_HANDLE_VALUE; } }; template<typename ObjectType, typename Allocator> class SharedObject { struct Holder { ObjectType Object = Allocator::invalid_object_value(); Holder() = default; Holder( ObjectType object ) { Object = object; } ~Holder() { Allocator::release( Object ); } }; std::shared_ptr<Holder> Holder_; ... }; using Win32SharedHandle = SharedObject<HANDLE, HandleAllocator>; int main() { Win32SharedHandle sh; }
-
@DocShoe sagte in Default-Initialisierung eines void* mit -1:
Geht sogar noch einfacher
Ich habe ja vorhin die Allocator-Klasse erwähnt, die für die Freigabe des gehaltenen Objekts verantwortlich ist. Die bekommt jetzt einfach noch ne statische Methode, die den ungültigen Objekttyp zurückgibt.Finde ich sogar noch besser als Funktion. Flexibler und simplere Syntax.
P.S.: Wenn du die Funktion jetzt übrigens noch
constexpr
machst, dann schliesst sich der Kreis wieder und wir können die Diskussion von vorne beginnen... SCNR
-
@Finnegan sagte in Default-Initialisierung eines void* mit -1:
P.S.: Wenn du die Funktion jetzt übrigens noch
constexpr
machst, dann schliesst sich der Kreis wieder und wir können die Diskussion von vorne beginnen... SCNRIch hab´ Zeit