nonstandard API: Discards the internally held container and replaces it with the one passed. Erases non-unique elements.
| 1417 | // nonstandard API: |
| 1418 | // Discards the internally held container and replaces it with the one passed. Erases non-unique elements. |
| 1419 | auto replace(value_container_type&& container) { |
| 1420 | if (ANKERL_UNORDERED_DENSE_UNLIKELY(container.size() > max_size())) { |
| 1421 | on_error_too_many_elements(); |
| 1422 | } |
| 1423 | auto shifts = calc_shifts_for_size(container.size()); |
| 1424 | if (0 == m_num_buckets || shifts < m_shifts || container.get_allocator() != m_values.get_allocator()) { |
| 1425 | m_shifts = shifts; |
| 1426 | deallocate_buckets(); |
| 1427 | allocate_buckets_from_shift(); |
| 1428 | } |
| 1429 | clear_buckets(); |
| 1430 | |
| 1431 | m_values = std::move(container); |
| 1432 | |
| 1433 | // can't use clear_and_fill_buckets_from_values() because container elements might not be unique |
| 1434 | auto value_idx = value_idx_type{}; |
| 1435 | |
| 1436 | // loop until we reach the end of the container. duplicated entries will be replaced with back(). |
| 1437 | while (value_idx != static_cast<value_idx_type>(m_values.size())) { |
| 1438 | auto const& key = get_key(m_values[value_idx]); |
| 1439 | |
| 1440 | auto hash = mixed_hash(key); |
| 1441 | auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash); |
| 1442 | auto bucket_idx = bucket_idx_from_hash(hash); |
| 1443 | |
| 1444 | bool key_found = false; |
| 1445 | while (true) { |
| 1446 | auto const& bucket = at(m_buckets, bucket_idx); |
| 1447 | if (dist_and_fingerprint > bucket.m_dist_and_fingerprint) { |
| 1448 | break; |
| 1449 | } |
| 1450 | if (dist_and_fingerprint == bucket.m_dist_and_fingerprint && |
| 1451 | m_equal(key, get_key(m_values[bucket.m_value_idx]))) { |
| 1452 | key_found = true; |
| 1453 | break; |
| 1454 | } |
| 1455 | dist_and_fingerprint = dist_inc(dist_and_fingerprint); |
| 1456 | bucket_idx = next(bucket_idx); |
| 1457 | } |
| 1458 | |
| 1459 | if (key_found) { |
| 1460 | if (value_idx != static_cast<value_idx_type>(m_values.size() - 1)) { |
| 1461 | m_values[value_idx] = std::move(m_values.back()); |
| 1462 | } |
| 1463 | m_values.pop_back(); |
| 1464 | } else { |
| 1465 | place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx); |
| 1466 | ++value_idx; |
| 1467 | } |
| 1468 | } |
| 1469 | } |
| 1470 | |
| 1471 | template <class M, typename Q = T, std::enable_if_t<is_map_v<Q>, bool> = true> |
| 1472 | auto insert_or_assign(Key const& key, M&& mapped) -> std::pair<iterator, bool> { |
no test coverage detected