Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::set of std::weak_ptr insert and remove

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.

like image 944
Irelia Avatar asked Jun 26 '26 06:06

Irelia


2 Answers

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.

like image 197
j6t Avatar answered Jun 30 '26 18:06

j6t


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.

like image 45
Gupta Avatar answered Jun 30 '26 17:06

Gupta