I'm using weak pointers as keys in a map. However, when I tried to compile, I got ugly messages which I interpreted to mean that I lacked a comparison operator for the std::weak_ptr, which, obviously, is required in a std::map, as it orders its elements according to key value.
Now, however, the weak_ptr class is a smart-pointer type class, and, as such, works with pointers to some managed data.
Is there a good reason why this class would NOT provide a base implementation of the operator< method ? I mean, comparing the pointer values seem pretty obvious to me, and, if it is required that it works in a different way, then one should be able to extend, or redefine, the method, to get the expected behavior instead, wouldn't it ?
Your insight would be much appreciated, here. Thanks in anticipation.
By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.
std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
To implement weak_ptr , the "counter" object stores two different counters: The "use count" is the number of shared_ptr instances pointing to the object. The "weak count" is the number of weak_ptr instances pointing to the object, plus one if the "use count" is still > 0.
Note that the control block used by std::weak_ptr and std::shared_ptr is thread-safe: different non-atomic std::weak_ptr objects can be accessed using mutable operations, such as operator= or reset , simultaneously by multiple threads, even when these instances are copies or otherwise share the same control block ...
std::owner_less
is the correct way to order smart pointers as keys in maps.
#include <map>
#include <memory>
#include <string>
struct Foo
{
};
using my_key = std::weak_ptr<Foo>;
using my_comp = std::owner_less<my_key>;
int main()
{
auto m = std::map<my_key, std::string, my_comp>();
auto p = std::make_shared<Foo>();
auto p1 = std::make_shared<Foo>();
m.emplace(p, "foo");
m.emplace(p1, "bar");
p.reset();
p1.reset();
}
UPDATE: There is a well-defined way to compare std::weak_ptr
, see @Richard's answer. I will leave my answer for historical archival purposes.
Implementing a good operator<
would require creating a shared_ptr
from the weak_ptr
and calling its operator<
. This is
shared_ptr
does not exist anymore.It would be difficult to get a well-defined and performant ordering of weak_ptr
s in general.
Note that you can always pass a custom comparator to your map object, which you can implement any way you want and keep local to only that object. But then it's up to you to figure out a good way to do this. Perhaps you could use the pointer to the control block to the connected shared_ptr
, but that is an implementation detail you cannot access. So I really see no meaningful way of doing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With