Hier ist ein Problem, auf das ich oft mit RAII stoße. Ich habe mich gefragt, ob jemand eine gute Lösung dafür hatte.RAII und abgeleitete Template-Argumente
Beginnen Sie mit Ihrem Standard-RAH Utility-Klasse:
class RAIIHelper {
RAIIHelper() {
AcquireAResource();
}
~RAIIHelper() {
ReleaseTheResource();
}
};
nun aus verschiedenen Gründen, ich brauche es eine Vorlage zu machen. Nehmen wir an, auch den Konstruktor ein Argument der Template-Parameter-Typ nimmt:
template <typename T>
class RAIIHelper {
RAIIHelper(T arg) {
AcquireAResource();
}
~RAIIHelper() {
ReleaseTheResource();
}
};
Betrachten wir nun eine Verwendung Website:
void func() {
RAIIHelper<SomeType> helper(someObj);
}
Es ist ärgerlich, haben zu schreiben, SomeType
wann kann es aus someObj
abgeleitet werden, so schreibe ich eine Hilfsfunktion den Typ ableiten:
template <typename T>
RAIIHelper<T> makeRAIIHelper(T arg) {
return RAIIHelper<T>(arg);
}
Jetzt kann ich es verwenden, etwa so:
void func() {
auto helper = makeRAIIHelper(someObj);
}
Wunderbar, oder? Außer dass es einen Haken gibt: RAIIHelper
muss jetzt kopierbar oder beweglich sein, und der Destruktor - der die Ressource freigibt - kann möglicherweise zweimal aufgerufen werden: einmal für das temporäre von makeRAIIHelper
zurückgegebene und einmal für die lokale Variable in der aufrufenden Funktion.
In der Praxis führt mein Compiler RVO und der Destruktor wird nur einmal aufgerufen. Dies ist jedoch nicht garantiert. Dies kann von der Tatsache gesehen werden, wenn ich versuche, RAIIHelper
einen = delete
'd move-Konstruktor zu geben, kompiliert der Code nicht mehr.
Ich könnte RAIIHelper einen zusätzlichen Status hinzufügen, so dass es ReleaseTheResource()
nicht zu rufen, nachdem es verschoben wurde, aber das ist zusätzliche Arbeit, die unnötig war, bevor ich makeRAIIHelper()
hinzugefügt, um den Typabzug zu erhalten.
Gibt es eine Möglichkeit, den Typ Abzug zu bekommen, ohne extra Staat zu RAIIHelper
hinzufügen?
Abgesehen davon, dass du 'unique_ptr' dort neu erfindest, bist du sicher, dass es absolut kein natürliches Sentinel-Objekt vom Typ' SomeType' gibt? – Deduplicator
Sie können ein 'unique_ptr' verwenden. –
Schreiben Sie einen richtigen Move-Konstruktor und deaktivieren Sie den Kopierkonstruktor. Dies sollte kein Problem sein. –