1// -*- C++ -*-
2
3// Copyright (C) 2005-2015 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
55namespace __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