Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any reason to use std::map::emplace() instead of try_emplace() in C++1z?

Tags:

c++

c++17

In C++17, std::map and std::unordered_map got a new member-function template: try_emplace(). This new addition, proposed in n4279, behaves similarly to emplace(), but has the following advantages:

  • try_emplace() does not move from rvalue arguments if the insertion does not happen. This is useful when manipulating maps whose values are move-only types, such as std::unique_ptr.
  • try_emplace() treats the key and the arguments to the mapped_type separately, which makes it somewhat more intuitive than generic mutators that are expressed in terms of value_type (which is std::pair).

Given the above advantages, would you ever use emplace() from C++11 instead of try_emplace() from C++1z when writing C++1z-only code?

like image 264
s3rvac Avatar asked Sep 05 '17 04:09

s3rvac


People also ask

When to use try_ emplace?

try_emplace() does not move from rvalue arguments if the insertion does not happen. This is useful when manipulating maps whose values are move-only types, such as std::unique_ptr .

What is MAP emplace?

The map::emplace() is a built-in function in C++ STL which inserts the key and its element in the map container. It effectively increases the container size by one.

What is std :: map used for?

If you mean std::map , it stores pairs of values. In each pair, the first value is called the key, and can be used to quickly look up the associated other value.


2 Answers

try_emplace can indeed replace most uses of emplace, but if you have an unusual use case of a map with a non-copyable and immovable key type, try_emplace will not work because it copies or moves the key. In that case, you must use emplace with std::pair's piecewise construction constructor to avoid copies and moves.

Even if your key type is copyable and/or moveable, piecewise construction is the only way to avoid copy or move constructing the key, so there might be cases when you prefer that over try_emplace.

like image 141
Praetorian Avatar answered Oct 06 '22 15:10

Praetorian


try_emplace also doesn't support heterogenous lookup - it can't, because it takes the key.

Suppose we have a std::map<std::string, int, std::less<>> counts; and a std::string_view sv. I want to do the equivalent of ++counts[std::string(sv)];, but I don't want to create a temporary std::string, which is just wasteful, especially if the string is already present in the map. try_emplace can't help you there. Instead you'd do something like

if(auto lb = counts.lower_bound(sv); lb != counts.end() && lb->first == sv) {     ++lb->second; } else {     counts.emplace_hint(lb, sv, 1); } 
like image 29
T.C. Avatar answered Oct 06 '22 15:10

T.C.