Yes, I was wondering if the magic call inside of smart_ptr's constructor,
that handles the enabled_shared_from_this, wouldn't be better as a free
function, like smart_pointer_being_created(), which gives you an extension
point to go look up whether the object already had a smart pointer. It
could default back to the enabled_shared_from_this trick if you don't
override it for your types, etc.
Qt's smart pointer has extra tracking like this - typically only turned on
in debugging.
The issue boils down to non-intrusiveness. I used a base class 'can_handle' for types I
Gottlob Frege wrote:
planned on using smart pointers on, much as you inherit from enable_shared_from_this but
without the need for CRTP. The free function that looks up the 'lifetime object' for any
given pointer (which may or may not already exist in the system) can be overloaded for
different ways of doing it for different classes, and inheriting from that base allows it
to match the intrusive form. Now as it turns out I never needed to make shared_ptr's to
types that I did not define (or trivially derive from), so it never bothered me; but the
intent was that a non-intrusive general solution would use a map or something. Only later
did I figure out the catch: knowing when the map can be cleaned up of counts to deleted
objects. Certainly it can be done: the logic in the smart pointer "I hit zero, free it"
code can call another free function to report it; the deleter can capture the need to
supplement the normal destructor with additional cleanup; etc.
Certainly with the maturity of current compilers there is no reason not to support "lost
and found" in an efficient manner. If non-intrusive, it only pays for it when you
construct a smart pointer from a raw pointer (potential "find"), and for creating fresh
objects a make_shared bypasses that step and knows that it does not exist already in the
system anyway.
Or, just as you have shared_from_this available now only if enabled, you can have
lost-and-found available only if enabled using the intrusive mechanism. Basically,
shared_from_this would always work whether it was "in the system" already or not, and
constructing a shared_ptr from a raw ptr that has such a base class would call
shared_from_this on it rather than new'ing up the counter object. Easy.
Hmm, a non-standard shared_from_this mechanism that works this way could still
interoperate with code that expects standard shared_ptr class to be used, if you call it
that way yourself when you need to "find". Standard code never will, and constructing a
shared_ptr the normal way still works as it always did.
Now I have noticed that the implementations for shared_from_this interact with internals
of weak_ptr. But a portable implementation doesn't have to. If I had time to write for
magazines (and such magazines still existed) I'd write that up for an issue.
—John