Разместить непосредственно в std::map пары

Почему этот код не скомпилируется?

std::map<int,std::pair<int,int>> m;
m.emplace(1,1,1);

Предполагая, что мы можем редактировать код std::map::emplaceМожно ли изменить его, чтобы сделать предыдущий код действительным?

1 ответ

Решение

Это недействительно по той же причине, что и недействительно:

std::pair<const int, std::pair<int, int>> p{1, 1, 1};

Потому что выше, по сути, то, что карта emplace сводится к.

Чтобы заставить его работать, вы можете использовать piecewise_construct конструкторstd::pair, который был введен именно для этой цели:

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

Это будет иметь желаемый эффект, не вызывая ненужных конструкторов (даже если они, скорее всего, будут исключены).


Чтобы ответить на ваш гипотетический вопрос о том, как заставить работать "прямой" синтаксис: в общем случае для произвольного map<K, V>нет Вообразите это:

struct Proof {
  Proof(int);
  Proof(int, int);
};

std::map<Proof, Proof> m;
m.emplace(1, 1, 1);  // Now what?

Вы, конечно, могли бы сделать это для ограниченного случая map<T, std::pair<T, T>>, Вероятно, это было бы выполнимо для чего-то более общего, с помощью огромного количества продвинутых шаблонных приемов (например, SFINAE влево, вправо и в центре, а затем некоторые). Стоит ли это того, зависит от деталей вашей ситуации.

Другие вопросы по тегам