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

Внедрение std:: pair

Есть ли способ размещения a std::pair?

std::unordered_map<int, std::pair<std::string, std::string>> my_map;
my_map.emplace(1, "foo", "bar"); // Error

Конечно, возможно вставка:

my_map[2] = std::make_pair("bar", "foo");

Но разве это не требует ненужного копирования/перемещения?

4b9b3361

Ответ 1

Есть ли способ размещения std:: pair?

Аргументы должны быть подходящими для конструктора pair<int, pair<string,string>>, отображения value_type:

my_map.emplace(1, std::make_pair("foo", "bar"));

Но разве это не требует ненужного копирования/перемещения?

Нет; make_pair создает пару указателей на строковые литералы, которые затем используются для инициализации (в случае emplace) или назначаются (в случае []) строки, содержащиеся в карте.

Ответ 2

В этом случае нет смысла размещать части "value-type" std::pair, так как std::string может быть эффективно преобразован из C-строки и может быть эффективно перемещен в карту. Простой m.emplace( 3, std::make_pair( "bob", "alice" ) ), и вы достигаете 99% оптимальной эффективности.

Однако, если у вас есть std::map, который сопоставляется с типом, который не может быть эффективно сконструирован таким образом, С++ 11 предоставляет std::piecewise_construct для std::pair как emplace d.

struct A { }; // nothing
struct C { C(C&&)=delete; }; // no copy/move
struct B { B()=delete; B(B&&)=delete; B(C&&, C&&) {}; }; // no copy/move, only annoying ctor

std::map< int, std::pair<A,B> > test;
// test.emplace( 0, std::make_pair( A{}, B{} ); // does not compile
// test.emplace( 0, std::make_pair( A{}, B{C{},C{}} ); // does not compile
test.emplace( std::piecewise_construct,
  std::make_tuple(0),
  std::forward_as_tuple(
    std::piecewise_construct,
    std::forward_as_tuple(A{}),
    std::forward_as_tuple( C{}, C{} )
  )
); // compiles!

живой пример

Это крайний угловой случай, поскольку объекты с более эффективным перемещением гораздо более распространены.

Ответ 3

Да, есть:

my_map.emplace(1, std::make_pair("foo", "bar"));