Why aren't weak pointers used more often?
A lot of people ask "Why are weak pointers useful?". To me, this is a no brainer, and I'm rather confused as to why they aren't used more often. They are the closest equivalent to the semantics we are most used to with raw pointers and I would tend to think they should be the default: a manager allocates a resource as a shared pointer, then this resource is always referred to via weak pointers.
However, most article I read on the Web about C++11 smart pointers focus on shared_ptr and unique_ptr, but don't spend as much time on weak_ptr. There are many blog posts or discussions on StackOverflow (example1, example2) that only mention weak pointers as a solution to the "ownership loop" problem, while IMHO this misses the point (such problem probably means that your design was flawed in the first place). There is this nice article by Herb Sutter explaining best practices and corresponding semantics on how to pass smart pointers or raw pointers/references as function argument, but it doesn't mention weak pointers at all! (only one comment mentions them).
The low usage of weak semantics seems also to be confirmed by a quick search through GitHub, though of course type aliases can be used, and usage may differ between open source code and proprietary code.
This seemingly low usage of weak pointers confuses me because in my personal experience, shared ownership is only useful in rare cases, while unique ownership combined with non-owning "references" 1 to these resources is the most typical use case, and better design whenever possible (RAII, etc.).
Do you know if it's just a perceived low usage and their actual usage and usefulness is just not well represented on the Web? If they are indeed not used much, is there a good and objective reason why, which I am failing to see? Am I wrong to think that non-owning pointers is a much more typical use case than shared pointers?
1 "reference" = generic terminology for raw pointer *, reference &, or smart pointer.
In most cases, the pointer semantics I am interested in is one of the following non-owning semantics:
A non-owning smart pointer that can tell whether the resource is expired or not. Optionally allows to "lock" for temporary ownership if the object may expire in a concurrent thread. This is to support the use case of "viewers/observers" that may outlive the observed object.
A non-owning smart pointer that supports direct dereference via "->", and aborts or throws an exception if the resource is expired. This is to support the use case when the resource is guaranteed to outlive the function call or the object referencing the resource, by design. I think this is by far the most typical use case.
Use case 1. is well covered by std::weak_ptr. In this case, the uniquely-owned resource is managed by a shared_ptr which is merely used as "unique ownership but with reference counting of weak pointers". As a side note, I know that the Observer pattern is probably a better alternative for this use case whenever feasible.
Use case 2., though, despite being what I believe is the most typical use case, is not well supported by the standard. In those cases, one should ideally use a & reference, but that only works if you don't need to store it and re-bind it. Otherwise, you're left to store a raw pointer, but if performance isn't an issue I'd rather store a smart pointer that throws if the object is expired, to catch programming errors.
So maybe the low usage of weak_ptr is explained by the fact that it only covers Case 1., which is not that typical, while it doesn't cover the more typical Case 2.? What do people usually do in case 2?
Who knows why. I don't believe that I should use weak pointers instead of raw pointers. They have additional checks so you should pay for it, it is not a C++ way, sometimes you need performance. If you think that weak pointers are useful so much, write some articles with useful usages of that approach.
Because if you are using shared_ptr then you need the reference counting aspect in the first place. std did not have a pure reference counting smart pointer, so shared_ptr or a custom smart pointer is used for that. No need to break cycles with weak_ptr if I do not construct cycles at all.
Opinion: The use case of non-owning smart pointers seems very useless. I am the programmer, I have full control over the life time of my objects, I am responsible that the object/resource is available if want to access this object. That's C++. And for debugging: Sorry the debugger will tell me if I access a "dead" object/memory/resource.