29 #ifndef GUM_HASHTABLE_H 30 #define GUM_HASHTABLE_H 35 #include <initializer_list> 41 #include <agrum/agrum.h> 42 #include <agrum/tools/core/hashFunc.h> 46 #ifndef DOXYGEN_SHOULD_SKIP_THIS 49 template <
typename Key,
typename Val,
typename Alloc >
51 template <
typename Key,
typename Val,
typename Alloc >
53 template <
typename Key,
typename Val >
54 class HashTableIterator;
55 template <
typename Key,
typename Val >
56 class HashTableConstIterator;
57 template <
typename Key,
typename Val >
58 class HashTableIteratorSafe;
59 template <
typename Key,
typename Val >
60 class HashTableConstIteratorSafe;
61 template <
typename T1,
typename T2,
typename Alloc >
72 struct HashTableConst {
79 static constexpr Size default_size{Size(4)};
86 static constexpr Size default_mean_val_by_slot{Size(3)};
93 static constexpr bool default_resize_policy{
true};
101 static constexpr bool default_uniqueness_policy{
true};
118 template <
typename Key,
typename Val,
typename Alloc >
119 std::ostream& operator<<(std::ostream& s,
120 const HashTableList< Key, Val, Alloc >& list);
139 template <
typename Key,
typename Val,
typename Alloc >
140 std::ostream& operator<<(std::ostream& s,
141 const HashTableList< Key*, Val, Alloc >& list);
157 template <
typename Key,
typename Val,
typename Alloc >
158 std::ostream& operator<<(std::ostream& s,
159 const HashTable< Key, Val, Alloc >& table);
177 template <
typename Key,
typename Val,
typename Alloc >
178 std::ostream& operator<<(std::ostream& s,
179 const HashTable< Key*, Val, Alloc >& table);
200 template <
typename Key,
typename Val >
201 struct HashTableBucket {
203 std::pair<
const Key, Val > pair;
206 HashTableBucket< Key, Val >* prev{
nullptr};
209 HashTableBucket< Key, Val >* next{
nullptr};
227 HashTableBucket(
const HashTableBucket< Key, Val >& from) : pair{from.pair} {}
234 HashTableBucket(
const Key& k,
const Val& v) : pair{k, v} {}
241 HashTableBucket(Key&& k, Val&& v) : pair{std::move(k), std::move(v)} {}
247 HashTableBucket(
const std::pair<
const Key, Val >& p) : pair(p) {}
253 HashTableBucket(std::pair<
const Key, Val >&& p) : pair(std::move(p)) {}
261 template <
typename... Args >
262 HashTableBucket(Emplace e, Args&&... args) :
264 pair(std::forward< Args >(args)...) {}
269 ~HashTableBucket() {}
275 std::pair<
const Key, Val >& elt() {
return pair; }
281 Key& key() {
return const_cast< Key& >(pair.first); }
287 Val& val() {
return pair.second; }
304 template <
typename Key,
typename Val,
typename Alloc >
305 class HashTableList {
309 using key_type = Key;
310 using mapped_type = Val;
311 using value_type = std::pair<
const Key, Val >;
312 using reference = value_type&;
313 using const_reference =
const value_type&;
314 using pointer = value_type*;
315 using const_pointer =
const value_type*;
316 using size_type = Size;
317 using allocator_type = Alloc;
318 using Bucket = HashTableBucket< Key, Val >;
322 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
338 HashTableList(BucketAllocator* allocator =
nullptr)
noexcept;
351 HashTableList(
const HashTableList< Key, Val, Alloc >& from);
357 HashTableList(HashTableList< Key, Val, Alloc >&& from)
noexcept;
387 HashTableList< Key, Val, Alloc >&
388 operator=(
const HashTableList< Key, Val, Alloc >& from);
407 template <
typename OtherAlloc >
408 HashTableList< Key, Val, Alloc >&
409 operator=(
const HashTableList< Key, Val, OtherAlloc >& from);
417 HashTableList< Key, Val, Alloc >&
418 operator=(HashTableList< Key, Val, Alloc >&& from)
noexcept;
434 value_type& at(Size i);
444 const value_type& at(Size i)
const;
452 mapped_type& operator[](
const key_type& key);
460 const mapped_type& operator[](
const key_type& key)
const;
469 bool exists(
const key_type& key)
const;
477 void insert(Bucket* new_elt)
noexcept;
483 void erase(Bucket* ptr);
494 bool empty()
const noexcept;
503 Bucket* bucket(
const Key& key)
const;
509 void setAllocator(BucketAllocator& alloc);
516 template <
typename K,
typename V,
typename A >
517 friend class HashTableList;
518 friend class HashTable< Key, Val, Alloc >;
519 friend class HashTableIterator< Key, Val >;
520 friend class HashTableConstIterator< Key, Val >;
521 friend class HashTableIteratorSafe< Key, Val >;
522 friend class HashTableConstIteratorSafe< Key, Val >;
523 friend std::ostream& operator<<<>(std::ostream&,
524 const HashTableList< Key, Val, Alloc >&);
525 friend std::ostream& operator<<<>(std::ostream&,
526 const HashTableList< Key*, Val, Alloc >&);
527 friend std::ostream& operator<<<>(std::ostream&,
528 const HashTable< Key, Val, Alloc >&);
529 friend std::ostream& operator<<<>(std::ostream&,
530 const HashTable< Key*, Val, Alloc >&);
534 HashTableBucket< Key, Val >* deb_list__{
nullptr};
537 HashTableBucket< Key, Val >* end_list__{
nullptr};
540 Size nb_elements__{Size(0)};
543 mutable BucketAllocator* alloc_bucket__;
555 template <
typename OtherAlloc >
556 void copy__(
const HashTableList< Key, Val, OtherAlloc >& from);
676 template <
typename Key,
678 typename Alloc = std::allocator< std::pair< Key, Val > > >
683 using key_type = Key;
684 using mapped_type = Val;
685 using value_type = std::pair<
const Key, Val >;
686 using reference = value_type&;
687 using const_reference =
const value_type&;
688 using pointer = value_type*;
689 using const_pointer =
const value_type*;
690 using size_type = Size;
691 using difference_type = std::ptrdiff_t;
692 using allocator_type = Alloc;
693 using iterator = HashTableIterator< Key, Val >;
694 using const_iterator = HashTableConstIterator< Key, Val >;
695 using iterator_safe = HashTableIteratorSafe< Key, Val >;
696 using const_iterator_safe = HashTableConstIteratorSafe< Key, Val >;
700 using Bucket = HashTableBucket< Key, Val >;
703 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
727 explicit HashTable(Size size_param = HashTableConst::default_size,
728 bool resize_pol = HashTableConst::default_resize_policy,
729 bool key_uniqueness_pol
730 = HashTableConst::default_uniqueness_policy);
736 explicit HashTable(std::initializer_list< std::pair< Key, Val > > list);
750 HashTable(
const HashTable< Key, Val, Alloc >& from);
764 template <
typename OtherAlloc >
765 HashTable(
const HashTable< Key, Val, OtherAlloc >& from);
771 HashTable(HashTable< Key, Val, Alloc >&& from);
794 const iterator& end()
noexcept;
808 const const_iterator& end()
const noexcept;
822 const const_iterator& cend()
const noexcept;
850 const_iterator begin()
const;
864 const_iterator cbegin()
const;
875 const iterator_safe& endSafe()
noexcept;
888 const const_iterator_safe& endSafe()
const noexcept;
901 const const_iterator_safe& cendSafe()
const noexcept;
914 iterator_safe beginSafe();
927 const_iterator_safe beginSafe()
const;
940 const_iterator_safe cbeginSafe()
const;
979 static const iterator& end4Statics();
1018 static const const_iterator& constEnd4Statics();
1057 static const iterator_safe& endSafe4Statics();
1096 static const const_iterator_safe& constEndSafe4Statics();
1116 HashTable< Key, Val, Alloc >&
1117 operator=(
const HashTable< Key, Val, Alloc >& from);
1131 template <
typename OtherAlloc >
1132 HashTable< Key, Val, Alloc >&
1133 operator=(
const HashTable< Key, Val, OtherAlloc >& from);
1141 HashTable< Key, Val, Alloc >& operator=(HashTable< Key, Val, Alloc >&& from);
1154 Val& operator[](
const Key& key);
1160 const Val& operator[](
const Key& key)
const;
1173 template <
typename OtherAlloc >
1174 bool operator==(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1188 template <
typename OtherAlloc >
1189 bool operator!=(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1206 Size capacity()
const noexcept;
1226 void resize(Size new_size);
1245 void setResizePolicy(
const bool new_policy)
noexcept;
1251 bool resizePolicy()
const noexcept;
1268 void setKeyUniquenessPolicy(
const bool new_policy)
noexcept;
1274 bool keyUniquenessPolicy()
const noexcept;
1289 Size size()
const noexcept;
1301 bool exists(
const Key& key)
const;
1323 value_type& insert(
const Key& key,
const Val& val);
1343 value_type& insert(Key&& key, Val&& val);
1364 value_type& insert(
const std::pair< Key, Val >& elt);
1383 value_type& insert(std::pair< Key, Val >&& elt);
1401 template <
typename... Args >
1402 value_type& emplace(Args&&... args);
1418 mapped_type& getWithDefault(
const Key& key,
const Val& default_value);
1434 mapped_type& getWithDefault(Key&& key, Val&& default_value);
1447 void set(
const Key& key,
const Val& default_value);
1458 void reset(
const Key& key);
1474 void erase(
const Key& key);
1486 void erase(
const iterator_safe& iter);
1498 void erase(
const const_iterator_safe& iter);
1516 void eraseByVal(
const Val& val);
1528 const Key& keyByVal(
const Val& val)
const;
1542 const Key& key(
const Key& key)
const;
1556 void eraseAllVal(
const Val& val);
1572 bool empty()
const noexcept;
1594 template <
typename Mount,
1595 typename OtherAlloc =
typename Alloc::
template rebind<
1596 std::pair< Key, Mount > >::other >
1597 HashTable< Key, Mount, OtherAlloc >
1598 map(Mount (*f)(Val),
1599 Size size = Size(0),
1600 bool resize_pol = HashTableConst::default_resize_policy,
1601 bool key_uniqueness_pol
1602 = HashTableConst::default_uniqueness_policy)
const;
1624 template <
typename Mount,
1625 typename OtherAlloc =
typename Alloc::
template rebind<
1626 std::pair< Key, Mount > >::other >
1627 HashTable< Key, Mount, OtherAlloc >
1628 map(Mount (*f)(Val&),
1629 Size size = Size(0),
1630 bool resize_pol = HashTableConst::default_resize_policy,
1631 bool key_uniqueness_pol
1632 = HashTableConst::default_uniqueness_policy)
const;
1654 template <
typename Mount,
1655 typename OtherAlloc =
typename Alloc::
template rebind<
1656 std::pair< Key, Mount > >::other >
1657 HashTable< Key, Mount, OtherAlloc >
1658 map(Mount (*f)(
const Val&),
1659 Size size = Size(0),
1660 bool resize_pol = HashTableConst::default_resize_policy,
1661 bool key_uniqueness_pol
1662 = HashTableConst::default_uniqueness_policy)
const;
1686 template <
typename Mount,
1687 typename OtherAlloc =
typename Alloc::
template rebind<
1688 std::pair< Key, Mount > >::other >
1689 HashTable< Key, Mount, OtherAlloc >
1690 map(
const Mount& val,
1691 Size size = Size(0),
1692 bool resize_pol = HashTableConst::default_resize_policy,
1693 bool key_uniqueness_pol
1694 = HashTableConst::default_uniqueness_policy)
const;
1701 template <
typename K,
typename V,
typename A >
1702 friend class HashTable;
1703 friend class HashTableIterator< Key, Val >;
1704 friend class HashTableConstIterator< Key, Val >;
1705 friend class HashTableIteratorSafe< Key, Val >;
1706 friend class HashTableConstIteratorSafe< Key, Val >;
1708 friend std::ostream& operator<<<>(std::ostream&,
1709 const HashTable< Key, Val, Alloc >&);
1710 friend std::ostream& operator<<<>(std::ostream& s,
1711 const HashTable< Key*, Val, Alloc >& table);
1714 template <
typename T1,
typename T2,
typename A >
1715 friend class Bijection;
1722 std::vector< HashTableList< Key, Val, Alloc > > nodes__;
1728 Size nb_elements__{Size(0)};
1731 HashFunc< Key > hash_func__;
1734 bool resize_policy__{
true};
1737 bool key_uniqueness_policy__{
true};
1753 mutable Size begin_index__{std::numeric_limits< Size >::max()};
1756 mutable std::vector< HashTableConstIteratorSafe< Key, Val >* >
1767 BucketAllocator alloc__;
1770 void erase__(HashTableBucket< Key, Val >* bucket, Size index);
1787 template <
typename OtherAlloc >
1788 void copy__(
const HashTable< Key, Val, OtherAlloc >& table);
1794 void create__(Size size);
1799 void clearIterators__();
1817 void insert__(Bucket* bucket);
1835 class HashTableIteratorStaticEnd {
1838 static const HashTableIterator<
int,
int >* HashTableIterEnd__;
1841 static const HashTableIteratorSafe<
int,
int >* HashTableIterEndSafe__;
1847 static const HashTableIterator<
int,
int >* end4Statics();
1853 static const HashTableConstIterator<
int,
int >* constEnd4Statics();
1860 static const HashTableIteratorSafe<
int,
int >* endSafe4Statics();
1867 static const HashTableConstIteratorSafe<
int,
int >* constEndSafe4Statics();
1870 template <
typename Key,
typename Val,
typename Alloc >
1871 friend class HashTable;
1921 template <
typename Key,
typename Val >
1922 class HashTableConstIteratorSafe {
1926 using iterator_category = std::forward_iterator_tag;
1927 using key_type = Key;
1928 using mapped_type = Val;
1929 using value_type = std::pair<
const Key, Val >;
1930 using reference = value_type&;
1931 using const_reference =
const value_type&;
1932 using pointer = value_type*;
1933 using const_pointer =
const value_type*;
1934 using difference_type = std::ptrdiff_t;
1945 HashTableConstIteratorSafe();
1953 template <
typename Alloc >
1954 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
1969 template <
typename Alloc >
1970 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab,
1977 HashTableConstIteratorSafe(
const HashTableConstIteratorSafe< Key, Val >& from);
1983 explicit HashTableConstIteratorSafe(
1984 const HashTableConstIterator< Key, Val >& from);
1990 HashTableConstIteratorSafe(HashTableConstIteratorSafe< Key, Val >&& from);
1995 ~HashTableConstIteratorSafe()
noexcept;
2009 const key_type& key()
const;
2018 const mapped_type& val()
const;
2027 void clear()
noexcept;
2040 HashTableConstIteratorSafe< Key, Val >&
2041 operator=(
const HashTableConstIteratorSafe< Key, Val >& from);
2048 HashTableConstIteratorSafe< Key, Val >&
2049 operator=(
const HashTableConstIterator< Key, Val >& from);
2056 HashTableConstIteratorSafe< Key, Val >&
2057 operator=(HashTableConstIteratorSafe< Key, Val >&& from)
noexcept;
2074 HashTableConstIteratorSafe< Key, Val >& operator++()
noexcept;
2082 HashTableConstIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2091 HashTableConstIteratorSafe< Key, Val > operator+(Size i)
const;
2099 const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2107 const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2115 const value_type& operator*()
const;
2126 template <
typename K,
typename V,
typename A >
2127 friend class HashTable;
2130 const HashTable< Key, Val >* table__{
nullptr};
2136 Size index__{Size(0)};
2139 HashTableBucket< Key, Val >* bucket__{
nullptr};
2149 HashTableBucket< Key, Val >* next_bucket__{
nullptr};
2152 HashTableBucket< Key, Val >* getBucket__()
const noexcept;
2160 Size getIndex__()
const noexcept;
2165 void removeFromSafeList__()
const;
2170 void insertIntoSafeList__()
const;
2223 template <
typename Key,
typename Val >
2224 class HashTableIteratorSafe:
public HashTableConstIteratorSafe< Key, Val > {
2228 using iterator_category = std::forward_iterator_tag;
2229 using key_type = Key;
2230 using mapped_type = Val;
2231 using value_type = std::pair<
const Key, Val >;
2232 using reference = value_type&;
2233 using const_reference =
const value_type&;
2234 using pointer = value_type*;
2235 using const_pointer =
const value_type*;
2236 using difference_type = std::ptrdiff_t;
2247 HashTableIteratorSafe();
2254 template <
typename Alloc >
2255 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
2269 template <
typename Alloc >
2270 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2277 HashTableIteratorSafe(
const HashTableIteratorSafe< Key, Val >& from);
2284 explicit HashTableIteratorSafe(
const HashTableIterator< Key, Val >& from);
2291 HashTableIteratorSafe(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2296 ~HashTableIteratorSafe()
noexcept;
2306 using HashTableConstIteratorSafe< Key, Val >::key;
2307 using HashTableConstIteratorSafe< Key, Val >::val;
2308 using HashTableConstIteratorSafe< Key, Val >::clear;
2330 HashTableIteratorSafe< Key, Val >&
2331 operator=(
const HashTableIteratorSafe< Key, Val >& from);
2338 HashTableIteratorSafe< Key, Val >&
2339 operator=(
const HashTableIterator< Key, Val >& from);
2346 HashTableIteratorSafe< Key, Val >&
2347 operator=(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2363 HashTableIteratorSafe< Key, Val >& operator++()
noexcept;
2370 HashTableIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2378 HashTableIteratorSafe< Key, Val > operator+(Size i)
const;
2386 bool operator!=(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2394 bool operator==(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2402 value_type& operator*();
2411 const value_type& operator*()
const;
2468 template <
typename Key,
typename Val >
2469 class HashTableConstIterator {
2473 using iterator_category = std::forward_iterator_tag;
2474 using key_type = Key;
2475 using mapped_type = Val;
2476 using value_type = std::pair<
const Key, Val >;
2477 using reference = value_type&;
2478 using const_reference =
const value_type&;
2479 using pointer = value_type*;
2480 using const_pointer =
const value_type*;
2481 using difference_type = std::ptrdiff_t;
2492 HashTableConstIterator()
noexcept;
2500 template <
typename Alloc >
2501 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2514 template <
typename Alloc >
2515 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2521 HashTableConstIterator(
2522 const HashTableConstIterator< Key, Val >& from)
noexcept;
2528 HashTableConstIterator(HashTableConstIterator< Key, Val >&& from)
noexcept;
2533 ~HashTableConstIterator()
noexcept;
2552 const key_type& key()
const;
2563 const mapped_type& val()
const;
2569 void clear()
noexcept;
2582 HashTableConstIterator< Key, Val >&
2583 operator=(
const HashTableConstIterator< Key, Val >& from)
noexcept;
2590 HashTableConstIterator< Key, Val >&
2591 operator=(HashTableConstIterator< Key, Val >&& from)
noexcept;
2610 HashTableConstIterator< Key, Val >& operator++()
noexcept;
2617 HashTableConstIterator< Key, Val >& operator+=(Size i)
noexcept;
2626 HashTableConstIterator< Key, Val > operator+(Size i)
const noexcept;
2634 bool operator!=(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2642 bool operator==(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2654 const value_type& operator*()
const;
2669 template <
typename K,
typename V,
typename A >
2670 friend class HashTable;
2673 friend class HashTableConstIteratorSafe< Key, Val >;
2676 const HashTable< Key, Val >* table__{
nullptr};
2682 Size index__{Size(0)};
2685 typename HashTable< Key, Val >::Bucket* bucket__{
nullptr};
2691 typename HashTable< Key, Val >::Bucket* getBucket__()
const noexcept;
2699 Size getIndex__()
const noexcept;
2753 template <
typename Key,
typename Val >
2754 class HashTableIterator:
public HashTableConstIterator< Key, Val > {
2758 using iterator_category = std::forward_iterator_tag;
2759 using key_type = Key;
2760 using mapped_type = Val;
2761 using value_type = std::pair<
const Key, Val >;
2762 using reference = value_type&;
2763 using const_reference =
const value_type&;
2764 using pointer = value_type*;
2765 using const_pointer =
const value_type*;
2766 using difference_type = std::ptrdiff_t;
2777 HashTableIterator()
noexcept;
2785 template <
typename Alloc >
2786 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2801 template <
typename Alloc >
2802 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2808 HashTableIterator(
const HashTableIterator< Key, Val >& from)
noexcept;
2814 HashTableIterator(HashTableIterator< Key, Val >&& from)
noexcept;
2819 ~HashTableIterator()
noexcept;
2829 using HashTableConstIterator< Key, Val >::key;
2830 using HashTableConstIterator< Key, Val >::val;
2831 using HashTableConstIterator< Key, Val >::clear;
2856 HashTableIterator< Key, Val >&
2857 operator=(
const HashTableIterator< Key, Val >& from)
noexcept;
2864 HashTableIterator< Key, Val >&
2865 operator=(HashTableIterator< Key, Val >&& from)
noexcept;
2883 HashTableIterator< Key, Val >& operator++()
noexcept;
2890 HashTableIterator< Key, Val >& operator+=(Size i)
noexcept;
2897 HashTableIterator< Key, Val > operator+(Size i)
const noexcept;
2905 bool operator!=(
const HashTableIterator< Key, Val >& from)
const noexcept;
2913 bool operator==(
const HashTableIterator< Key, Val >& from)
const noexcept;
2924 value_type& operator*();
2935 const value_type& operator*()
const;
2943 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2944 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2945 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2946 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2947 extern template class gum::HashTable<
int,
int >;
2952 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2953 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2954 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2955 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2956 extern template class gum::HashTable<
int, std::string >;
2961 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2962 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2963 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2964 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2965 extern template class gum::HashTable< std::string, std::string >;
2970 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2971 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2972 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2973 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2974 extern template class gum::HashTable< std::string,
int >;
2982 #include <agrum/tools/core/hashTable_tpl.h>