In theory, I should be able to use a custom pointer type and deleter in order to have unique_ptr
manage an object that is not a pointer. I tried the following code:
#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
This doesn't work (gcc 4.7 with the -std=c++11
parameter). It responds with the following errors:
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!='
From delving into the definition of unique_ptr
, I can see two problems that prevent it from working. The first, which seems in clear violation of the standard, is that the destructor for unique_ptr
compares the "pointer" (which is, as per my definition, an int) to nullptr
in order to see whether it is initialized or not. This is in contrast to the way it reports it through the boolean conversion, which is to compare it to "pointer()"
(an uninitialized "pointer"). This is the cause of the errors I am seeing - an integer is not comparable to a nullptr
.
The second problem is that I need some way to tell unique_ptr
what an uninitialized value is. I want the following snippet to work:
unique_fd fd( open(something...) );
if( !fd )
throw errno_exception("Open failed");
For that to work, unique_ptr
needs to know that an "uninitialized value" is -1, as zero is a valid file descriptor.
Is this a bug in gcc
, or am I trying to do something here that simply cannot be done?
std::unique_ptr
for non-pointer storage. It expects the data to actually be a pointer, while you want it to be a non-pointer. – Sternutationstd::handle
similar tostd::unique_ptr
but withoutoperator*
, and two extra template parameters:class handle_type=void*
, andhandle_type null_value=nullptr
. – Tuddor