Spec-Zone.ru › C++

std::unordered_map<Key,T,Hash,KeyEqual,Allocator>::try_emplace

template< class... Args >
std::pair<iterator, bool> try_emplace( const Key& k, Args&&... args );
(1) (начиная с C++17)
template< class... Args >
std::pair<iterator, bool> try_emplace( Key&& k, Args&&... args );
(2) (начиная с C++17)
template< class K, class... Args >
std::pair<iterator, bool> try_emplace( K&& k, Args&&... args );
(3) (начиная с C++26)
template< class... Args >
iterator try_emplace( const_iterator hint, const Key& k, Args&&... args );
(4) (начиная с C++17)
template< class... Args >
iterator try_emplace( const_iterator hint, Key&& k, Args&&... args );
(5) (начиная с C++17)
template< class K, class... Args >
iterator try_emplace( const_iterator hint, K&& k, Args&&... args );
(6) (начиная с C++26)

Если в контейнере уже существует ключ, эквивалентный k, функция ничего не делает. В противном случае она вставляет в контейнер новый элемент с ключом k и значением, сконструированным с помощью args. В этом случае:

1) Ведёт себя как emplace, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(k),
           std::forward_as_tuple(std::forward<Args>(args)...))
2) Ведёт себя как emplace, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::move(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))
3) Ведёт себя как emplace, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))
4) Ведёт себя как emplace_hint, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(k),
           std::forward_as_tuple(std::forward<Args>(args)...))
5) Ведёт себя как emplace_hint, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::move(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))
6) Ведёт себя как emplace_hint, за исключением того, что элемент конструируется следующим образом:
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))
1-6) Если value_type не удовлетворяет требованиям EmplaceConstructible для unordered_map при использовании соответствующего выражения, поведение не определено.
3) Эта перегрузка участвует в разрешении перегрузки, только если выполнены все следующие условия:
  • std::is_convertible_v<K&&, const_iterator> и std::is_convertible_v<K&&, iterator> являются false.
  • Hash::is_transparent и KeyEqual::is_transparent являются корректными и каждое обозначает тип.
Если hash_function()(u.first) != hash_function()(k) || contains(u.first) является true, поведение не определено; здесь u — новый элемент, подлежащий вставке.
6) Эта перегрузка участвует в разрешении перегрузки, только если Hash::is_transparent и KeyEqual::is_transparent являются корректными и каждое обозначает тип.
Если hash_function()(u.first) != hash_function()(k) || contains(u.first) является true, поведение не определено; здесь u — новый элемент, подлежащий вставке.

Если после выполнения операции новое число элементов превышает старое значение max_load_factor() * bucket_count(), выполняется перехеширование.
Если происходит перехеширование (из-за вставки), все итераторы становятся недействительными. В противном случае (если перехеширования нет) итераторы остаются действительными.

Параметры

k - ключ, используемый как для поиска, так и для вставки, если он не найден
hint - итератор на позицию, перед которой будет вставлен новый элемент
args - аргументы, передаваемые конструктору элемента

Возвращаемое значение

1-3) То же, что и у emplace:
Пара, состоящая из итератора на вставленный элемент (или на элемент, помешавший вставке) и значения типа bool, равного true тогда и только тогда, когда вставка состоялась.
4-6) То же, что и у emplace_hint:
Итератор на вставленный элемент или на элемент, помешавший вставке.

Сложность

1-3) То же, что и у emplace:
В среднем амортизированная константная, в худшем случае линейная относительно размера контейнера.
4-6) То же, что и у emplace_hint:
В среднем амортизированная константная, в худшем случае линейная относительно размера контейнера.

Примечания

В отличие от insert или emplace, эти функции не перемещают аргументы-значения rvalue, если вставка не происходит. Это упрощает работу с отображениями, значения которых являются типами, допускающими только перемещение, например std::unordered_map<std::string,std::unique_ptr<foo>>. Кроме того, try_emplace обрабатывает ключ и аргументы для mapped_type по отдельности, в отличие от emplace, которому нужны аргументы для конструирования value_type (то есть std::pair).

Перегрузки (3,6) можно вызывать без конструирования объекта типа Key.

Макрос проверки поддержки возможностей Значение Стандарт Возможность
__cpp_lib_unordered_map_try_emplace 201411L (C++17) std::unordered_map::try_emplace,
std::unordered_map::insert_or_assign
__cpp_lib_associative_heterogeneous_insertion 202311L (C++26) Гетерогенные перегрузки для остальных функций-членов упорядоченных ассоциативных и неупорядоченных ассоциативных контейнеров. Перегрузки (3) и (6).

Пример

#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>

void print_node(const auto& node)
{
    std::cout << '[' << node.first << "] = " << node.second << '\n';
}

void print_result(auto const& pair)
{
    std::cout << (pair.second ? "inserted: " : "ignored:  ");
    print_node(*pair.first);
}

int main()
{
    using namespace std::literals;
    std::unordered_map<std::string, std::string> m;
    
    print_result(m.try_emplace("a", "a"s));
    print_result(m.try_emplace("b", "abcd"));
    print_result(m.try_emplace("c", 10, 'c'));
    print_result(m.try_emplace("c", "Won't be inserted"));
    
    for (const auto& p : m)
        print_node(p);
}

Возможный вывод:

inserted: [a] = a
inserted: [b] = abcd
inserted: [c] = cccccccccc
ignored:  [c] = cccccccccc
[a] = a
[b] = abcd
[c] = cccccccccc

См. также

emplace
конструирует элемент на месте
(открытая функция-член)
emplace_hint
конструирует элементы на месте, используя подсказку
(открытая функция-член)
insert
вставляет элементы или узлы(начиная с C++17)
(открытая функция-член)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/container/unordered_map/try_emplace

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API