Combining a smart pointer with a collection we can get all the functionality that the original author wrote a custom class for, and a bit more:
typedef std::vector<std::shared_ptr<void>> garbage_collector;
Er, that's it. So how would you use this? Say you wanted to use character arrays as the author's examples:
std::shared_ptr<char> ptr( new char, std::default_deleter<char>() );
gc.push_back( ptr );
In this example ptr is the thing you'd use to do something with the memory you've allocated. When the memory's finished with ptr and gc go out of scope and everything's cleaned up.
Unlike the original tip this can manage "real" objects with destructors as the pointers don't have their types erased, just their interfaces. It can mix array and non-array types.
So everything's peachy? Actually no. Like the original tip this code is completely and utterly pointless. In both cases you're writing too much code.
In both cases instead of using raw pointers and manually managing memory there is a far simpler solution - use smart pointers and collections to manage your data. So instead of needing a baroque technique to avoid leaking memory when allocating arrays of characters just reach for a vector:
char *p = new char[ 128 ];
std::vector<char> buff( 128 );
and that really is it. There's no need to palm the allocated memory off on another auxilary data structure. There's nothing for the programmer to keep track of and less ways of blowing the program up.
So if a programmer you work with comes and tells you about an exciting and "safe" way of avoiding memory leaks you can give him the same answer I do: "Memory leak? Oh, that's so last century! I haven't had one of those since 1999."