std:: map emplace bez kopiowania wartości

Typ C++11 std::map<K,V> posiada funkcję emplace, podobnie jak wiele innych kontenerów.

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

std::string val {"hello"};

m.emplace(1, val);

Ten kod działa zgodnie z reklamą, umieszczając std::pair<K,V> bezpośrednio, jednak skutkuje to wykonaniem kopii key i val.

Czy możliwe jest umieszczenie typu wartości bezpośrednio na mapie? Czy możemy zrobić coś lepszego niż przeniesienie argumentów w wywołaniu do emplace?


Oto bardziej dokładny przykład:

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
Author: Drew Noakes, 2015-01-15

2 answers

Argumenty, które przekazujesz map::emplace są przekazywane do konstruktora map::value_type, czyli pair<const Key, Value>. Możesz więc użyć piecewise Construction constructor z std::pair, Aby uniknąć pośrednich kopii i ruchów.

std::map<int, Foo> m;

m.emplace(std::piecewise_construct,
          std::forward_as_tuple(1),
          std::forward_as_tuple(2.3, "hello"));

Live demo

 59
Author: Praetorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-15 09:46:41

W C++17 można to łatwiej osiągnąć za pomocą try_emplace metoda.

map<int,Foo> m;
m.try_emplace(1, 2.3, "hello");

Ten dodatek do biblioteki standardowej został napisany w paper N4279 i powinien być już obsługiwany w Visual Studio 2015, GCC 6.1 i LLVM 3.7 (biblioteka libc++).

 13
Author: James Holderness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 18:57:45