I am trying to map a third-party API using a unique_ptr custom deleter. The problem is that the API is as such:
x *x_alloc_x(void);
void x_free_x(x **p);
The API wants me to provide a pointer to a pointer for it to set to NULL. I have been writing my deleter functor as taking a reference-to-pointer, which I convert to pointer-to-pointer with the "&" operator.
struct XDeleter {
void operator(x *&p) { x_free_x(&p); }
};
This has worked with GCC 4.6, but is this actually permitted by the standard? If not, is there a standard-compliant way to map this API to a deleter?
The code is not well-formed. n3797 [unique.ptr.single.dtor]/1 requires in the destructor of unique_ptr
:
Requires: The expression
get_deleter()(get())
shall be well formed [...]
Where [unique.ptr.single] specifies:
pointer get() const noexcept;
That is, get()
is a prvalue.
Additionally, [unique.ptr.single]/1
A client-supplied template argument
D
[the deleter type] shall be a function object type, lvalue-reference to function, or lvalue-reference to function object type for which, given a valued
of typeD
and a valueptr
of typeunique_ptr<T, D>::pointer
, the expressiond(ptr)
is valid and has the effect of disposing of the pointer as appropriate for that deleter.
A value is a prvalue.
The solution has been given in the comments by Mooing Duck:
struct XDeleter {
void operator(x *p)
{ x_free_x(&p); }
};
The destructor of unique_ptr
however is not required to assign nullptr
to the stored pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With