I am creating a class which interops with some Windows API code, now one of the pointers I have to initialize is done by calling a native function which initializes it.
My pointers are of type std::unique_ptr with a custom deleter, which calls the WinAPI deleter function provided, however I cannot pass the unique_ptr with the & address-of operator to the init-function. Why?
I have created a sample that demonstrates my problem:
#include <memory>
struct foo
{
int x;
};
struct custom_deleter {};
void init_foo(foo** init)
{
*init = new foo();
}
int main()
{
std::unique_ptr<foo, custom_deleter> foo_ptr;
init_foo(&foo_ptr);
}
The compiler barks and says:
source.cpp: In function 'int main()':
source.cpp:19:21: error: cannot convert 'std::unique_ptr<foo, custom_deleter>*' to 'foo**' for argument '1' to 'void init_foo(foo**)'
Somewhere under the covers,
unique_ptr<foo>has a data member of typefoo*.However, it’s not legitimate for a user of the class to directly modify that data member. Doing so would not necessarily preserve the class invariants of
unique_ptr, in particular it wouldn’t free the old pointer value (if any). In your special case you don’t need that to happen, because the previous value is 0, but in general it should happen.For that reason
unique_ptrdoesn’t provide access to the data member, only to a copy of its value (viaget()andoperator->). You can’t get afoo**out of yourunique_ptr.You could instead write:
This is exception-safe for the same reason that
std::unique_ptr<foo, custom_deleter> foo_ptr(new foo());is exception-safe:unique_ptrguarantees that whatever you pass in to its constructor will eventually get deleted using the deleter.Btw, doesn’t
custom_deleterneed anoperator()(foo*)? Or have I missed something?