flat_hash_map.h (27260B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: flat_hash_map.h 17 // ----------------------------------------------------------------------------- 18 // 19 // An `absl::flat_hash_map<K, V>` is an unordered associative container of 20 // unique keys and associated values designed to be a more efficient replacement 21 // for `std::unordered_map`. Like `unordered_map`, search, insertion, and 22 // deletion of map elements can be done as an `O(1)` operation. However, 23 // `flat_hash_map` (and other unordered associative containers known as the 24 // collection of Abseil "Swiss tables") contain other optimizations that result 25 // in both memory and computation advantages. 26 // 27 // In most cases, your default choice for a hash map should be a map of type 28 // `flat_hash_map`. 29 // 30 // `flat_hash_map` is not exception-safe. 31 32 #ifndef ABSL_CONTAINER_FLAT_HASH_MAP_H_ 33 #define ABSL_CONTAINER_FLAT_HASH_MAP_H_ 34 35 #include <cstddef> 36 #include <memory> 37 #include <type_traits> 38 #include <utility> 39 40 #include "absl/algorithm/container.h" 41 #include "absl/base/attributes.h" 42 #include "absl/base/macros.h" 43 #include "absl/container/hash_container_defaults.h" 44 #include "absl/container/internal/container_memory.h" 45 #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export 46 #include "absl/meta/type_traits.h" 47 48 namespace absl { 49 ABSL_NAMESPACE_BEGIN 50 namespace container_internal { 51 template <class K, class V> 52 struct FlatHashMapPolicy; 53 } // namespace container_internal 54 55 // ----------------------------------------------------------------------------- 56 // absl::flat_hash_map 57 // ----------------------------------------------------------------------------- 58 // 59 // An `absl::flat_hash_map<K, V>` is an unordered associative container which 60 // has been optimized for both speed and memory footprint in most common use 61 // cases. Its interface is similar to that of `std::unordered_map<K, V>` with 62 // the following notable differences: 63 // 64 // * Requires keys that are CopyConstructible 65 // * Requires values that are MoveConstructible 66 // * Supports heterogeneous lookup, through `find()`, `operator[]()` and 67 // `insert()`, provided that the map is provided a compatible heterogeneous 68 // hashing function and equality operator. See below for details. 69 // * Invalidates any references and pointers to elements within the table after 70 // `rehash()` and when the table is moved. 71 // * Contains a `capacity()` member function indicating the number of element 72 // slots (open, deleted, and empty) within the hash map. 73 // * Returns `void` from the `erase(iterator)` overload. 74 // 75 // By default, `flat_hash_map` uses the `absl::Hash` hashing framework. 76 // All fundamental and Abseil types that support the `absl::Hash` framework have 77 // a compatible equality operator for comparing insertions into `flat_hash_map`. 78 // If your type is not yet supported by the `absl::Hash` framework, see 79 // absl/hash/hash.h for information on extending Abseil hashing to user-defined 80 // types. 81 // 82 // Using `absl::flat_hash_map` at interface boundaries in dynamically loaded 83 // libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may 84 // be randomized across dynamically loaded libraries. 85 // 86 // To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type 87 // parameters can be used or `T` should have public inner types 88 // `absl_container_hash` and (optionally) `absl_container_eq`. In either case, 89 // `typename Hash::is_transparent` and `typename Eq::is_transparent` should be 90 // well-formed. Both types are basically functors: 91 // * `Hash` should support `size_t operator()(U val) const` that returns a hash 92 // for the given `val`. 93 // * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true 94 // if `lhs` is equal to `rhs`. 95 // 96 // In most cases `T` needs only to provide the `absl_container_hash`. In this 97 // case `std::equal_to<void>` will be used instead of `eq` part. 98 // 99 // NOTE: A `flat_hash_map` stores its value types directly inside its 100 // implementation array to avoid memory indirection. Because a `flat_hash_map` 101 // is designed to move data when rehashed, map values will not retain pointer 102 // stability. If you require pointer stability, or if your values are large, 103 // consider using `absl::flat_hash_map<Key, std::unique_ptr<Value>>` instead. 104 // If your types are not moveable or you require pointer stability for keys, 105 // consider `absl::node_hash_map`. 106 // 107 // PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance: 108 // * Iteration takes O(capacity) time, not O(size). 109 // * erase() slows down begin() and ++iterator. 110 // * Capacity only shrinks on rehash() or clear() -- not on erase(). 111 // 112 // Example: 113 // 114 // // Create a flat hash map of three strings (that map to strings) 115 // absl::flat_hash_map<std::string, std::string> ducks = 116 // {{"a", "huey"}, {"b", "dewey"}, {"c", "louie"}}; 117 // 118 // // Insert a new element into the flat hash map 119 // ducks.insert({"d", "donald"}); 120 // 121 // // Force a rehash of the flat hash map 122 // ducks.rehash(0); 123 // 124 // // Find the element with the key "b" 125 // std::string search_key = "b"; 126 // auto result = ducks.find(search_key); 127 // if (result != ducks.end()) { 128 // std::cout << "Result: " << result->second << std::endl; 129 // } 130 template <class K, class V, class Hash = DefaultHashContainerHash<K>, 131 class Eq = DefaultHashContainerEq<K>, 132 class Allocator = std::allocator<std::pair<const K, V>>> 133 class ABSL_ATTRIBUTE_OWNER flat_hash_map 134 : public absl::container_internal::raw_hash_map< 135 absl::container_internal::FlatHashMapPolicy<K, V>, Hash, Eq, 136 Allocator> { 137 using Base = typename flat_hash_map::raw_hash_map; 138 139 public: 140 // Constructors and Assignment Operators 141 // 142 // A flat_hash_map supports the same overload set as `std::unordered_map` 143 // for construction and assignment: 144 // 145 // * Default constructor 146 // 147 // // No allocation for the table's elements is made. 148 // absl::flat_hash_map<int, std::string> map1; 149 // 150 // * Initializer List constructor 151 // 152 // absl::flat_hash_map<int, std::string> map2 = 153 // {{1, "huey"}, {2, "dewey"}, {3, "louie"},}; 154 // 155 // * Copy constructor 156 // 157 // absl::flat_hash_map<int, std::string> map3(map2); 158 // 159 // * Copy assignment operator 160 // 161 // // Hash functor and Comparator are copied as well 162 // absl::flat_hash_map<int, std::string> map4; 163 // map4 = map3; 164 // 165 // * Move constructor 166 // 167 // // Move is guaranteed efficient 168 // absl::flat_hash_map<int, std::string> map5(std::move(map4)); 169 // 170 // * Move assignment operator 171 // 172 // // May be efficient if allocators are compatible 173 // absl::flat_hash_map<int, std::string> map6; 174 // map6 = std::move(map5); 175 // 176 // * Range constructor 177 // 178 // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; 179 // absl::flat_hash_map<int, std::string> map7(v.begin(), v.end()); 180 flat_hash_map() {} 181 using Base::Base; 182 183 // flat_hash_map::begin() 184 // 185 // Returns an iterator to the beginning of the `flat_hash_map`. 186 using Base::begin; 187 188 // flat_hash_map::cbegin() 189 // 190 // Returns a const iterator to the beginning of the `flat_hash_map`. 191 using Base::cbegin; 192 193 // flat_hash_map::cend() 194 // 195 // Returns a const iterator to the end of the `flat_hash_map`. 196 using Base::cend; 197 198 // flat_hash_map::end() 199 // 200 // Returns an iterator to the end of the `flat_hash_map`. 201 using Base::end; 202 203 // flat_hash_map::capacity() 204 // 205 // Returns the number of element slots (assigned, deleted, and empty) 206 // available within the `flat_hash_map`. 207 // 208 // NOTE: this member function is particular to `absl::flat_hash_map` and is 209 // not provided in the `std::unordered_map` API. 210 using Base::capacity; 211 212 // flat_hash_map::empty() 213 // 214 // Returns whether or not the `flat_hash_map` is empty. 215 using Base::empty; 216 217 // flat_hash_map::max_size() 218 // 219 // Returns the largest theoretical possible number of elements within a 220 // `flat_hash_map` under current memory constraints. This value can be thought 221 // of the largest value of `std::distance(begin(), end())` for a 222 // `flat_hash_map<K, V>`. 223 using Base::max_size; 224 225 // flat_hash_map::size() 226 // 227 // Returns the number of elements currently within the `flat_hash_map`. 228 using Base::size; 229 230 // flat_hash_map::clear() 231 // 232 // Removes all elements from the `flat_hash_map`. Invalidates any references, 233 // pointers, or iterators referring to contained elements. 234 // 235 // NOTE: this operation may shrink the underlying buffer. To avoid shrinking 236 // the underlying buffer call `erase(begin(), end())`. 237 using Base::clear; 238 239 // flat_hash_map::erase() 240 // 241 // Erases elements within the `flat_hash_map`. Erasing does not trigger a 242 // rehash. Overloads are listed below. 243 // 244 // void erase(const_iterator pos): 245 // 246 // Erases the element at `position` of the `flat_hash_map`, returning 247 // `void`. 248 // 249 // NOTE: returning `void` in this case is different than that of STL 250 // containers in general and `std::unordered_map` in particular (which 251 // return an iterator to the element following the erased element). If that 252 // iterator is needed, simply post increment the iterator: 253 // 254 // map.erase(it++); 255 // 256 // iterator erase(const_iterator first, const_iterator last): 257 // 258 // Erases the elements in the open interval [`first`, `last`), returning an 259 // iterator pointing to `last`. The special case of calling 260 // `erase(begin(), end())` resets the reserved growth such that if 261 // `reserve(N)` has previously been called and there has been no intervening 262 // call to `clear()`, then after calling `erase(begin(), end())`, it is safe 263 // to assume that inserting N elements will not cause a rehash. 264 // 265 // size_type erase(const key_type& key): 266 // 267 // Erases the element with the matching key, if it exists, returning the 268 // number of elements erased (0 or 1). 269 using Base::erase; 270 271 // flat_hash_map::insert() 272 // 273 // Inserts an element of the specified value into the `flat_hash_map`, 274 // returning an iterator pointing to the newly inserted element, provided that 275 // an element with the given key does not already exist. If rehashing occurs 276 // due to the insertion, all iterators are invalidated. Overloads are listed 277 // below. 278 // 279 // std::pair<iterator,bool> insert(const init_type& value): 280 // 281 // Inserts a value into the `flat_hash_map`. Returns a pair consisting of an 282 // iterator to the inserted element (or to the element that prevented the 283 // insertion) and a bool denoting whether the insertion took place. 284 // 285 // std::pair<iterator,bool> insert(T&& value): 286 // std::pair<iterator,bool> insert(init_type&& value): 287 // 288 // Inserts a moveable value into the `flat_hash_map`. Returns a pair 289 // consisting of an iterator to the inserted element (or to the element that 290 // prevented the insertion) and a bool denoting whether the insertion took 291 // place. 292 // 293 // iterator insert(const_iterator hint, const init_type& value): 294 // iterator insert(const_iterator hint, T&& value): 295 // iterator insert(const_iterator hint, init_type&& value); 296 // 297 // Inserts a value, using the position of `hint` as a non-binding suggestion 298 // for where to begin the insertion search. Returns an iterator to the 299 // inserted element, or to the existing element that prevented the 300 // insertion. 301 // 302 // void insert(InputIterator first, InputIterator last): 303 // 304 // Inserts a range of values [`first`, `last`). 305 // 306 // NOTE: Although the STL does not specify which element may be inserted if 307 // multiple keys compare equivalently, for `flat_hash_map` we guarantee the 308 // first match is inserted. 309 // 310 // void insert(std::initializer_list<init_type> ilist): 311 // 312 // Inserts the elements within the initializer list `ilist`. 313 // 314 // NOTE: Although the STL does not specify which element may be inserted if 315 // multiple keys compare equivalently within the initializer list, for 316 // `flat_hash_map` we guarantee the first match is inserted. 317 using Base::insert; 318 319 // flat_hash_map::insert_or_assign() 320 // 321 // Inserts an element of the specified value into the `flat_hash_map` provided 322 // that a value with the given key does not already exist, or replaces it with 323 // the element value if a key for that value already exists, returning an 324 // iterator pointing to the newly inserted element. If rehashing occurs due 325 // to the insertion, all existing iterators are invalidated. Overloads are 326 // listed below. 327 // 328 // pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj): 329 // pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj): 330 // 331 // Inserts/Assigns (or moves) the element of the specified key into the 332 // `flat_hash_map`. 333 // 334 // iterator insert_or_assign(const_iterator hint, 335 // const init_type& k, T&& obj): 336 // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj): 337 // 338 // Inserts/Assigns (or moves) the element of the specified key into the 339 // `flat_hash_map` using the position of `hint` as a non-binding suggestion 340 // for where to begin the insertion search. 341 using Base::insert_or_assign; 342 343 // flat_hash_map::emplace() 344 // 345 // Inserts an element of the specified value by constructing it in-place 346 // within the `flat_hash_map`, provided that no element with the given key 347 // already exists. 348 // 349 // The element may be constructed even if there already is an element with the 350 // key in the container, in which case the newly constructed element will be 351 // destroyed immediately. Prefer `try_emplace()` unless your key is not 352 // copyable or moveable. 353 // 354 // If rehashing occurs due to the insertion, all iterators are invalidated. 355 using Base::emplace; 356 357 // flat_hash_map::emplace_hint() 358 // 359 // Inserts an element of the specified value by constructing it in-place 360 // within the `flat_hash_map`, using the position of `hint` as a non-binding 361 // suggestion for where to begin the insertion search, and only inserts 362 // provided that no element with the given key already exists. 363 // 364 // The element may be constructed even if there already is an element with the 365 // key in the container, in which case the newly constructed element will be 366 // destroyed immediately. Prefer `try_emplace()` unless your key is not 367 // copyable or moveable. 368 // 369 // If rehashing occurs due to the insertion, all iterators are invalidated. 370 using Base::emplace_hint; 371 372 // flat_hash_map::try_emplace() 373 // 374 // Inserts an element of the specified value by constructing it in-place 375 // within the `flat_hash_map`, provided that no element with the given key 376 // already exists. Unlike `emplace()`, if an element with the given key 377 // already exists, we guarantee that no element is constructed. 378 // 379 // If rehashing occurs due to the insertion, all iterators are invalidated. 380 // Overloads are listed below. 381 // 382 // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args): 383 // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args): 384 // 385 // Inserts (via copy or move) the element of the specified key into the 386 // `flat_hash_map`. 387 // 388 // iterator try_emplace(const_iterator hint, 389 // const key_type& k, Args&&... args): 390 // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args): 391 // 392 // Inserts (via copy or move) the element of the specified key into the 393 // `flat_hash_map` using the position of `hint` as a non-binding suggestion 394 // for where to begin the insertion search. 395 // 396 // All `try_emplace()` overloads make the same guarantees regarding rvalue 397 // arguments as `std::unordered_map::try_emplace()`, namely that these 398 // functions will not move from rvalue arguments if insertions do not happen. 399 using Base::try_emplace; 400 401 // flat_hash_map::extract() 402 // 403 // Extracts the indicated element, erasing it in the process, and returns it 404 // as a C++17-compatible node handle. Overloads are listed below. 405 // 406 // node_type extract(const_iterator position): 407 // 408 // Extracts the key,value pair of the element at the indicated position and 409 // returns a node handle owning that extracted data. 410 // 411 // node_type extract(const key_type& x): 412 // 413 // Extracts the key,value pair of the element with a key matching the passed 414 // key value and returns a node handle owning that extracted data. If the 415 // `flat_hash_map` does not contain an element with a matching key, this 416 // function returns an empty node handle. 417 // 418 // NOTE: when compiled in an earlier version of C++ than C++17, 419 // `node_type::key()` returns a const reference to the key instead of a 420 // mutable reference. We cannot safely return a mutable reference without 421 // std::launder (which is not available before C++17). 422 using Base::extract; 423 424 // flat_hash_map::merge() 425 // 426 // Extracts elements from a given `source` flat hash map into this 427 // `flat_hash_map`. If the destination `flat_hash_map` already contains an 428 // element with an equivalent key, that element is not extracted. 429 using Base::merge; 430 431 // flat_hash_map::swap(flat_hash_map& other) 432 // 433 // Exchanges the contents of this `flat_hash_map` with those of the `other` 434 // flat hash map. 435 // 436 // All iterators and references on the `flat_hash_map` remain valid, excepting 437 // for the past-the-end iterator, which is invalidated. 438 // 439 // `swap()` requires that the flat hash map's hashing and key equivalence 440 // functions be Swappable, and are exchanged using unqualified calls to 441 // non-member `swap()`. If the map's allocator has 442 // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value` 443 // set to `true`, the allocators are also exchanged using an unqualified call 444 // to non-member `swap()`; otherwise, the allocators are not swapped. 445 using Base::swap; 446 447 // flat_hash_map::rehash(count) 448 // 449 // Rehashes the `flat_hash_map`, setting the number of slots to be at least 450 // the passed value. If the new number of slots increases the load factor more 451 // than the current maximum load factor 452 // (`count` < `size()` / `max_load_factor()`), then the new number of slots 453 // will be at least `size()` / `max_load_factor()`. 454 // 455 // To force a rehash, pass rehash(0). 456 // 457 // NOTE: unlike behavior in `std::unordered_map`, references are also 458 // invalidated upon a `rehash()`. 459 using Base::rehash; 460 461 // flat_hash_map::reserve(count) 462 // 463 // Sets the number of slots in the `flat_hash_map` to the number needed to 464 // accommodate at least `count` total elements without exceeding the current 465 // maximum load factor, and may rehash the container if needed. 466 using Base::reserve; 467 468 // flat_hash_map::at() 469 // 470 // Returns a reference to the mapped value of the element with key equivalent 471 // to the passed key. 472 using Base::at; 473 474 // flat_hash_map::contains() 475 // 476 // Determines whether an element with a key comparing equal to the given `key` 477 // exists within the `flat_hash_map`, returning `true` if so or `false` 478 // otherwise. 479 using Base::contains; 480 481 // flat_hash_map::count(const Key& key) const 482 // 483 // Returns the number of elements with a key comparing equal to the given 484 // `key` within the `flat_hash_map`. note that this function will return 485 // either `1` or `0` since duplicate keys are not allowed within a 486 // `flat_hash_map`. 487 using Base::count; 488 489 // flat_hash_map::equal_range() 490 // 491 // Returns a closed range [first, last], defined by a `std::pair` of two 492 // iterators, containing all elements with the passed key in the 493 // `flat_hash_map`. 494 using Base::equal_range; 495 496 // flat_hash_map::find() 497 // 498 // Finds an element with the passed `key` within the `flat_hash_map`. 499 using Base::find; 500 501 // flat_hash_map::operator[]() 502 // 503 // Returns a reference to the value mapped to the passed key within the 504 // `flat_hash_map`, performing an `insert()` if the key does not already 505 // exist. 506 // 507 // If an insertion occurs and results in a rehashing of the container, all 508 // iterators are invalidated. Otherwise iterators are not affected and 509 // references are not invalidated. Overloads are listed below. 510 // 511 // T& operator[](const Key& key): 512 // 513 // Inserts an init_type object constructed in-place if the element with the 514 // given key does not exist. 515 // 516 // T& operator[](Key&& key): 517 // 518 // Inserts an init_type object constructed in-place provided that an element 519 // with the given key does not exist. 520 using Base::operator[]; 521 522 // flat_hash_map::bucket_count() 523 // 524 // Returns the number of "buckets" within the `flat_hash_map`. Note that 525 // because a flat hash map contains all elements within its internal storage, 526 // this value simply equals the current capacity of the `flat_hash_map`. 527 using Base::bucket_count; 528 529 // flat_hash_map::load_factor() 530 // 531 // Returns the current load factor of the `flat_hash_map` (the average number 532 // of slots occupied with a value within the hash map). 533 using Base::load_factor; 534 535 // flat_hash_map::max_load_factor() 536 // 537 // Manages the maximum load factor of the `flat_hash_map`. Overloads are 538 // listed below. 539 // 540 // float flat_hash_map::max_load_factor() 541 // 542 // Returns the current maximum load factor of the `flat_hash_map`. 543 // 544 // void flat_hash_map::max_load_factor(float ml) 545 // 546 // Sets the maximum load factor of the `flat_hash_map` to the passed value. 547 // 548 // NOTE: This overload is provided only for API compatibility with the STL; 549 // `flat_hash_map` will ignore any set load factor and manage its rehashing 550 // internally as an implementation detail. 551 using Base::max_load_factor; 552 553 // flat_hash_map::get_allocator() 554 // 555 // Returns the allocator function associated with this `flat_hash_map`. 556 using Base::get_allocator; 557 558 // flat_hash_map::hash_function() 559 // 560 // Returns the hashing function used to hash the keys within this 561 // `flat_hash_map`. 562 using Base::hash_function; 563 564 // flat_hash_map::key_eq() 565 // 566 // Returns the function used for comparing keys equality. 567 using Base::key_eq; 568 }; 569 570 // erase_if(flat_hash_map<>, Pred) 571 // 572 // Erases all elements that satisfy the predicate `pred` from the container `c`. 573 // Returns the number of erased elements. 574 template <typename K, typename V, typename H, typename E, typename A, 575 typename Predicate> 576 typename flat_hash_map<K, V, H, E, A>::size_type erase_if( 577 flat_hash_map<K, V, H, E, A>& c, Predicate pred) { 578 return container_internal::EraseIf(pred, &c); 579 } 580 581 // swap(flat_hash_map<>, flat_hash_map<>) 582 // 583 // Swaps the contents of two `flat_hash_map` containers. 584 // 585 // NOTE: we need to define this function template in order for 586 // `flat_hash_set::swap` to be called instead of `std::swap`. Even though we 587 // have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a 588 // derived-to-base conversion, whereas `std::swap` is a function template so 589 // `std::swap` will be preferred by compiler. 590 template <typename K, typename V, typename H, typename E, typename A> 591 void swap(flat_hash_map<K, V, H, E, A>& x, 592 flat_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) { 593 x.swap(y); 594 } 595 596 namespace container_internal { 597 598 // c_for_each_fast(flat_hash_map<>, Function) 599 // 600 // Container-based version of the <algorithm> `std::for_each()` function to 601 // apply a function to a container's elements. 602 // There is no guarantees on the order of the function calls. 603 // Erasure and/or insertion of elements in the function is not allowed. 604 template <typename K, typename V, typename H, typename E, typename A, 605 typename Function> 606 decay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c, 607 Function&& f) { 608 container_internal::ForEach(f, &c); 609 return f; 610 } 611 template <typename K, typename V, typename H, typename E, typename A, 612 typename Function> 613 decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c, 614 Function&& f) { 615 container_internal::ForEach(f, &c); 616 return f; 617 } 618 template <typename K, typename V, typename H, typename E, typename A, 619 typename Function> 620 decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c, 621 Function&& f) { 622 container_internal::ForEach(f, &c); 623 return f; 624 } 625 626 } // namespace container_internal 627 628 namespace container_internal { 629 630 template <class K, class V> 631 struct FlatHashMapPolicy { 632 using slot_policy = container_internal::map_slot_policy<K, V>; 633 using slot_type = typename slot_policy::slot_type; 634 using key_type = K; 635 using mapped_type = V; 636 using init_type = std::pair</*non const*/ key_type, mapped_type>; 637 638 template <class Allocator, class... Args> 639 static void construct(Allocator* alloc, slot_type* slot, Args&&... args) { 640 slot_policy::construct(alloc, slot, std::forward<Args>(args)...); 641 } 642 643 // Returns std::true_type in case destroy is trivial. 644 template <class Allocator> 645 static auto destroy(Allocator* alloc, slot_type* slot) { 646 return slot_policy::destroy(alloc, slot); 647 } 648 649 template <class Allocator> 650 static auto transfer(Allocator* alloc, slot_type* new_slot, 651 slot_type* old_slot) { 652 return slot_policy::transfer(alloc, new_slot, old_slot); 653 } 654 655 template <class F, class... Args> 656 static decltype(absl::container_internal::DecomposePair( 657 std::declval<F>(), std::declval<Args>()...)) 658 apply(F&& f, Args&&... args) { 659 return absl::container_internal::DecomposePair(std::forward<F>(f), 660 std::forward<Args>(args)...); 661 } 662 663 template <class Hash> 664 static constexpr HashSlotFn get_hash_slot_fn() { 665 return memory_internal::IsLayoutCompatible<K, V>::value 666 ? &TypeErasedApplyToSlotFn<Hash, K> 667 : nullptr; 668 } 669 670 static size_t space_used(const slot_type*) { return 0; } 671 672 static std::pair<const K, V>& element(slot_type* slot) { return slot->value; } 673 674 static V& value(std::pair<const K, V>* kv) { return kv->second; } 675 static const V& value(const std::pair<const K, V>* kv) { return kv->second; } 676 }; 677 678 } // namespace container_internal 679 680 namespace container_algorithm_internal { 681 682 // Specialization of trait in absl/algorithm/container.h 683 template <class Key, class T, class Hash, class KeyEqual, class Allocator> 684 struct IsUnorderedContainer< 685 absl::flat_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {}; 686 687 } // namespace container_algorithm_internal 688 689 ABSL_NAMESPACE_END 690 } // namespace absl 691 692 #endif // ABSL_CONTAINER_FLAT_HASH_MAP_H_