This is also a problem when an object referenced by a shared_ptr is destroyed much later than expected because some obscure part of the code still holds a reference to the object.
That's why in many situations it makes sense to have an explicitly called discard() method, while the destructor is 'empty' and only checks that discard has actually been called.
Of course that also means that RAII isn't all that useful for such situations.
Because there may still be shared pointers in the wild holding a reference to the object and the last of those will call also attempt to call the destructor.
With an explicit deinit() method you'd basically get an object that's in an deinitialized, but not destructed state (quite similar to the state a moved-from object is in), the object still exists in memory and can react with proper errors to attempts to access.
The whole point of a shared_ptr is that you can't delete it out from under other users. You can do exactly what you suggest with a weak_ptr.
A shared_ptr to an object with a deinit() is rather like a weak_ptr in that someone else can "delete" it, and you should check if it's really there, except it can still have some information about things like deinit failures rather than just telling you that the object is deleted.
In this case it is clearly intended to be deleted under users, so why not use the language feature for that (destructor) instead of inventing yet another level of book-keeping.
You can, as long as you don't need to know if/how something within the deinit failed. If you literally just want to know if the item is gone, that's exactly a weak_ptr.
File streams, say, do this by expecting users to close() the file themselves if they care if exceptions happen, but if you destruct without doing that first, any exceptions are caught and don't make it out of the destructor, so they're just gone and you'll never know.
That's why in many situations it makes sense to have an explicitly called discard() method, while the destructor is 'empty' and only checks that discard has actually been called.
Of course that also means that RAII isn't all that useful for such situations.