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 .