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,
const HashTableList< Key, Val, Alloc >& list);
138 template <
typename Key,
typename Val,
typename Alloc >
139 std::ostream& operator<<(std::ostream& s,
const HashTableList< Key*, Val, Alloc >& list);
155 template <
typename Key,
typename Val,
typename Alloc >
156 std::ostream& operator<<(std::ostream& s,
const HashTable< Key, Val, Alloc >& table);
174 template <
typename Key,
typename Val,
typename Alloc >
175 std::ostream& operator<<(std::ostream& s,
const HashTable< Key*, Val, Alloc >& table);
196 template <
typename Key,
typename Val >
197 struct HashTableBucket {
199 std::pair<
const Key, Val > pair;
202 HashTableBucket< Key, Val >* prev{
nullptr};
205 HashTableBucket< Key, Val >* next{
nullptr};
223 HashTableBucket(
const HashTableBucket< Key, Val >& from) : pair{from.pair} {}
230 HashTableBucket(
const Key& k,
const Val& v) : pair{k, v} {}
237 HashTableBucket(Key&& k, Val&& v) : pair{std::move(k), std::move(v)} {}
243 HashTableBucket(
const std::pair<
const Key, Val >& p) : pair(p) {}
249 HashTableBucket(std::pair<
const Key, Val >&& p) : pair(std::move(p)) {}
257 template <
typename... Args >
258 HashTableBucket(Emplace e, Args&&... args) :
260 pair(std::forward< Args >(args)...) {}
265 ~HashTableBucket() {}
271 std::pair<
const Key, Val >& elt() {
return pair; }
277 Key& key() {
return const_cast< Key& >(pair.first); }
283 Val& val() {
return pair.second; }
300 template <
typename Key,
typename Val,
typename Alloc >
301 class HashTableList {
305 using key_type = Key;
306 using mapped_type = Val;
307 using value_type = std::pair<
const Key, Val >;
308 using reference = value_type&;
309 using const_reference =
const value_type&;
310 using pointer = value_type*;
311 using const_pointer =
const value_type*;
312 using size_type = Size;
313 using allocator_type = Alloc;
314 using Bucket = HashTableBucket< Key, Val >;
318 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
334 HashTableList(BucketAllocator* allocator =
nullptr)
noexcept;
347 HashTableList(
const HashTableList< Key, Val, Alloc >& from);
353 HashTableList(HashTableList< Key, Val, Alloc >&& from)
noexcept;
383 HashTableList< Key, Val, Alloc >& operator=(
const HashTableList< Key, Val, Alloc >& from);
402 template <
typename OtherAlloc >
403 HashTableList< Key, Val, Alloc >& operator=(
const HashTableList< Key, Val, OtherAlloc >& from);
411 HashTableList< Key, Val, Alloc >& operator=(HashTableList< Key, Val, Alloc >&& from)
noexcept;
427 value_type& at(Size i);
437 const value_type& at(Size i)
const;
445 mapped_type& operator[](
const key_type& key);
453 const mapped_type& operator[](
const key_type& key)
const;
462 bool exists(
const key_type& key)
const;
470 void insert(Bucket* new_elt)
noexcept;
476 void erase(Bucket* ptr);
487 bool empty()
const noexcept;
496 Bucket* bucket(
const Key& key)
const;
502 void setAllocator(BucketAllocator& alloc);
509 template <
typename K,
typename V,
typename A >
510 friend class HashTableList;
511 friend class HashTable< Key, Val, Alloc >;
512 friend class HashTableIterator< Key, Val >;
513 friend class HashTableConstIterator< Key, Val >;
514 friend class HashTableIteratorSafe< Key, Val >;
515 friend class HashTableConstIteratorSafe< Key, Val >;
516 friend std::ostream& operator<<<>(std::ostream&,
const HashTableList< Key, Val, Alloc >&);
517 friend std::ostream& operator<<<>(std::ostream&,
const HashTableList< Key*, Val, Alloc >&);
518 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key, Val, Alloc >&);
519 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key*, Val, Alloc >&);
523 HashTableBucket< Key, Val >* _deb_list_{
nullptr};
526 HashTableBucket< Key, Val >* _end_list_{
nullptr};
529 Size _nb_elements_{Size(0)};
532 mutable BucketAllocator* _alloc_bucket_;
544 template <
typename OtherAlloc >
545 void _copy_(
const HashTableList< Key, Val, OtherAlloc >& from);
665 template <
typename Key,
typename Val,
typename Alloc = std::allocator< std::pair< Key, Val > > >
670 using key_type = Key;
671 using mapped_type = Val;
672 using value_type = std::pair<
const Key, Val >;
673 using reference = value_type&;
674 using const_reference =
const value_type&;
675 using pointer = value_type*;
676 using const_pointer =
const value_type*;
677 using size_type = Size;
678 using difference_type = std::ptrdiff_t;
679 using allocator_type = Alloc;
680 using iterator = HashTableIterator< Key, Val >;
681 using const_iterator = HashTableConstIterator< Key, Val >;
682 using iterator_safe = HashTableIteratorSafe< Key, Val >;
683 using const_iterator_safe = HashTableConstIteratorSafe< Key, Val >;
687 using Bucket = HashTableBucket< Key, Val >;
690 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
714 explicit HashTable(Size size_param = HashTableConst::default_size,
715 bool resize_pol = HashTableConst::default_resize_policy,
716 bool key_uniqueness_pol = HashTableConst::default_uniqueness_policy);
722 explicit HashTable(std::initializer_list< std::pair< Key, Val > > list);
736 HashTable(
const HashTable< Key, Val, Alloc >& from);
750 template <
typename OtherAlloc >
751 HashTable(
const HashTable< Key, Val, OtherAlloc >& from);
757 HashTable(HashTable< Key, Val, Alloc >&& from);
780 const iterator& end()
noexcept;
794 const const_iterator& end()
const noexcept;
808 const const_iterator& cend()
const noexcept;
836 const_iterator begin()
const;
850 const_iterator cbegin()
const;
861 const iterator_safe& endSafe()
noexcept;
874 const const_iterator_safe& endSafe()
const noexcept;
887 const const_iterator_safe& cendSafe()
const noexcept;
900 iterator_safe beginSafe();
913 const_iterator_safe beginSafe()
const;
926 const_iterator_safe cbeginSafe()
const;
965 static const iterator& end4Statics();
1004 static const const_iterator& constEnd4Statics();
1043 static const iterator_safe& endSafe4Statics();
1082 static const const_iterator_safe& constEndSafe4Statics();
1102 HashTable< Key, Val, Alloc >& operator=(
const HashTable< Key, Val, Alloc >& from);
1116 template <
typename OtherAlloc >
1117 HashTable< Key, Val, Alloc >& operator=(
const HashTable< Key, Val, OtherAlloc >& from);
1125 HashTable< Key, Val, Alloc >& operator=(HashTable< Key, Val, Alloc >&& from);
1138 Val& operator[](
const Key& key);
1144 const Val& operator[](
const Key& key)
const;
1157 template <
typename OtherAlloc >
1158 bool operator==(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1172 template <
typename OtherAlloc >
1173 bool operator!=(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1190 Size capacity()
const noexcept;
1210 void resize(Size new_size);
1229 void setResizePolicy(
const bool new_policy)
noexcept;
1235 bool resizePolicy()
const noexcept;
1252 void setKeyUniquenessPolicy(
const bool new_policy)
noexcept;
1258 bool keyUniquenessPolicy()
const noexcept;
1273 Size size()
const noexcept;
1285 bool exists(
const Key& key)
const;
1307 value_type& insert(
const Key& key,
const Val& val);
1327 value_type& insert(Key&& key, Val&& val);
1348 value_type& insert(
const std::pair< Key, Val >& elt);
1367 value_type& insert(std::pair< Key, Val >&& elt);
1385 template <
typename... Args >
1386 value_type& emplace(Args&&... args);
1402 mapped_type& getWithDefault(
const Key& key,
const Val& default_value);
1418 mapped_type& getWithDefault(Key&& key, Val&& default_value);
1431 void set(
const Key& key,
const Val& default_value);
1442 void reset(
const Key& key);
1458 void erase(
const Key& key);
1470 void erase(
const iterator_safe& iter);
1482 void erase(
const const_iterator_safe& iter);
1500 void eraseByVal(
const Val& val);
1512 const Key& keyByVal(
const Val& val)
const;
1526 const Key& key(
const Key& key)
const;
1540 void eraseAllVal(
const Val& val);
1556 bool empty()
const noexcept;
1578 template <
typename Mount,
1580 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1581 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val),
1582 Size size = Size(0),
1583 bool resize_pol = HashTableConst::default_resize_policy,
1584 bool key_uniqueness_pol
1585 = HashTableConst::default_uniqueness_policy)
const;
1607 template <
typename Mount,
1609 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1610 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val&),
1611 Size size = Size(0),
1612 bool resize_pol = HashTableConst::default_resize_policy,
1613 bool key_uniqueness_pol
1614 = HashTableConst::default_uniqueness_policy)
const;
1636 template <
typename Mount,
1638 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1639 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(
const Val&),
1640 Size size = Size(0),
1641 bool resize_pol = HashTableConst::default_resize_policy,
1642 bool key_uniqueness_pol
1643 = HashTableConst::default_uniqueness_policy)
const;
1667 template <
typename Mount,
1669 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1670 HashTable< Key, Mount, OtherAlloc > map(
const Mount& val,
1671 Size size = Size(0),
1672 bool resize_pol = HashTableConst::default_resize_policy,
1673 bool key_uniqueness_pol
1674 = HashTableConst::default_uniqueness_policy)
const;
1681 template <
typename K,
typename V,
typename A >
1682 friend class HashTable;
1683 friend class HashTableIterator< Key, Val >;
1684 friend class HashTableConstIterator< Key, Val >;
1685 friend class HashTableIteratorSafe< Key, Val >;
1686 friend class HashTableConstIteratorSafe< Key, Val >;
1688 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key, Val, Alloc >&);
1689 friend std::ostream& operator<<<>(std::ostream& s,
const HashTable< Key*, Val, Alloc >& table);
1692 template <
typename T1,
typename T2,
typename A >
1693 friend class Bijection;
1700 std::vector< HashTableList< Key, Val, Alloc > > _nodes_;
1706 Size _nb_elements_{Size(0)};
1709 HashFunc< Key > _hash_func_;
1712 bool _resize_policy_{
true};
1715 bool _key_uniqueness_policy_{
true};
1731 mutable Size _begin_index_{std::numeric_limits< Size >::max()};
1734 mutable std::vector< HashTableConstIteratorSafe< Key, Val >* > _safe_iterators_;
1744 BucketAllocator _alloc_;
1747 void _erase_(HashTableBucket< Key, Val >* bucket, Size index);
1764 template <
typename OtherAlloc >
1765 void _copy_(
const HashTable< Key, Val, OtherAlloc >& table);
1771 void _create_(Size size);
1776 void _clearIterators_();
1794 void _insert_(Bucket* bucket);
1812 class HashTableIteratorStaticEnd {
1815 static const HashTableIterator<
int,
int >* _HashTableIterEnd_;
1818 static const HashTableIteratorSafe<
int,
int >* _HashTableIterEndSafe_;
1824 static const HashTableIterator<
int,
int >* end4Statics();
1830 static const HashTableConstIterator<
int,
int >* constEnd4Statics();
1837 static const HashTableIteratorSafe<
int,
int >* endSafe4Statics();
1844 static const HashTableConstIteratorSafe<
int,
int >* constEndSafe4Statics();
1847 template <
typename Key,
typename Val,
typename Alloc >
1848 friend class HashTable;
1898 template <
typename Key,
typename Val >
1899 class HashTableConstIteratorSafe {
1903 using iterator_category = std::forward_iterator_tag;
1904 using key_type = Key;
1905 using mapped_type = Val;
1906 using value_type = std::pair<
const Key, Val >;
1907 using reference = value_type&;
1908 using const_reference =
const value_type&;
1909 using pointer = value_type*;
1910 using const_pointer =
const value_type*;
1911 using difference_type = std::ptrdiff_t;
1922 HashTableConstIteratorSafe();
1930 template <
typename Alloc >
1931 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
1946 template <
typename Alloc >
1947 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
1953 HashTableConstIteratorSafe(
const HashTableConstIteratorSafe< Key, Val >& from);
1959 explicit HashTableConstIteratorSafe(
const HashTableConstIterator< Key, Val >& from);
1965 HashTableConstIteratorSafe(HashTableConstIteratorSafe< Key, Val >&& from);
1970 ~HashTableConstIteratorSafe()
noexcept;
1984 const key_type& key()
const;
1993 const mapped_type& val()
const;
2002 void clear()
noexcept;
2015 HashTableConstIteratorSafe< Key, Val >&
2016 operator=(
const HashTableConstIteratorSafe< Key, Val >& from);
2023 HashTableConstIteratorSafe< Key, Val >&
2024 operator=(
const HashTableConstIterator< Key, Val >& from);
2031 HashTableConstIteratorSafe< Key, Val >&
2032 operator=(HashTableConstIteratorSafe< Key, Val >&& from)
noexcept;
2049 HashTableConstIteratorSafe< Key, Val >& operator++()
noexcept;
2057 HashTableConstIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2066 HashTableConstIteratorSafe< Key, Val > operator+(Size i)
const;
2073 bool operator!=(
const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2080 bool operator==(
const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2088 const value_type& operator*()
const;
2099 template <
typename K,
typename V,
typename A >
2100 friend class HashTable;
2103 const HashTable< Key, Val >* _table_{
nullptr};
2109 Size _index_{Size(0)};
2112 HashTableBucket< Key, Val >* _bucket_{
nullptr};
2122 HashTableBucket< Key, Val >* _next_bucket_{
nullptr};
2125 HashTableBucket< Key, Val >* _getBucket_()
const noexcept;
2133 Size _getIndex_()
const noexcept;
2138 void _removeFromSafeList_()
const;
2143 void _insertIntoSafeList_()
const;
2196 template <
typename Key,
typename Val >
2197 class HashTableIteratorSafe:
public HashTableConstIteratorSafe< Key, Val > {
2201 using iterator_category = std::forward_iterator_tag;
2202 using key_type = Key;
2203 using mapped_type = Val;
2204 using value_type = std::pair<
const Key, Val >;
2205 using reference = value_type&;
2206 using const_reference =
const value_type&;
2207 using pointer = value_type*;
2208 using const_pointer =
const value_type*;
2209 using difference_type = std::ptrdiff_t;
2220 HashTableIteratorSafe();
2227 template <
typename Alloc >
2228 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
2242 template <
typename Alloc >
2243 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2250 HashTableIteratorSafe(
const HashTableIteratorSafe< Key, Val >& from);
2257 explicit HashTableIteratorSafe(
const HashTableIterator< Key, Val >& from);
2264 HashTableIteratorSafe(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2269 ~HashTableIteratorSafe()
noexcept;
2279 using HashTableConstIteratorSafe< Key, Val >::key;
2280 using HashTableConstIteratorSafe< Key, Val >::val;
2281 using HashTableConstIteratorSafe< Key, Val >::clear;
2303 HashTableIteratorSafe< Key, Val >& operator=(
const HashTableIteratorSafe< Key, Val >& from);
2310 HashTableIteratorSafe< Key, Val >& operator=(
const HashTableIterator< Key, Val >& from);
2317 HashTableIteratorSafe< Key, Val >& operator=(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2333 HashTableIteratorSafe< Key, Val >& operator++()
noexcept;
2340 HashTableIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2348 HashTableIteratorSafe< Key, Val > operator+(Size i)
const;
2356 bool operator!=(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2364 bool operator==(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2372 value_type& operator*();
2381 const value_type& operator*()
const;
2438 template <
typename Key,
typename Val >
2439 class HashTableConstIterator {
2443 using iterator_category = std::forward_iterator_tag;
2444 using key_type = Key;
2445 using mapped_type = Val;
2446 using value_type = std::pair<
const Key, Val >;
2447 using reference = value_type&;
2448 using const_reference =
const value_type&;
2449 using pointer = value_type*;
2450 using const_pointer =
const value_type*;
2451 using difference_type = std::ptrdiff_t;
2462 HashTableConstIterator()
noexcept;
2470 template <
typename Alloc >
2471 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2484 template <
typename Alloc >
2485 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2491 HashTableConstIterator(
const HashTableConstIterator< Key, Val >& from)
noexcept;
2497 HashTableConstIterator(HashTableConstIterator< Key, Val >&& from)
noexcept;
2502 ~HashTableConstIterator()
noexcept;
2521 const key_type& key()
const;
2532 const mapped_type& val()
const;
2538 void clear()
noexcept;
2551 HashTableConstIterator< Key, Val >&
2552 operator=(
const HashTableConstIterator< Key, Val >& from)
noexcept;
2559 HashTableConstIterator< Key, Val >&
2560 operator=(HashTableConstIterator< Key, Val >&& from)
noexcept;
2579 HashTableConstIterator< Key, Val >& operator++()
noexcept;
2586 HashTableConstIterator< Key, Val >& operator+=(Size i)
noexcept;
2595 HashTableConstIterator< Key, Val > operator+(Size i)
const noexcept;
2603 bool operator!=(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2611 bool operator==(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2623 const value_type& operator*()
const;
2638 template <
typename K,
typename V,
typename A >
2639 friend class HashTable;
2642 friend class HashTableConstIteratorSafe< Key, Val >;
2645 const HashTable< Key, Val >* _table_{
nullptr};
2651 Size _index_{Size(0)};
2654 typename HashTable< Key, Val >::Bucket* _bucket_{
nullptr};
2660 typename HashTable< Key, Val >::Bucket* _getBucket_()
const noexcept;
2668 Size _getIndex_()
const noexcept;
2722 template <
typename Key,
typename Val >
2723 class HashTableIterator:
public HashTableConstIterator< Key, Val > {
2727 using iterator_category = std::forward_iterator_tag;
2728 using key_type = Key;
2729 using mapped_type = Val;
2730 using value_type = std::pair<
const Key, Val >;
2731 using reference = value_type&;
2732 using const_reference =
const value_type&;
2733 using pointer = value_type*;
2734 using const_pointer =
const value_type*;
2735 using difference_type = std::ptrdiff_t;
2746 HashTableIterator()
noexcept;
2754 template <
typename Alloc >
2755 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2770 template <
typename Alloc >
2771 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2777 HashTableIterator(
const HashTableIterator< Key, Val >& from)
noexcept;
2783 HashTableIterator(HashTableIterator< Key, Val >&& from)
noexcept;
2788 ~HashTableIterator()
noexcept;
2798 using HashTableConstIterator< Key, Val >::key;
2799 using HashTableConstIterator< Key, Val >::val;
2800 using HashTableConstIterator< Key, Val >::clear;
2825 HashTableIterator< Key, Val >& operator=(
const HashTableIterator< Key, Val >& from)
noexcept;
2832 HashTableIterator< Key, Val >& operator=(HashTableIterator< Key, Val >&& from)
noexcept;
2850 HashTableIterator< Key, Val >& operator++()
noexcept;
2857 HashTableIterator< Key, Val >& operator+=(Size i)
noexcept;
2864 HashTableIterator< Key, Val > operator+(Size i)
const noexcept;
2872 bool operator!=(
const HashTableIterator< Key, Val >& from)
const noexcept;
2880 bool operator==(
const HashTableIterator< Key, Val >& from)
const noexcept;
2891 value_type& operator*();
2902 const value_type& operator*()
const;
2910 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2911 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2912 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2913 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2914 extern template class gum::HashTable<
int,
int >;
2919 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2920 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2921 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2922 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2923 extern template class gum::HashTable<
int, std::string >;
2928 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2929 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2930 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2931 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2932 extern template class gum::HashTable< std::string, std::string >;
2937 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2938 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2939 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2940 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2941 extern template class gum::HashTable< std::string,
int >;
2949 #include <agrum/tools/core/hashTable_tpl.h>