In der Theorie sollte ich in der Lage sein, einen benutzerdefinierten Zeigertyp und Deleter zu verwenden, damit unique_ptr ein Objekt verwaltet, das kein Zeiger ist. Ich habe versucht, den folgenden Code:Verwenden von unique_ptr zum Steuern eines Dateideskriptors
#ifndef UNIQUE_FD_H
#define UNIQUE_FD_H
#include <memory>
#include <unistd.h>
struct unique_fd_deleter {
typedef int pointer; // Internal type is a pointer
void operator()(int fd)
{
close(fd);
}
};
typedef std::unique_ptr<int, unique_fd_deleter> unique_fd;
#endif // UNIQUE_FD_H
Diese nicht (gcc 4.7 mit dem -std = C++ 11 Parameter) funktioniert. Es reagiert mit den folgenden Fehler:
In file included from /usr/include/c++/4.7/memory:86:0,
from test.cc:6:
/usr/include/c++/4.7/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = int; _Dp = unique_fd_deleter]':
test.cc:22:55: required from here
/usr/include/c++/4.7/bits/unique_ptr.h:172:2: error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator!='
in die Definition von unique_ptr Von einzutauchen, kann ich zwei Probleme sehen, dass es von der Arbeit verhindern. Der erste, der eindeutig gegen den Standard verstößt, ist, dass der Destruktor für unique_ptr den "Zeiger" (der gemäß meiner Definition ein int ist) mit nullptr vergleicht, um zu sehen, ob er initialisiert ist oder nicht. Dies steht im Gegensatz zu der Art und Weise, wie es durch die boolesche Umwandlung berichtet wird, die es mit "pointer()" (einem nicht initialisierten "Zeiger") vergleicht. Dies ist die Ursache für die Fehler, die ich sehe - eine Ganzzahl ist nicht mit einem Nullptr vergleichbar.
Das zweite Problem ist, dass ich eine Möglichkeit brauche, unique_ptr zu sagen, was ein nicht initialisierter Wert ist. Ich möchte das folgende Snippet arbeiten:
unique_fd fd(open(something...));
if(!fd)
throw errno_exception("Open failed");
Damit das funktioniert, unique_ptr wissen muss, dass ein „nicht initialisierte Wert“ -1 ist, als Null gültiger Dateideskriptor ist.
Ist das ein Fehler in gcc, oder versuche ich hier etwas zu tun, was einfach nicht möglich ist?
Danke, Shachar
Ich werde die offensichtliche hinzufügen. Anstelle von "int" kann ich den Zeigertyp auf eine Klasse setzen, die ich erfinde. So kann ich alles machen, was ich möchte. Dies wird jedoch keine triviale Klasse sein, da es implizite Umwandlungen in int und andere Dinge erfordert, die ich lieber vermeiden würde. –
Ich schlage vor, Sie aufhören zu verwenden 'std :: unique_ptr' für Non-Pointer-Speicher. Es erwartet, dass die Daten tatsächlich _be_ ein Zeiger sind, während Sie möchten, dass es ein _non-Zeiger_ ist. –
Umschließen Sie die Datei-APIs in einer anderen Klasse (RAII), die die Datei öffnet und den Dateideskriptor speichert. Die Klasse sollte den Deskriptor schließen, wenn der Destruktor aufgerufen wird. Verwenden Sie dann den eindeutigen Zeiger einer solchen Klasse. –