How to pass unique_ptr<T> in place of a raw *output* pointer parameter?
You can save one line of code (potentially many times) by writing many lines of code once:
class Wrapper
{
std::unique_ptr<MyThing> &u;
MyThing *p;
public:
Wrapper(std::unique_ptr<MyThing> &u) : u(u), p() {}
operator MyThing* & ()
{ return p; }
~Wrapper()
{ u.reset(p); }
};
Usage:
std::unique_ptr<MyThing> u;
CreateTheThing(Wrapper(u));
Is there a more direct method than this? One which doesn't require a temporary raw pointer?
No, there isn't.
Ideally, there would be a method of unique_ptr which exposes its internal pointer in a way that could work directly with the CreateTheThing method?
unique_ptr::get()
does not allow this, to my knowledge.
Your knowledge is correct. That would defeat the whole purpose of the std::unique_ptr
, therefore unique_ptr::get()
is a const
function and the pointer is returned by value.
However similar as your constructor example, you can always use std::unique_ptr::reset()
to pass an externally allocated pointer.
Also note: If the 3rd party API requires you to release the memory using free()
you may need to provide a special deleter function for the std::unique_ptr
.
If you use the function often you could put the conversion in a function.
Best would be to change the API, but this can also work.
inline std::unique_ptr<MyThing> CreateTheThing()
{
MyThing* p;
if (CreateTheThing(p))
{
return std::unique_ptr<MyThing>(p);
}
return std::unique_ptr<MyThing>();
}
You could also make this overload to make refactoring even easier:
inline bool CreateTheThing(std::unique_ptr<MyThing>& ptr)
{
try
{
MyThing* p;
if (CreateTheThing(p))
ptr = std::unique_ptr<MyThing>(p);
else
return false;
}
catch (std::bad_alloc&)
{
return false;
}
return true;
}