Подтвердить что ты не робот

Std:: map emplace без копирования значения

Тип С++ 11 std::map<K,V> имеет функцию emplace, как и многие другие контейнеры.

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

std::string val {"hello"};

m.emplace(1, val);

Этот код работает так, как рекламируется, размещая std::pair<K,V> напрямую, однако он приводит к копированию key и val.

Можно ли также ввести тип значения непосредственно в карту? Можем ли мы лучше, чем перемещать аргументы в вызове emplace?


Вот более подробный пример:

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
4b9b3361

Ответ 1

Аргументы, передаваемые в map::emplace, передаются конструктору map::value_type, который равен pair<const Key, Value>. Таким образом, вы можете использовать конструктор кусочной конструкции std::pair, чтобы избежать промежуточных копий и перемещений.

std::map<int, Foo> m;

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

Живая демонстрация

Ответ 2

В С++ 17 это легче сделать с помощью метода try_emplace.

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

Это дополнение к стандартной библиотеке было описано в документе N4279 и должно быть уже поддержано в Visual Studio 2015, GCC 6.1 и LLVM 3.7 (библиотека libС++).