Recently, I made a stupid mistake that made me think about the way C++ APIs handle dependencies and what we can do to prevent dangling references and lifetime issues. πŸ€”

It was a surprisingly fun topic to explore that led me to the discovery of a very cool static analysis tool. Can you guess which one? 😎

You can find out in the article I wrote about the topic here:
➀ https://medium.com/@nerudaj/type-safe-dependency-management-in-c-a293703f00ff

#cpp #StaticAnalysis #SoftwareEngineering

Type-safe dependency management in C++

Putting β€œlife” into lifetime issues in C++.

Medium
@jakub_neruda I would add one more option: Implicit sharing. It uses shared pointers internally, but behaves like a copied value to the outside. It will only do a deep copy if someone wants to change their copy. In your example, you would probably just pass ownership of AnimationStates, no copy, no crash.
Does make it somewhat harder to debug memory leaks.

@asperamanca I don't think what you describe is a dependency injection approach. If I recall correctly this is how Adobe Photoshop deals with memory snapshots for the purposes of undo/redo functionality.

So far with dependencies I always wanted that there is only a single instance of a given dependency, shared across one or many dependees.

@jakub_neruda Think of a logger that receives its output policy as an injected dependency.
Why should such a dependency not be passed by value and then "owned" by the logger?
And implicit sharing would just be an optimization strategy on top.

@asperamanca I think I get what you say.

So you have a dependency that acts as a value type, internally using a shared pointer and when you call a non-const method on it, the shared pointer is deep-copied. Sounds a lot like Prototype design pattern.

Theoretically, it might not violate SOLID, if the actual logic was implemented in a dedicated class and then wrapped with a Decorator that handles the shared pointer.

It would be a nightmare if such reasource needs to perform a deinitialization routine at a deterministic point in time, but it is likely only going to be used in cases where writes are possible, but not very common, for data storage purposes, rather that stuff like DB connectors.

Interesting for sure!

@jakub_neruda Determinism is not going to be a strength of this approach. It's a tradeoff similar to hash table vs. ordered map: You gain on average, but lose in the worst case.

Also, for SOLID the implicitly shared class should be wrapped such that it does not have logic itself. It looks like a true value-semantic object to the outside world, and apart from potential atomic contention when instance counts across threads need to be updated, it would behave just like a value type.