Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::unordered_map::extract references/pointers invalidation

For the new C++17 std::unordered_map::extract function the documentation says:

Extracting a node invalidates only the iterators to the extracted element, and preserves the relative order of the elements that are not erased. Pointers and references to the extracted element remain valid, but cannot be used while element is owned by a node handle: they become usable if the element is inserted into a container.

Naturally, extract invalidates iterator of the extracted (which is a thing of the container, from which the element was removed). But the documentation is funky about references and pointers - it says these remain valid but cannot be used until re-inserted into (possibly another) container - case in which they will have retained their values (?).

Question: My use case is to examine an element after extracting, i.e. do an erase-examine-discardForGood operation with only one hash lookup. The extract function seemed perfectly suited for this however documentation suggests I can't use node_type to examine the element. Is my understanding correct?

like image 394
haelix Avatar asked Oct 10 '18 11:10

haelix


2 Answers

Yes, that is what the text says.

At first glance that seems like a fairly arbitrary limitation, though I'm sure there's some good, if arcane, reason for it.

That being said, the handle itself has member functions value()/key()/mapped() that may be of value (!) to you.

Node handle is a move-only type that owns and provides access to the element (the value_type) stored in the node, and provides non-const access to the key part of the element (the key_type) and the mapped part of the element (the mapped_type). (ref)

like image 178
Lightness Races in Orbit Avatar answered Nov 15 '22 13:11

Lightness Races in Orbit


You can think that extract (and corresponding insert) "magically" changes the type of the affected map element: when the element is owned by the map, it has type std::pair<const key_type, mapped_type>, but when the element is owned by the node handle, it has type std::pair<key_type, mapped_type> (so you can change the value of the key).

Thus, if you acquire a reference/pointer to an element when the element is owned by the map, then you can't use that reference/pointer after the element is extracted and before it is re-inserted, or you will violate the strict aliasing rule.

However, it is totally fine to use a reference/pointer acquired after the extraction.

like image 45
cpplearner Avatar answered Nov 15 '22 12:11

cpplearner