nonstandard API: Discards the internally held container and replaces it with the one passed. Erases non-unique elements.
| 953 | // nonstandard API: |
| 954 | // Discards the internally held container and replaces it with the one passed. Erases non-unique elements. |
| 955 | auto replace(value_container_type &&container) { |
| 956 | if (container.size() > max_size()) { |
| 957 | throw std::out_of_range("ankerl::unordered_dense::map::replace(): too many elements"); |
| 958 | } |
| 959 | |
| 960 | auto shifts = calc_shifts_for_size(container.size()); |
| 961 | if (0 == m_num_buckets || shifts < m_shifts || container.get_allocator() != m_values.get_allocator()) { |
| 962 | m_shifts = shifts; |
| 963 | deallocate_buckets(); |
| 964 | allocate_buckets_from_shift(); |
| 965 | } |
| 966 | clear_buckets(); |
| 967 | |
| 968 | m_values = std::move(container); |
| 969 | |
| 970 | // can't use clear_and_fill_buckets_from_values() because container elements might not be unique |
| 971 | auto value_idx = value_idx_type{}; |
| 972 | |
| 973 | // loop until we reach the end of the container. duplicated entries will be replaced with back(). |
| 974 | while (value_idx != static_cast<value_idx_type>(m_values.size())) { |
| 975 | auto const &key = get_key(m_values[value_idx]); |
| 976 | |
| 977 | auto hash = mixed_hash(key); |
| 978 | auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash); |
| 979 | auto bucket_idx = bucket_idx_from_hash(hash); |
| 980 | |
| 981 | bool key_found = false; |
| 982 | while (true) { |
| 983 | auto const &bucket = at(m_buckets, bucket_idx); |
| 984 | if (dist_and_fingerprint > bucket.m_dist_and_fingerprint) { |
| 985 | break; |
| 986 | } |
| 987 | if (dist_and_fingerprint == bucket.m_dist_and_fingerprint && m_equal(key, m_values[bucket.m_value_idx].first)) { |
| 988 | key_found = true; |
| 989 | break; |
| 990 | } |
| 991 | dist_and_fingerprint = dist_inc(dist_and_fingerprint); |
| 992 | bucket_idx = next(bucket_idx); |
| 993 | } |
| 994 | |
| 995 | if (key_found) { |
| 996 | if (value_idx != static_cast<value_idx_type>(m_values.size() - 1)) { |
| 997 | m_values[value_idx] = std::move(m_values.back()); |
| 998 | } |
| 999 | m_values.pop_back(); |
| 1000 | } else { |
| 1001 | place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx); |
| 1002 | ++value_idx; |
| 1003 | } |
| 1004 | } |
| 1005 | } |
| 1006 | |
| 1007 | template <class M, typename Q = T, std::enable_if_t<is_map_v<Q>, bool> = true> |
| 1008 | auto insert_or_assign(Key const &key, M &&mapped) -> std::pair<iterator, bool> { |
no test coverage detected