Reputation: 28761
I am dealing with C types which have a new_
and free_
methods associated.
The type signature of new_
may vary, but the free_
is always a void free_something(something*);
Currently, I am declaring my unique_ptr
s this way, which seems overly verbose:
std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
Can I do this with less ceremony, somehow? I saw a neat solution for a situation when my deallocator is the std::free()
function, at https://stackoverflow.com/a/43626234/1047788. I tried to create a version where I could parameterize the deallocator, but I got nowhere with it.
The best I could think of was to create a macro from the above declaration.
Upvotes: 3
Views: 340
Reputation: 238311
I've been using following:
template <auto fptr>
struct Caller {
template <class... Args>
auto
operator()(Args&&... args) noexcept
{
return fptr(std::forward<Args...>(args)...);
}
};
Example usage:
using qdr_freer = Caller<free_qdr_link_t>;
using unique_qdr_ptr = std::unique_ptr<qdr_link_t, qdr_freer>;
[[nodiscard]] unique_qdr_ptr
make_qdr_unique()
{
return unique_qdr_ptr{new_qdr_link_t()};
}
This implementation uses C++17 features though, so it requires a few changes to work in C++11.
Note that although Caller
may seem like a good fit with std::free
, they are strictly speaking not compatible because std::free
is a standard library function not designated as "addressable".
Upvotes: 3
Reputation: 17454
Let the language do the hard work!
#include <memory>
struct qdr_link_t;
qdr_link_t* new_qdr_link_t();
void free_qdr_link_t(qdr_link_t*);
template <typename T, typename Deleter>
auto make_unique_ptr(T* raw, Deleter deleter)
{
return std::unique_ptr<T, Deleter>(raw, deleter);
}
//std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
auto link = make_unique_ptr(new_qdr_link_t(), free_qdr_link_t);
Add std::forward
to taste (if you care).
For C++11, you'll need to add the trailing return type -> std::unique_ptr<T, Deleter>
to make_unique_ptr
, or just put that in the "normal" return type.
Upvotes: 1