There is another option, that the factory maintains some kind of pool of objects and that an object (once created) is never destroyed. This is probably a very rare case but it does happen (e.g. Singleton design pattern). In this case the factory is correctly written and shouldn’t be changed.
What’s missing from the standard is some kind of unowned_ptr<T> which would document these cases.
I think shared_ptr is rather suspicious since it breaks the lifetime semantics of shared_ptr.
Normally having a shared_ptr implies that the pointed to object will be kept alive until all shared_ptr’s to it are gone but if you use a null_deleter then you can end up with a valid shared_ptr that points to a deleted object.
There’s another ripple that the solution doesn’t acknowledge.
The original calling code has a raw pointer. After all, it’s modern and so it’s using `auto` when it calls the factory function that returns a raw pointer. Therefore, assuming the current calling code it correct, it’s making at least one cleanup call (e.g., `delete widget;` or `free_widget(widget);`). Changing the factory to a smart pointer means you’ll have to search through all the calling code to delete those cleanup operations.
I would have commented directly on the solution, but it seems you disable comments on the solutions.
@Adrian: The compiler will tell the caller all the places that delete so that one’s fine. Just like it will tell you all the cases where the caller might try to convert to store the pointer as another type.