Почему try_emplace не реализован для std :: multimap? - PullRequest
0 голосов
/ 14 декабря 2018

C ++ 17 представляет метод try_emplace для std::map, поэтому теперь я могу написать код, подобный приведенному ниже:

struct Test
{
    Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);

Но try_emplace для std::multimap<int, Test> нет, поэтому piecewise_construct все еще нужно.

Есть ли техническая причина для этого?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

есть ли техническая причина для этого?

Да.Цель try_emplace() - ничего не делать, если ключ уже существует на карте.Но для std::{unordered_,}multi{map,set} вы можете иметь несколько значений для каждой клавиши.В этом и заключается смысл этих контейнеров: иметь несколько значений для данного ключа.

В результате try_emplace() не может завершиться ошибкой для этих контейнеров - поэтому было бы сложно и бессмысленно предоставлять такиефункция.

Судя по комментариям, кажется, что мотивация - это только часть try_emplace(), которая облегчает использование значения.Для этого вы можете написать вспомогательную функцию:

template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
    return map.emplace(std::piecewise_construct,
                       std::forward_as_tuple(std::forward<Key>(key)),
                       std::forward_as_tuple(std::forward<Args>(args)...));
}

, которая позволит вам написать emplace_value(tmap, 10, 10, 10), даже для {unordered_,}multimap.

0 голосов
/ 14 декабря 2018

В этом нет необходимости, поскольку для случая с несколькими картами, поскольку нет уникального ключа, try_emplace никогда не завершится ошибкой.Рациональным добавлением try_emplace к карте был весь подверженный ошибкам код, необходимый для решения проблемы, когда ключ уже существует, см. Предложение n4279 ( выделение мое ):

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

Обоснование и обоснование нового интерфейса приведены в N3873.Первоначальной реакцией на N3873 в Иссакве было то, что существующие интерфейсы карты должны быть исправлены, а не добавлены новые интерфейсы.Мы исследовали эту идею в N4006 в Рапперсвиле и решили, что первоначальное предложение было предпочтительным (с некоторыми изменениями имени).Эта статья только обобщает предлагаемое расширение без повторения первоначального обсуждения.Мы приведем здесь только фрагмент кода мотивации:

std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr);    // ??? (may or may not fire)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...