1 // -*- C++ -*- 2 3 // Copyright (C) 2005-2013 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the terms 7 // of the GNU General Public License as published by the Free Software 8 // Foundation; either version 3, or (at your option) any later 9 // version. 10 11 // This library is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 26 27 // Permission to use, copy, modify, sell, and distribute this software 28 // is hereby granted without fee, provided that the above copyright 29 // notice appears in all copies, and that both that copyright notice 30 // and this permission notice appear in supporting documentation. None 31 // of the above authors, nor IBM Haifa Research Laboratories, make any 32 // representation about the suitability of this software for any 33 // purpose. It is provided "as is" without express or implied 34 // warranty. 35 36 /** 37 * @file gp_hash_table_map_/gp_ht_map_.hpp 38 * Contains an implementation class for general probing hash. 39 */ 40 41 #include <ext/pb_ds/tag_and_trait.hpp> 42 #include <ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp> 43 #include <ext/pb_ds/detail/types_traits.hpp> 44 #include <ext/pb_ds/exception.hpp> 45 #include <ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp> 46 #include <utility> 47 #ifdef PB_DS_HT_MAP_TRACE_ 48 #include <iostream> 49 #endif 50 #ifdef _GLIBCXX_DEBUG 51 #include <ext/pb_ds/detail/debug_map_base.hpp> 52 #endif 53 #include <debug/debug.h> 54 55 namespace __gnu_pbds 56 { 57 namespace detail 58 { 59 #ifdef PB_DS_DATA_TRUE_INDICATOR 60 #define PB_DS_GP_HASH_NAME gp_ht_map 61 #endif 62 63 #ifdef PB_DS_DATA_FALSE_INDICATOR 64 #define PB_DS_GP_HASH_NAME gp_ht_set 65 #endif 66 67 #define PB_DS_CLASS_T_DEC \ 68 template<typename Key, typename Mapped, typename Hash_Fn, typename Eq_Fn, \ 69 typename _Alloc, bool Store_Hash, typename Comb_Probe_Fn, \ 70 typename Probe_Fn, typename Resize_Policy> 71 72 #define PB_DS_CLASS_C_DEC \ 73 PB_DS_GP_HASH_NAME<Key, Mapped, Hash_Fn, Eq_Fn, _Alloc, \ 74 Store_Hash, Comb_Probe_Fn, Probe_Fn, Resize_Policy> 75 76 #define PB_DS_HASH_EQ_FN_C_DEC \ 77 hash_eq_fn<Key, Eq_Fn, _Alloc, Store_Hash> 78 79 #define PB_DS_RANGED_PROBE_FN_C_DEC \ 80 ranged_probe_fn<Key, Hash_Fn, _Alloc, Comb_Probe_Fn, Probe_Fn, Store_Hash> 81 82 #define PB_DS_GP_HASH_TRAITS_BASE \ 83 types_traits<Key, Mapped, _Alloc, Store_Hash> 84 85 #ifdef _GLIBCXX_DEBUG 86 #define PB_DS_DEBUG_MAP_BASE_C_DEC \ 87 debug_map_base<Key, Eq_Fn, \ 88 typename _Alloc::template rebind<Key>::other::const_reference> 89 #endif 90 91 92 /** 93 * A general-probing hash-based container. 94 * 95 * 96 * @ingroup hash-detail 97 * 98 * @tparam Key Key type. 99 * 100 * @tparam Mapped Map type. 101 * 102 * @tparam Hash_Fn Hashing functor. 103 * Default is __gnu_cxx::hash. 104 * 105 * @tparam Eq_Fn Equal functor. 106 * Default std::equal_to<Key> 107 * 108 * @tparam _Alloc Allocator type. 109 * 110 * @tparam Store_Hash If key type stores extra metadata. 111 * Defaults to false. 112 * 113 * @tparam Comb_Probe_Fn Combining probe functor. 114 * If Hash_Fn is not null_type, then this 115 * is the ranged-probe functor; otherwise, 116 * this is the range-hashing functor. 117 * XXX See Design::Hash-Based Containers::Hash Policies. 118 * Default direct_mask_range_hashing. 119 * 120 * @tparam Probe_Fn Probe functor. 121 * Defaults to linear_probe_fn, 122 * also quadratic_probe_fn. 123 * 124 * @tparam Resize_Policy Resizes hash. 125 * Defaults to hash_standard_resize_policy, 126 * using hash_exponential_size_policy and 127 * hash_load_check_resize_trigger. 128 * 129 * 130 * Bases are: detail::hash_eq_fn, Resize_Policy, detail::ranged_probe_fn, 131 * detail::types_traits. (Optional: detail::debug_map_base.) 132 */ 133 template<typename Key, 134 typename Mapped, 135 typename Hash_Fn, 136 typename Eq_Fn, 137 typename _Alloc, 138 bool Store_Hash, 139 typename Comb_Probe_Fn, 140 typename Probe_Fn, 141 typename Resize_Policy> 142 class PB_DS_GP_HASH_NAME : 143 #ifdef _GLIBCXX_DEBUG 144 protected PB_DS_DEBUG_MAP_BASE_C_DEC, 145 #endif 146 public PB_DS_HASH_EQ_FN_C_DEC, 147 public Resize_Policy, 148 public PB_DS_RANGED_PROBE_FN_C_DEC, 149 public PB_DS_GP_HASH_TRAITS_BASE 150 { 151 private: 152 typedef PB_DS_GP_HASH_TRAITS_BASE traits_base; 153 typedef typename traits_base::value_type value_type_; 154 typedef typename traits_base::pointer pointer_; 155 typedef typename traits_base::const_pointer const_pointer_; 156 typedef typename traits_base::reference reference_; 157 typedef typename traits_base::const_reference const_reference_; 158 typedef typename traits_base::comp_hash comp_hash; 159 160 enum entry_status 161 { 162 empty_entry_status, 163 valid_entry_status, 164 erased_entry_status 165 } __attribute__ ((packed)); 166 167 struct entry : public traits_base::stored_data_type 168 { 169 entry_status m_stat; 170 }; 171 172 typedef typename _Alloc::template rebind<entry>::other entry_allocator; 173 typedef typename entry_allocator::pointer entry_pointer; 174 typedef typename entry_allocator::const_pointer const_entry_pointer; 175 typedef typename entry_allocator::reference entry_reference; 176 typedef typename entry_allocator::const_reference const_entry_reference; 177 typedef typename entry_allocator::pointer entry_array; 178 179 typedef PB_DS_RANGED_PROBE_FN_C_DEC ranged_probe_fn_base; 180 181 #ifdef _GLIBCXX_DEBUG 182 typedef PB_DS_DEBUG_MAP_BASE_C_DEC debug_base; 183 #endif 184 185 typedef PB_DS_HASH_EQ_FN_C_DEC hash_eq_fn_base; 186 typedef Resize_Policy resize_base; 187 188 #define PB_DS_GEN_POS typename _Alloc::size_type 189 190 #include <ext/pb_ds/detail/unordered_iterator/point_const_iterator.hpp> 191 #include <ext/pb_ds/detail/unordered_iterator/point_iterator.hpp> 192 #include <ext/pb_ds/detail/unordered_iterator/const_iterator.hpp> 193 #include <ext/pb_ds/detail/unordered_iterator/iterator.hpp> 194 195 #undef PB_DS_GEN_POS 196 197 public: 198 typedef _Alloc allocator_type; 199 typedef typename _Alloc::size_type size_type; 200 typedef typename _Alloc::difference_type difference_type; 201 typedef Hash_Fn hash_fn; 202 typedef Eq_Fn eq_fn; 203 typedef Probe_Fn probe_fn; 204 typedef Comb_Probe_Fn comb_probe_fn; 205 typedef Resize_Policy resize_policy; 206 207 /// Value stores hash, true or false. 208 enum 209 { 210 store_hash = Store_Hash 211 }; 212 213 typedef typename traits_base::key_type key_type; 214 typedef typename traits_base::key_pointer key_pointer; 215 typedef typename traits_base::key_const_pointer key_const_pointer; 216 typedef typename traits_base::key_reference key_reference; 217 typedef typename traits_base::key_const_reference key_const_reference; 218 typedef typename traits_base::mapped_type mapped_type; 219 typedef typename traits_base::mapped_pointer mapped_pointer; 220 typedef typename traits_base::mapped_const_pointer mapped_const_pointer; 221 typedef typename traits_base::mapped_reference mapped_reference; 222 typedef typename traits_base::mapped_const_reference mapped_const_reference; 223 typedef typename traits_base::value_type value_type; 224 typedef typename traits_base::pointer pointer; 225 typedef typename traits_base::const_pointer const_pointer; 226 typedef typename traits_base::reference reference; 227 typedef typename traits_base::const_reference const_reference; 228 229 #ifdef PB_DS_DATA_TRUE_INDICATOR 230 typedef point_iterator_ point_iterator; 231 #endif 232 233 #ifdef PB_DS_DATA_FALSE_INDICATOR 234 typedef point_const_iterator_ point_iterator; 235 #endif 236 237 typedef point_const_iterator_ point_const_iterator; 238 239 #ifdef PB_DS_DATA_TRUE_INDICATOR 240 typedef iterator_ iterator; 241 #endif 242 243 #ifdef PB_DS_DATA_FALSE_INDICATOR 244 typedef const_iterator_ iterator; 245 #endif 246 247 typedef const_iterator_ const_iterator; 248 249 PB_DS_GP_HASH_NAME(); 250 251 PB_DS_GP_HASH_NAME(const PB_DS_CLASS_C_DEC&); 252 253 PB_DS_GP_HASH_NAME(const Hash_Fn&); 254 255 PB_DS_GP_HASH_NAME(const Hash_Fn&, const Eq_Fn&); 256 257 PB_DS_GP_HASH_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Probe_Fn&); 258 259 PB_DS_GP_HASH_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Probe_Fn&, 260 const Probe_Fn&); 261 262 PB_DS_GP_HASH_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Probe_Fn&, 263 const Probe_Fn&, const Resize_Policy&); 264 265 template<typename It> 266 void 267 copy_from_range(It, It); 268 269 virtual 270 ~PB_DS_GP_HASH_NAME(); 271 272 void 273 swap(PB_DS_CLASS_C_DEC&); 274 275 inline size_type 276 size() const; 277 278 inline size_type 279 max_size() const; 280 281 /// True if size() == 0. 282 inline bool 283 empty() const; 284 285 /// Return current hash_fn. 286 Hash_Fn& 287 get_hash_fn(); 288 289 /// Return current const hash_fn. 290 const Hash_Fn& 291 get_hash_fn() const; 292 293 /// Return current eq_fn. 294 Eq_Fn& 295 get_eq_fn(); 296 297 /// Return current const eq_fn. 298 const Eq_Fn& 299 get_eq_fn() const; 300 301 /// Return current probe_fn. 302 Probe_Fn& 303 get_probe_fn(); 304 305 /// Return current const probe_fn. 306 const Probe_Fn& 307 get_probe_fn() const; 308 309 /// Return current comb_probe_fn. 310 Comb_Probe_Fn& 311 get_comb_probe_fn(); 312 313 /// Return current const comb_probe_fn. 314 const Comb_Probe_Fn& 315 get_comb_probe_fn() const; 316 317 /// Return current resize_policy. 318 Resize_Policy& 319 get_resize_policy(); 320 321 /// Return current const resize_policy. 322 const Resize_Policy& 323 get_resize_policy() const; 324 325 inline std::pair<point_iterator, bool> 326 insert(const_reference r_val) 327 { 328 _GLIBCXX_DEBUG_ONLY(PB_DS_CLASS_C_DEC::assert_valid(__FILE__, __LINE__);) 329 return insert_imp(r_val, traits_base::m_store_extra_indicator); 330 } 331 332 inline mapped_reference 333 operator[](key_const_reference r_key) 334 { 335 #ifdef PB_DS_DATA_TRUE_INDICATOR 336 return subscript_imp(r_key, traits_base::m_store_extra_indicator); 337 #else 338 insert(r_key); 339 return traits_base::s_null_type; 340 #endif 341 } 342 343 inline point_iterator 344 find(key_const_reference); 345 346 inline point_const_iterator 347 find(key_const_reference) const; 348 349 inline point_iterator 350 find_end(); 351 352 inline point_const_iterator 353 find_end() const; 354 355 inline bool 356 erase(key_const_reference); 357 358 template<typename Pred> 359 inline size_type 360 erase_if(Pred); 361 362 void 363 clear(); 364 365 inline iterator 366 begin(); 367 368 inline const_iterator 369 begin() const; 370 371 inline iterator 372 end(); 373 374 inline const_iterator 375 end() const; 376 377 #ifdef _GLIBCXX_DEBUG 378 void 379 assert_valid(const char*, int) const; 380 #endif 381 382 #ifdef PB_DS_HT_MAP_TRACE_ 383 void 384 trace() const; 385 #endif 386 387 private: 388 #ifdef PB_DS_DATA_TRUE_INDICATOR 389 friend class iterator_; 390 #endif 391 392 friend class const_iterator_; 393 394 void 395 deallocate_all(); 396 397 void 398 initialize(); 399 400 void 401 erase_all_valid_entries(entry_array, size_type); 402 403 inline bool 404 do_resize_if_needed(); 405 406 inline void 407 do_resize_if_needed_no_throw(); 408 409 void 410 resize_imp(size_type); 411 412 virtual void 413 do_resize(size_type); 414 415 void 416 resize_imp(entry_array, size_type); 417 418 inline void 419 resize_imp_reassign(entry_pointer, entry_array, false_type); 420 421 inline void 422 resize_imp_reassign(entry_pointer, entry_array, true_type); 423 424 inline size_type 425 find_ins_pos(key_const_reference, false_type); 426 427 inline comp_hash 428 find_ins_pos(key_const_reference, true_type); 429 430 inline std::pair<point_iterator, bool> 431 insert_imp(const_reference, false_type); 432 433 inline std::pair<point_iterator, bool> 434 insert_imp(const_reference, true_type); 435 436 inline pointer 437 insert_new_imp(const_reference r_val, size_type pos) 438 { 439 _GLIBCXX_DEBUG_ASSERT(m_entries[pos].m_stat != valid_entry_status); 440 441 if (do_resize_if_needed()) 442 pos = find_ins_pos(PB_DS_V2F(r_val), 443 traits_base::m_store_extra_indicator); 444 445 _GLIBCXX_DEBUG_ASSERT(m_entries[pos].m_stat != valid_entry_status); 446 entry* const p_e = m_entries + pos; 447 new (&p_e->m_value) value_type(r_val); 448 p_e->m_stat = valid_entry_status; 449 resize_base::notify_inserted(++m_num_used_e); 450 451 _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(p_e->m_value));) 452 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);) 453 return &p_e->m_value; 454 } 455 456 inline pointer 457 insert_new_imp(const_reference r_val, comp_hash& r_pos_hash_pair) 458 { 459 _GLIBCXX_DEBUG_ASSERT(m_entries[r_pos_hash_pair.first].m_stat != 460 valid_entry_status); 461 462 if (do_resize_if_needed()) 463 r_pos_hash_pair = find_ins_pos(PB_DS_V2F(r_val), 464 traits_base::m_store_extra_indicator); 465 466 _GLIBCXX_DEBUG_ASSERT(m_entries[r_pos_hash_pair.first].m_stat != 467 valid_entry_status); 468 469 entry* const p_e = m_entries + r_pos_hash_pair.first; 470 new (&p_e->m_value) value_type(r_val); 471 p_e->m_hash = r_pos_hash_pair.second; 472 p_e->m_stat = valid_entry_status; 473 474 resize_base::notify_inserted(++m_num_used_e); 475 476 _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(p_e->m_value));) 477 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);) 478 return &p_e->m_value; 479 } 480 481 #ifdef PB_DS_DATA_TRUE_INDICATOR 482 inline mapped_reference 483 subscript_imp(key_const_reference key, false_type) 484 { 485 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);) 486 487 const size_type pos = find_ins_pos(key, 488 traits_base::m_store_extra_indicator); 489 490 entry_pointer p_e = &m_entries[pos]; 491 if (p_e->m_stat != valid_entry_status) 492 return insert_new_imp(value_type(key, mapped_type()), pos)->second; 493 494 PB_DS_CHECK_KEY_EXISTS(key) 495 return p_e->m_value.second; 496 } 497 498 inline mapped_reference 499 subscript_imp(key_const_reference key, true_type) 500 { 501 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);) 502 503 comp_hash pos_hash_pair = find_ins_pos(key, 504 traits_base::m_store_extra_indicator); 505 506 if (m_entries[pos_hash_pair.first].m_stat != valid_entry_status) 507 return insert_new_imp(value_type(key, mapped_type()), 508 pos_hash_pair)->second; 509 510 PB_DS_CHECK_KEY_EXISTS(key) 511 return (m_entries + pos_hash_pair.first)->m_value.second; 512 } 513 #endif 514 515 inline pointer 516 find_key_pointer(key_const_reference key, false_type) 517 { 518 const size_type hash = ranged_probe_fn_base::operator()(key); 519 resize_base::notify_find_search_start(); 520 521 // Loop until entry is found or until all possible entries accessed. 522 for (size_type i = 0; i < m_num_e; ++i) 523 { 524 const size_type pos = ranged_probe_fn_base::operator()(key, 525 hash, i); 526 527 entry* const p_e = m_entries + pos; 528 switch (p_e->m_stat) 529 { 530 case empty_entry_status: 531 { 532 resize_base::notify_find_search_end(); 533 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key) 534 return 0; 535 } 536 break; 537 case valid_entry_status: 538 if (hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value), key)) 539 { 540 resize_base::notify_find_search_end(); 541 PB_DS_CHECK_KEY_EXISTS(key) 542 return pointer(&p_e->m_value); 543 } 544 break; 545 case erased_entry_status: 546 break; 547 default: 548 _GLIBCXX_DEBUG_ASSERT(0); 549 }; 550 551 resize_base::notify_find_search_collision(); 552 } 553 554 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key) 555 resize_base::notify_find_search_end(); 556 return 0; 557 } 558 559 inline pointer 560 find_key_pointer(key_const_reference key, true_type) 561 { 562 comp_hash pos_hash_pair = ranged_probe_fn_base::operator()(key); 563 resize_base::notify_find_search_start(); 564 565 // Loop until entry is found or until all possible entries accessed. 566 for (size_type i = 0; i < m_num_e; ++i) 567 { 568 const size_type pos = 569 ranged_probe_fn_base::operator()(key, pos_hash_pair.second, i); 570 571 entry* const p_e = m_entries + pos; 572 573 switch(p_e->m_stat) 574 { 575 case empty_entry_status: 576 { 577 resize_base::notify_find_search_end(); 578 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key) 579 return 0; 580 } 581 break; 582 case valid_entry_status: 583 if (hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value), 584 p_e->m_hash, 585 key, pos_hash_pair.second)) 586 { 587 resize_base::notify_find_search_end(); 588 PB_DS_CHECK_KEY_EXISTS(key) 589 return pointer(&p_e->m_value); 590 } 591 break; 592 case erased_entry_status: 593 break; 594 default: 595 _GLIBCXX_DEBUG_ASSERT(0); 596 }; 597 598 resize_base::notify_find_search_collision(); 599 } 600 601 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key) 602 resize_base::notify_find_search_end(); 603 return 0; 604 } 605 606 inline bool 607 erase_imp(key_const_reference, true_type); 608 609 inline bool 610 erase_imp(key_const_reference, false_type); 611 612 inline void 613 erase_entry(entry_pointer); 614 615 #ifdef PB_DS_DATA_TRUE_INDICATOR 616 void 617 inc_it_state(pointer& r_p_value, size_type& r_pos) const 618 { inc_it_state((mapped_const_pointer& )r_p_value, r_pos); } 619 #endif 620 621 void 622 inc_it_state(const_pointer& r_p_value, size_type& r_pos) const 623 { 624 _GLIBCXX_DEBUG_ASSERT(r_p_value != 0); 625 for (++r_pos; r_pos < m_num_e; ++r_pos) 626 { 627 const_entry_pointer p_e =& m_entries[r_pos]; 628 if (p_e->m_stat == valid_entry_status) 629 { 630 r_p_value =& p_e->m_value; 631 return; 632 } 633 } 634 r_p_value = 0; 635 } 636 637 void 638 get_start_it_state(const_pointer& r_p_value, size_type& r_pos) const 639 { 640 for (r_pos = 0; r_pos < m_num_e; ++r_pos) 641 { 642 const_entry_pointer p_e = &m_entries[r_pos]; 643 if (p_e->m_stat == valid_entry_status) 644 { 645 r_p_value = &p_e->m_value; 646 return; 647 } 648 } 649 r_p_value = 0; 650 } 651 652 void 653 get_start_it_state(pointer& r_p_value, size_type& r_pos) 654 { 655 for (r_pos = 0; r_pos < m_num_e; ++r_pos) 656 { 657 entry_pointer p_e = &m_entries[r_pos]; 658 if (p_e->m_stat == valid_entry_status) 659 { 660 r_p_value = &p_e->m_value; 661 return; 662 } 663 } 664 r_p_value = 0; 665 } 666 667 #ifdef _GLIBCXX_DEBUG 668 void 669 assert_entry_array_valid(const entry_array, false_type, 670 const char*, int) const; 671 672 void 673 assert_entry_array_valid(const entry_array, true_type, 674 const char*, int) const; 675 #endif 676 677 static entry_allocator s_entry_allocator; 678 static iterator s_end_it; 679 static const_iterator s_const_end_it; 680 681 size_type m_num_e; 682 size_type m_num_used_e; 683 entry_pointer m_entries; 684 685 enum 686 { 687 store_hash_ok = !Store_Hash 688 || !is_same<Hash_Fn, __gnu_pbds::null_type>::value 689 }; 690 691 PB_DS_STATIC_ASSERT(sth, store_hash_ok); 692 }; 693 694 #include <ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp> 695 #include <ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp> 696 #include <ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp> 697 #include <ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp> 698 #include <ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp> 699 #include <ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp> 700 #include <ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp> 701 #include <ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp> 702 #include <ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp> 703 #include <ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp> 704 705 #undef PB_DS_CLASS_T_DEC 706 #undef PB_DS_CLASS_C_DEC 707 #undef PB_DS_HASH_EQ_FN_C_DEC 708 #undef PB_DS_RANGED_PROBE_FN_C_DEC 709 #undef PB_DS_GP_HASH_TRAITS_BASE 710 #undef PB_DS_DEBUG_MAP_BASE_C_DEC 711 #undef PB_DS_GP_HASH_NAME 712 } // namespace detail 713 } // namespace __gnu_pbds 714