How to safely "pop-front" from std::map without extra copy?

Viewed 359

I have a std::map object.

std::map<std::string, std::string> m;

m.insert({ "abcd", "foo" });
m.insert({ "1234", "bar" });

and I want to get and remove the first element, like:

auto iter = m.begin();
auto [key, value] = std::move(*iter);
m.erase(iter);
do_something_with(key, value);

Is this considered safe? (Moving from the iterator should make the key an empty string, which makes the m an invalid map.)

3 Answers

You can use std::map::extract like this:

auto nh = m.extract(m.begin());

and then use the key and value like this:

do_something(nh.key(), nh.mapped());

This has the needed property that no extra copies are made.

Is this considered safe?

On the condition that the map isn't empty, yes.

However, note that the key will be a deep copy; not moved one. This is because the the key of the map element is const.

How to safely “pop-front” from std::map without extra copy?

It is possible to move from the key too, if you use the extract member function:

auto handle = m.extract(m.begin());
// if you need separate objects:
auto key = std::move(handle.key());
auto mapped = std::move(handle.mapped());

Use std map extract. Using the resulting node handle, move the key/value to your key/value variables.

Prior to std map extract, this isn't fully possible. std map extract was added to let you do this, and similar operations like splicing maps.

Related