I have just one comment. I would recommend returning a unique_ptr instead of a shared_ptr, as you can then use the object as a unique_ptr, be move it into a shared_ptr, or adopt it by other means elsewhere in your data structures. Returning a shared_ptr locks you into keeping the data as a shared_ptr.
Best Regards,
M. Scott Mueller