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
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"));
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 ++).