The C++11 std::map<K,V>
type has an emplace
function, as do many other containers.
std::map<int,std::string> m; std::string val {"hello"}; m.emplace(1, val);
This code works as advertised, emplacing the std::pair<K,V>
directly, however it results in a copy of key
and val
taking place.
Is it possible to emplace the value type directly into the map as well? Can we do better than moving the arguments in the call to emplace
?
Here's a more thorough example:
struct Foo { Foo(double d, string s) {} Foo(const Foo&) = delete; Foo(Foo&&) = delete; } map<int,Foo> m; m.emplace(1, 2.3, string("hello")); // invalid
Yes -- when you insert an item into an std::map, you pass it by value, so what it contains is a copy of what you passed.
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.
Yes, a std::map<K,V> is ordered based on the key, K , using std::less<K> to compare objects, by default.
The arguments you pass to map::emplace
get forwarded to the constructor of map::value_type
, which is pair<const Key, Value>
. So you can use the piecewise construction constructor of std::pair
to avoid intermediate copies and moves.
std::map<int, Foo> m; m.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple(2.3, "hello"));
Live demo
In C++17 this can more easily be achieved with the try_emplace
method.
map<int,Foo> m; m.try_emplace(1, 2.3, "hello");
This addition to the standard library was covered in paper N4279 and should already be supported in Visual Studio 2015, GCC 6.1 and LLVM 3.7 (the libc++ library).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With