Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unique_ptr deleter pointer to pointer

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?

like image 833
user2363399 Avatar asked Nov 01 '22 00:11

user2363399


1 Answers

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 value d of type D and a value ptr of type unique_ptr<T, D>::pointer, the expression d(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.

like image 151
dyp Avatar answered Nov 15 '22 04:11

dyp