2

I've got an map shared_ptrs

std::unordered_map<uint64_t, std::shared_ptr<Target>> map;

Is there a way to make them weak_ptrs at some point or do I have to make something like

std::unordered_map<uint64_t, 
    std::pair<std::shared_ptr<Target>, 
    std::weak_ptr<Target>>> map;

and swap them?

Thanks in advance

Christoph Diegelmann
  • 2,004
  • 15
  • 26
  • You can always assign from `shared_ptr` to `weak_ptr`, they are complimentary parts of the same design. Is that what you meant? – Deduplicator Nov 19 '14 at 23:03
  • @Deduplicator I want to remove the reference shared_ptr puts on it so it might get deleted if there's no other shared_ptr somewhere. Basically I want to change the shared_ptr to a weak_ptr at runtime. – Christoph Diegelmann Nov 19 '14 at 23:11
  • There's no way to make a `shared_ptr` act like a `weak_ptr` or the other way around. What would be the point of such an amorphous mass? Though what you *can* do is making a non-owning non-empty `shared_ptr`. – Deduplicator Nov 19 '14 at 23:16
  • 2
    @Christoph: Then you have to use a `std::pair` (or a custom `struct` that holds both types) and swap them when needed, eg: `auto &value = map[12345]; value.second = value.first; value.first.reset();` This assumes that there is another `shared_ptr` somewhere keeping the object alive, otherwise there is no point in assigning an object to a `weak_ptr` just to free the object when the associated `shared_ptr` is cleared. – Remy Lebeau Nov 19 '14 at 23:16
  • How about using `boost::variant` instead ? – v.oddou Nov 20 '14 at 01:09
  • I'm having trouble grasping the point behind this question. Does the `map` participate in ownership or not? You appear to be mixing two concepts here... – Mooing Duck Nov 24 '14 at 21:36

2 Answers2

2

As people already stated in the comments, you can not do that. A shared_ptr always owns a reference, while a weak_ptr never does. The API of the standard library is explicitly designed in a way that the type tells you whether you currently own a reference or not (and the only thing you should do to access pointees of weak_ptr objects is lock() them, and check the resulting shared_ptr for non-null-ness, so you can (even in a multi-threaded environment) be sure, that you own a reference for yourself while working with the object.

What you could possibly do is have a map of weak_ptr all along, and store a shared_ptr elsewhere as long as you want to keep the object alive. Depending on the design or purpose, the place for the shared_ptr might even be a member variable of the object.

If you use a map of pairs, I would not swap() the pair members, but start with a pair of a shared and a weak ptr referring to the same managed object, and just reset() the shared ptr if it is decided to drop the strong reference, not touching the weak_ptr at that point.

Michael Karcher
  • 3,803
  • 1
  • 14
  • 25
0

You can always use the weak_ptr or shared_ptr itself as the key in the map. So indeed:

std::map<std::weak_ptr<void>, std::string> information_map;

Would be able to associate strings with any kind of weak ptr, regardless of type. This is because std::less<void*> defines a weak total ordering over all possible pointer values according to the standard.

See also

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633