assign_ptr is a utility for interfacing C++ smart pointers with C-style APIs that allocate resources through output parameters.
// Allocates memory to output parameter 'p' via 'new'
// Caller responsible for freeing the allocated memory via 'delete'
void foo_alloc(int*& p);How to move the allocated raw pointer into a smart pointer for safety?
int* p_ = nullptr;
foo_alloc(p_);
std::unique_ptr<int> p(p_);Doable, but pollutes the scope with a temporary variable.
std::unique_ptr<int> p;
{
int* p_ = nullptr;
foo_alloc(p_);
p.reset(p_);
}Requires more lines of boilerplate code.
std::unique_ptr<int> p;
foo_alloc(zpp::assign_ptr(p));Done.
There is one unintuitive edge case to be aware of.
int* p = nullptr;
if (foo_alloc(p) && p != nullptr)
{
// Do something with `p`
}
delete p;is not equivalent to
std::unique_ptr<int> p;
if (foo_alloc(zpp::assign_ptr(p)) && p != nullptr)
{
// Impossible to enter this branch
// because `p` has not yet been set
}C++17 offers a solution via if-statement initialization.
std::unique_ptr<int> p;
if (foo_alloc(zpp::assign); p != nullptr)
{
// Do something with `p`
}assign_ptr should work with any class/struct that defines the following:
element_typetypereset(element_type*)member function
- std::unique_ptr
- std::shared_ptr
- std::auto_ptr
C++11 (but backporting to C++03 is possible)