Поскольку это для заметок, ни одна из них не является хорошей идеей.
Для получения уникальных ключей контейнеров, emplace
и insert
(кроме случаев, когда insert
передается value_type
- то есть, pair<const Key, Value>
) может безусловно выделить память и построить пару ключ-значение, а затем уничтожить пару и освободить память, если ключ уже существует; это очевидно дорого, если ваш ключ уже существует. (Им нужно сделать это, потому что в общем случае вам нужно построить ключ, прежде чем вы сможете проверить, существует ли он, и ключ должен быть сконструирован непосредственно в конечном месте.)
Тем не менее, вы также хотите избежать ненужного копирования ключа, поэтому вставка value_type
не подходит - Key
в нем есть константа и поэтому не может быть перемещен.
Наконец, вы также захотите избежать дополнительных поисков. Не так дорого, как выделение памяти, но все же полезно его сохранить.
Таким образом, нам нужно сначала найти ключ и только позвонить emplace
, если ключ отсутствует на карте. В C++ 11 допускается только однородный поиск, поэтому вам нужно сделать одну копию args...
.
map<tuple<Args...>, int> cache;
auto key = std::make_tuple(args...);
auto it = cache.lower_bound(key); // *it is the first element whose key is
// not less than 'key'
if(it != cache.end() && it->first == key) {
// key already in the map, do what you have to do
}
else {
// add new entry, using 'it' as hint and moving 'key' into container.
cache.emplace_hint(it, std::move(key), /* value */);
}
В C++ 14, вы можете сделать гетерогенный поиск, что означает, что вы можете сохранить копию для того, когда вы на самом деле нужны:
map<tuple<Args...>, int, less<>> cache; // "diamond functor" enables hetergeneous lookup
auto key = std::tie(args...); // this is a tuple<const Args&...> - a tuple of references!
auto it = cache.lower_bound(key); // *it is the first element whose key is
// not less than 'key'
if(it != cache.end() && it->first == key) {
// key already in the map, do what you have to do
}
else {
// add new entry, copying args...
cache.emplace_hint(it, key, /* value */);
}
BTW кортеже с большим объектом, как ключ карты не оптимальный вариант IMO –
Можете ли вы предложить его тогда? :) – justHelloWorld
Как я могу предложить, так как я не знаю, в чем проблема. –