elldur
elldur

Reputation: 2103

Can std::map move contained elements?

I would like to use pointers to resources stored in an std::map as handles to the resource but for this to work the std::map cannot move any of its contained elements due to insertion/deletion from the map. For example:

class Resource { ... }
std::map<std::string, Resource> resources;

resources["one"] = Resource( ... );
Resource *handle = &resources["one"];

resources["two"] = Resource( ... );
handle->doSomething(); // Is handle guaranteed to still point to the same resource?

I cannot find any documentation that states whether elements can be moved or not, std::map can contain an uncopyable and unmovable type however I want to be sure this isn't some intended adaption to such a type.

Upvotes: 2

Views: 360

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118435

From the C++ standard: a std::map is an associative container:

Class template map overview [map.overview]

A map is an associative container that supports unique keys...

The shown code uses the [] operator to modify the map, which is specified in terms of try_emplace():

26.4.4.3 map element access [map.access]

T& operator[](const key_type& x);

Effects: Equivalent to:

return try_emplace(x).first->second;

One of the requirements of all associative containers is that neither the insert nor the emplace members invalidate any existing iterators and references to the container, and erase invalidates only the affected elements:

26.2.6 Associative containers [associative.reqmts]

The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.

In other words, your handle remains valid, and is not affected by any other changes to the same map. Only actual removal from the map container invalidates any references or pointers, and only to the elements in the container that are affected by the erase.

Upvotes: 2

Related Questions