web-dev-qa-db-fra.com

std :: map emplace sans copier la valeur

Le C++ 11 std::map<K,V> type a une fonction emplace, comme le font de nombreux autres conteneurs.

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

std::string val {"hello"};

m.emplace(1, val);

Ce code fonctionne comme annoncé, mettant en place le std::pair<K,V> directement, mais il en résulte une copie de key et val en cours.

Est-il également possible de placer le type de valeur directement dans la carte? Pouvons-nous faire mieux que de déplacer les arguments de l'appel vers emplace?


Voici un exemple plus complet:

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
47
Drew Noakes

Les arguments que vous passez à map::emplace être transmis au constructeur de map::value_type, lequel est pair<const Key, Value>. Vous pouvez donc utiliser le constructeur de construction par morceaux of std::pair pour éviter les copies et déplacements intermédiaires.

std::map<int, Foo> m;

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

Démo en direct

66
Praetorian

En C++ 17, cela peut être plus facilement réalisé avec le try_emplace méthode.

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

Cet ajout à la bibliothèque standard a été couvert dans papier N4279 et devrait déjà être pris en charge dans Visual Studio 2015 , GCC 6.1 et LLVM 3.7 (la bibliothèque libc ++).

16
James Holderness