1
  • shared_ptr/weak_ptr allow to keep a weak reference on an object but I can't prevent someone who receives a weak to convert it and store it as a shared. So I lose the control of the object lifetime .

  • unique_ptr is ok to control the lifetime of the object, but does not have a weak reference mechanism.

I couldn't find a standard way to have the benefits of lifetime control and weak reference at the same time. I can't believe that I'm the only one to encounter this problem.

Is there anything in the standard or in boost that would allow this behavior? Or is there a pattern allowing this without rewriting a complete smart_ptr class?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Nicolas
  • 17
  • 2
  • Related http://stackoverflow.com/questions/17536731/shared-ptr-is-to-weak-ptr-as-unique-ptr-is-to-what. There is also `std::experimental::observer_ptr` but it won't become null when the unique_ptr is deleted. – kennytm Apr 03 '17 at 17:20
  • 4
    That is kind of the point of `weak_ptr`. When the client uses the referenced object, it converts it to shared for the duration of use so that it isn't deleted. The client owning the `weak_ptr` needs some way to assume partial ownership of the lifetime of the object before using it. – lcs Apr 03 '17 at 18:03
  • There is no need for weak_ptr-like mechanism in case of unique_ptr because the lifetime of the object stored in it must exceed the lifetime of all the references to it and all the code referencing this object can use these references without any additional checks. If some part of the code actually may expect that object does not exist then it would be better to give it access to object though something like [boost::optional_reference](http://www.boost.org/doc/libs/1_63_0/libs/optional/doc/html/boost_optional/tutorial/optional_references.html). – dodo951 Apr 04 '17 at 08:49

3 Answers3

1

If you want to control the lifetime, it's not a weak pointer.

Weak pointers can be upgraded to sharing pointers. So, if you don't want to share ownership, you need to pass references/raw pointers.

You can make your own kind of limited-access observer_ptr by wrapping a weak_ptr and not exposing the whole interface. However, this would be hard to get safe in a multi-threaded setting (arguably the only setting where shared_ptr thrives).

sehe
  • 374,641
  • 47
  • 450
  • 633
0

You are asking for the impossible.

An object cannot be safely accessed by code that cannot extend the lifetime of the object to cover the time during which it is accessing the object.

To permit external code to access an object, you must also permit that code to extend the object's lifetime to cover the time in which it is accessing the object.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
-1

Ok, there is no standard way to do that.

The solution is to add unique_ids to all the objects, and everybody who needs a weak reference store an id.

Then we have a Manager that keeps a map of unique_ptr of those objects, with a public method findById(id).

This way, the memory allocation is fully controlled by the manager, and anybody can keep weak references on it.

Nicolas
  • 17
  • 2
  • 1
    This won't work. You call `findById(id)` and you get back an object that may or may not disappear at any time because something else controls its lifetime?! How can you use that? This is precisely equivalent to, and as useless as, a weak pointer that cannot be promoted to a strong pointer. – David Schwartz Jul 05 '17 at 18:52
  • You're right, findById(id) returns what I called a TransientPtr, a pointer that must be tested before use, and can never be copied or stored. So I use this object for a very short scope, and as long as I don't destroy it in the scope where I use it, there is no problem. The custom weak_ptr has the same problem I think, if I cannot promote it to a strong pointer, there is no way of using it while being sure that the shared_ptr is still alive. And the advantage over a custom weak_ptr is that in my case the objects can be destroyed and recreated later (from a server), and my id is still valid. – Nicolas Jul 06 '17 at 19:47
  • So then why bother with the IDs at all? Why not just wrap a `weak_ptr` in a class that can only turn it into a `TransientPtr`? The wrapped `weak_ptr` serves the purpose of the ID and the function to turn it into a `TransientPtr` serves the purpose `findById` serves. The ID serves no purpose. – David Schwartz Jul 06 '17 at 20:56
  • Yeah, you're right. In my special case, the IDs are persistent on a server, it allows me to keep a weak_ptr without having the resource, and once the server tells me to create the resource, the ptr will work magically. – Nicolas Aug 02 '17 at 15:41