I want a container to store unique std::weak_ptrs. std:set requires operator<, presumably because it stores the items in a tree. My worry is if I implement operator< in the obvious way (destroyed ptr = null ptr < valid ptr) then this result can mutate after items are added to the container, which may break it.
Is this in fact safe? If not, any suggestions for a container?
Thanks
2 个答案:
答案 0 :(得分:1)
user3159253 is correct. Found the full answer here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1590.html
weak_ptr::operator<
Since a weak_ptr can expire at any time, it is not possible to order weak pointers based on their value. Accessing the value of a deleted pointer invokes undefined behavior, and reinterpret_cast tricks are no good, either, as the same pointer value can be reused by the next new expression. Using p.lock().get() for ordering is similarly flawed, as this implies that the value of p < q may change when p or q expires. If p and q are members of a std::set, this will break its invariant.
The only practical alternative is to order weak pointers by the address of their control block, as the current specification effectively demands.
答案 1 :(得分:0)
You cannot use weak_ptrs as keys unless you use a owner based comparison (against the value based one, that is not even defined for weak_ptr, for which trying to use the operator< results in an error).
The problem is that they can expire and the ordering of your containers (a set as well as a map) wouldn't be consistent anymore.
As correctly pointed out by Kerrek SB (forgive me, but the mobile app does not let me to correctly link users) and as you can read from my link in the comments, you can rely on std::owner_less starting from C++11.
A valid approach is to use a set defined as it follows:
std::set<std::weak_ptr<C>, std::owner_less<std::weak_ptr<C>>>
Note that owner_less can be less verbose, for it deduces the type automatically.
Keep in mind that this approach does not keep you from invoking the expired method while visiting the set, because it can still contains expired objects even if consistently ordered.
Also, note that there is a huge difference between an expired weak_ptr and an empty one, so the owner based comparison could be not so intuitively, even if expiration shouldn't affect it once used the approach above mentioned.
Here some links.