A reasonable option is to implement SomeImmutableObject in a way that supports this - internally, like a smart pointer to a logical state read with reference, and externally it can provide semantics of values. (This can make it harder to use from streaming code β you might want to read on copy-on-write (COW) and why it has become unpopular with the implementation of std::string .)
If you are stuck in an existing SomeImmutableObject implementation that you cannot change, and you cannot wrap it with a socket pointer with a list of links, then the choice will be limited.
It does not provide as pure use of the caller, but you can make manipulationIsNeccessary function available for calling, and then call the calling call with the code "new object with new data" in the second function:
SomeImmutableObject obj; const SomeImmutableObject& o = manipulationIsNecessary(obj) ? newObjectWithNewData(obj) : obj; ...use o...
Having a newObjectWithNewData separate function, you should get optimized return value (although it is always better to check with your compiler / settings).
source share