In my main application, I have an std::set<std::shared_ptr<Object>>. I also want to create a secondary set of std::set<std::weak_ptr<Object>> because I don't want to increment the reference count but I also want to avoid calling bad memory locations by using a lock. Unfortunately, I cannot define a std::set with std::weak_ptrs inside. Having done so, the compiler complains with some errors in the insert and remove methods.
#include <memory>
#include <set>
#include <vector>
class Test{
private:
int x ;
public:
Test(int x){
this->x = x;
}
int getx(){
return x;
}
};
int main(){
std::shared_ptr<Test> t = std::make_shared<Test>(10);
std::weak_ptr<Test> ref = std::weak_ptr<Test>(t);
std::set<std::weak_ptr<Test>> weakrefs;
weakrefs.insert(ref);//compiler error
weakrefs.erase(ref);//compiler error
}
But when I use std::vector<std::weak_ptr<Test>>, I'm allowed to push back and pop back. But I would like similar functionality to std::set.
To have a set of weak_ptrs, you need std::owner_less<>, a special comparison operator:
std::set<std::weak_ptr<Test>, std::owner_less<std::weak_ptr<Test>>> weakrefs;
This comparison operator uses the administrative region to look up the smart pointers, not the pointers to the object that they point to. This is necessary because the object can be deleted while the smart pointers are still in the std::set.
You should actually also use std::owner_less for a set of shared_ptrs.
But when I use std::vector< std::weak_ptr< Test>>, I'm allowed to push back and pop back. But I would like similar functionality to std::set.
std::set is an ordered container. It means that when you insert something, the data structure needs some comparisons to find its right place (inside the internal tree). Because of this, as @j6t has mentioned, you need to introduce a compare operator while defining the set. This is not the case for the std::vector because for the std::vector you keep the elements one after another, without any comparisons.
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