Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
473 views
in Technique[技术] by (71.8m points)

c++ - How to make a c++11 std::unordered_set of std::weak_ptr

I have a set like this: set<weak_ptr<Node>, owner_less<weak_ptr<Node> > > setName;

It works fine. But I would like to change it to an unordered set. However, I get about six pages of errors when I do that. Any ideas how to do that?

After looking through all the pages of error messages I found to lines that might help.

/usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
/usr/include/c++/4.7/bits/stl_function.h: In instantiation of ‘bool std::equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::weak_ptr<Node>]’:
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The short and unfortunate answer is that while shared_ptr<> can be used safely as a key in an unordered set or map, weak_ptr<> cannot and must not. No amount of trickery can make it safe.

This is because weak_ptr's interface does not expose access to the shared control object, which is the basis of comparing by owner_before() when used in an ordered set or map.

While it may seem reasonable to lock the pointer and then hash the shared_ptr, it is not. If the last shared_ptr goes out of scope the hash value will change, which will result in undefined behaviour next time your set or map is iterated. This will most likely go un-noticed until your code is in production in front of customers where you get unexpected and inexplicable loss of functionality occasionally, but your unit tests will still pass flawlessly, giving you the false idea that your test coverage is good, your code is reliable and it is the users, hardware or network that's to blame.

So, in summary, if you're going to use weak_ptr's to build your non-owning object caches (for which they are excellent) you need use a std::set<weak_ptr> and suffer the miniscule performance hit (although in reality this will be dwarfed by the performance loss caused by the mutex that protects the set).

If you really want to use a weak_ptr as an unordered key you will have to write your own (hint: use the address of the shared control block as the basis for the hash function).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...