This article starts with a flawed premise, that the right way to create a managed pointer is something like this[1].
std::unique_ptr<void,void(*)(void*)> big_ptr(malloc(1), free);
The wasteful thing about this is that you have to store the deleter (free() in this case) right next to your void* for
every pointer you manage, so the unique_ptr is twice as large as it needs to be. What you'd like to do is store the deleter in the type of the pointer rather than the pointer itself. It turns out unique_ptr can handle this. If the second template parameter is a type with an overloaded function call operator, then unique_ptr will use that to delete. We can wrap it up like so.
template <class T, void F(T *)> struct unique {
struct deleter { void operator()(T *p) { F(p); }; };
typedef std::unique_ptr<T, deleter> ptr;
};
With this helper type you can now declare a similar managed pointer
unique<void, free>::ptr small_ptr(malloc(1));
but this time notice that the deleter function is the second template parameter and not an argument to the constructor and the following holds.
assert(2 * sizeof(small_ptr) == sizeof(big_ptr));
[1] I used malloc() and free() so those of you following along at home can easily try this out for yourselves.