Smart pointers are about ownership.
Ownership is about lifetime.
const std::string toJson(const Location &obj);
This says "you will pass an obj
which is a valid Location
, and this function promises not to change it".
The return value -- const std::string
-- is a toxic anti-pattern. Don't do that. Return std::string
.
std::string toJson(std::weak_ptr<const Location> obj);
This states "I will take a possibly valid reference to an obj
, which I will faithfully store somewhere. At some unknown future point, I will check if that object still exists, and create a shared pointer to it. Once you call this function, do not assume that the lifetime of the pointed to obj
will end at any controlled spot; but usually I'll be polite, and not hold onto a generated shared_ptr
for more than a short bit".
std::string toJson(std::shared_ptr<const Location> obj);
This says "I want to participate in the shared management of the pointed to obj
. obj
has and should have a complex lifetime which cannot be easily expressed through simple ownership. I tried to use simpler ownership models, but they don't reflect the true essence of how long obj
should survive, so I'm using reference counted pointers."
std::unique_ptr<Location> uniqueLocation = getLocation();
This says "I want to have controlled ownership of this object, which has never been in a complex ownership situation. If I could, I'd be a value (or maybe an optional), but some issues block me from being a value. So I'll be a unique pointer to a value."
The serialization does not need to take ownership of the unique_ptr. Which method should it call? The toJson using weak_ptr, or the toJson by reference?
A function that converts things to Json probably just needs the object being converted to be valid the length of the call.
toJson(const Location&)
is the one that means that.