Reputation: 3692
In using std::unique_ptr
with a custom deleter I desire to use std::make_unique
rather than a raw new. I am using VC++2013. It appears to me that there is no way to use std::unique_ptr
if you are using a custom deleter. Did I miss something or is this really the case?
Additional Information:
I am using a std::unique_ptr<HANDLE, custom_deleter>
to hold a Windows HANDLE for an opened COM port.
I could write a custom RAII class for this, and it wouldn't be terribly difficult, but I was seeing how hard/difficult/bad it would be to use std::unique_ptr
.
Upvotes: 56
Views: 42091
Reputation: 143
Here is a way to wrap c style memory management into a std::unique_ptr
using a custom deleter that calls a custom free function. This has a make function helper similar to std::make_unique
LIVE:
#include <iostream>
#include <functional>
#include <memory>
// Some C style code that has some custom free function ptr...
extern "C" {
struct ABC { };
enum free_type_e {
FREE_ALL,
FREE_SOME
};
typedef void (free_f)(enum free_type_e free_type, void *ptr);
struct some_c_ops { free_f* free_op; };
void MY_free(enum free_type_e free_type, void *ptr)
{
printf("%s:%d ptr=%ld\n", __func__, __LINE__, (long)ptr);
(void)free_type;
free(ptr);
}
}; // extern "C"
template<typename T>
using c_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
template <typename T>
c_unique_ptr<T> make_c_unique(some_c_ops* op, free_type_e free_type)
{
return c_unique_ptr<T>(static_cast<T*>(calloc(1, sizeof(T))),
std::bind(op->free_op, free_type, std::placeholders::_1));
}
void foo(c_unique_ptr<ABC> ptr)
{
std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
}
int main()
{
some_c_ops ops = { MY_free };
c_unique_ptr<ABC> ptr = make_c_unique<ABC>(&ops, FREE_ALL);
std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
foo(std::move(ptr));
std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
}
Possible output:
main:48 ptr=50511440 foo:40 ptr=50511440 MY_free:20 ptr=50511440 main:53 ptr=0
Upvotes: 3
Reputation: 319
As far as I know there is no make_unique
function in the C++11 standard. See
So I would assume that the make_unique
is an implementation from Microsoft that is at least not included in the standard.
But nevertheless you can use a custom deleter with unique_ptr
. When using unique_ptr
you have to specify the type of the deleter as a second template argument and then pass an appropriate object to the constructor.
Upvotes: -5
Reputation: 477010
The whole point of make_unique
is to encapsulate the notion of "use new
to create a T
from given constructor arguments and use delete
to destroy it".
If you wanted a custom deleter, you would also have to specify how to create the object, and then there would be nothing more gained from having the emplacing maker function.
I wrote some examples of custom maker functions for certain unique resource handles in this post.
Upvotes: 48