Comparator operator in weak_ptr C ++

I'm still new to new stl members. Can someone please indicate why this code gives a segmentation error?

#include<memory> #include<stdio.h> #include<map> #include<set> #include<string> using namespace std; struct StubClass { weak_ptr<string> b; int c; friend bool operator==(StubClass x,StubClass y); friend bool operator<(StubClass x,StubClass y); StubClass(weak_ptr<string> x):b(x){c=5;} }; bool operator==(StubClass d,StubClass c) { return db==cb;} bool operator<(StubClass d,StubClass c) { return db<cb; } int main() { shared_ptr<string> spPtr(new string("Hello")); weak_ptr<string> wpPtr(spPtr); StubClass hello(wpPtr); set<StubClass> helloSet; helloSet.insert(hello); if(helloSet.find(StubClass(wpPtr))!=helloSet.end()) printf("YAYA"); else puts("Bye"); } 

The error is in the line

if (helloSet.find (StubClass (wpPtr))! = helloSet.end ()) printf ("YAYA");

Other studies show that a problem occurs when the StubClass comparator function is called. I compile the program here

EDIT:

 bool operator==(StubClass d,StubClass c) { return dblock()==cblock();} bool operator<(StubClass d,StubClass c) { return dblock()<cblock(); } 

This resolved the issue. I have to read more. :( In any case, someone from the community will explain the reason why the first code gives SIGSEGV. In the end, I realized this, but still a good explanation will not hurt. :)

+4
source share
2 answers

If you want to compare the lines stored in the weak_ptr file, follow these steps:

 bool operator<(StubClass d, StubClass c) { std::shared_ptr<std::string> a = dblock(); std::shared_ptr<std::string> b = cblock(); if (!a && !b) return false; if (!a) return true; if (!b) return false; return *a < *b; } 

Run result

+4
source

The source code for segfaults, because you accidentally set up infinite recursion:

 bool operator<(StubClass d,StubClass c) { return db<cb; } 

No operator< for weak_ptr . However, you have an implicit conversion from weak_ptr to StubClass . And StubClass has operator< . Thus, this function invokes itself indefinitely: thus, segfault.

The currently accepted answer from inkooboo will also lead to undefined behavior, likely to lead to a crash. As weak_ptrs expires during the execution of your program (something more active than your test case), the order in which they change will change. When this happens between two weak_ptrs in set , set will become damaged, which can lead to failure. However, there is a way around this with owner_less , which was designed specifically for this use case:

 bool operator==(const StubClass& d, const StubClass& c) { return !owner_less<weak_ptr<string>>()(db, cb) && !owner_less<weak_ptr<string>>()(cb, db); } bool operator<(const StubClass& d, const StubClass& c) { return owner_less<weak_ptr<string>>()(db, cb); } 

Or, if you want, this can also be encoded using the owner_before member owner_before . Both are equivalent:

 bool operator==(const StubClass& d, const StubClass& c) { return !dbowner_before(cb) && !cbowner_before(db); } bool operator<(const StubClass& d, const StubClass& c) { return dbowner_before(cb); } 

Using these functions, even when one weak_ptr expires and the other does not, their order remains stable. And so you will have a clearly defined set .

+5
source

All Articles