I'm trying to use std::unique_ptr
with a custom deleter to simplify managing the life of handles returned to me from various C APIs. This is nice in theory, but I'm struggling to find an approach which is both optimal at runtime, and doesn't have a heap of boilerplate for every wrapped type.
For example, consider some opaque type foo
which must be freed by passing its pointer to destroy_foo
:
// approach 1: pass destroy_foo at runtime (bad for performance)
using foo_ptr = std::unique_ptr<foo, decltype(&destroy_foo)>;
foo_ptr bar{create_foo(...), destroy_foo};
// approach 2: make a deleter type (verbose - for many types)
struct foo_deleter
{
void operator()(foo* p)
{
destroy_foo(p);
}
};
using foo_ptr = std::unique_ptr<foo, foo_deleter>;
foo_ptr bar{create_foo(...)};
The first approach is hard for the compiler to optimize because I'm passing a function pointer around, so it's out. The second approach seems needlessly verbose. I have quite a lot of types like this I want to manage, and manually creating a class for each one is painful.
How can I define a class template that takes destroy_foo
and gives me a type equivalent to foo_deleter
? Or is there a standard library template to do this?
// best of both worlds - to_obj<Func> makes foo_deleter from destroy_foo...
using foo_ptr = std::unique_ptr<foo, to_obj<destroy_foo>>;
foo_ptr bar{create_foo(..)};
So given any function, the template would define a class with an operator()
which simply forwards all arguments to the function, and returns the result.