Julian Gonggrijp
Jeremy Maitin-Shepard wrote:
From reading the documentation, it seems that owner_ptr/data_ptr are basically equivalent in functionality to std::unique_ptr, and weak_ptr is basically equivalent to a raw pointer/raw reference. (Referring to std::shared_ptr seems a bit misleading given that you don't address the problem of multiple ownership.)
Well I think there are two ways to see it. I was motivated by both of them:
std::unique_ptr + added safety + non-owning companion smart pointer type
(as you suggested) or
std::shared_ptr + std::weak_ptr - accidental cyclic ownership - runtime
overhead
I believe multiple ownership in std::shared_ptr is not a goal in itself, but just a way to ensure that objects stay live as long as they're needed. In my opinion I do actually address the problem of multiple ownership by taking it away.
Well, regardless of how you want to look at it, shared_ptr allows an arbitrary acyclic ownership/"ensure pointers stay alive" graph, while unique_ptr only allows an ownership forest.
As for the rich-typed weak_ptr, I think you should really think of it as a smart pointer, if only because it doesn't allow the user to deallocate the referenced object.
As I understand it, the goal of your library is not to add any functionality over std::unique_ptr, but to provide a little bit more compile-time safety at the cost of some additional typing (pun intended).
Well, yes. I do consider that additional functionality.
It does seem that wrappers around unique_ptr and shared_ptr that disable default construction and discourage storing a null pointer would be useful for many people. It would be much more useful if they explicitly interoperated with those types, though.
Fortunately it is trivial to add some interoperability with the std:: pointers. I'll add that to the roadmap.
I think the primary use case for your proposed weak_ptr (possibly renamed param_ptr or arg_ptr) would be as the declared type for function parameters.
That, and as a way to create arbitrarily complex linked data structures without introducing ownership problems. Note how this makes it more similar to std::weak_ptr than you may have thought initially.
I think that's overselling it a bit. It only supports tree structures (with possible back pointers using raw pointers/your proposed weak_ptr). Certainly in many cases a tree structure is all that is needed, but sometimes a more general ownership graph is needed.
I do like your suggestion for the name param_ptr or arg_ptr, though. I've been considering whether I should split weak_ptr in two types, one for function arguments and one for linked data structures. In that case your name suggestions would be excellent for the former while I could keep using the name weak_ptr for the latter. This would allow me to enforce that the proposed param_ptr is always non-null so that functions can rely on that.
Perhaps it would be useful to have both a possibly null and a non-null variant of param_ptr, where the non-null version has a runtime check.
When used only in that context, the implicit conversion from an owning pointer to a raw pointer is safe, because any values used as function arguments are guaranteed to live for the duration of the function.
For any other use, though, the implicit conversion is actually dangerous,
Could you elaborate on why implicit conversion to my weak_ptr would be dangerous?
Because the weak_ptr may outlive the underlying object, and the implicit conversion makes it silent. The only context in which this can't happen is if the weak_ptr is used only as a function parameter type. A dangling reference is quite possible if used as a return type or struct/class member, or even a local variable. It is best to limit implicit conversions to cases that are guaranteed to be safe, and can't possibly result in a dangling reference. If it is possibly unsafe, there should be some syntactic cue indicating as much.
Since type deduction is only rudimental in C++11, there actually is such a warning signal:
auto x = weak(foo);
Sure, in this case there is a syntactic cue, although it is perhaps not strong enough: "weak reference" typically means a non-owning reference that nonetheless knows when the reference becomes invalid, and therefore is still safe. This is the case for std::weak_ptr, as well as weak references in most other languages. For that reason I think it would be better to choose a different name.