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};
225 HashTableBucket(
const HashTableBucket< Key, Val >& from) : pair{from.pair} {}
232 HashTableBucket(
const Key& k,
const Val& v) : pair{k, v} {}
239 HashTableBucket(Key&& k, Val&& v) : pair{std::move(k), std::move(v)} {}
245 HashTableBucket(
const std::pair<
const Key, Val >& p) : pair(p) {}
251 HashTableBucket(std::pair<
const Key, Val >&& p) : pair(std::move(p)) {}
259 template <
typename... Args >
260 HashTableBucket(Emplace e, Args&&... args) :
262 pair(std::forward< Args >(args)...) {}
267 ~HashTableBucket() {}
273 std::pair<
const Key, Val >& elt() {
return pair; }
279 Key& key() {
return const_cast< Key& >(pair.first); }
285 Val& val() {
return pair.second; }
302 template <
typename Key,
typename Val,
typename Alloc >
303 class HashTableList {
307 using key_type = Key;
308 using mapped_type = Val;
309 using value_type = std::pair<
const Key, Val >;
310 using reference = value_type&;
311 using const_reference =
const value_type&;
312 using pointer = value_type*;
313 using const_pointer =
const value_type*;
314 using size_type = Size;
315 using allocator_type = Alloc;
316 using Bucket = HashTableBucket< Key, Val >;
320 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
336 HashTableList(BucketAllocator* allocator =
nullptr)
noexcept;
349 HashTableList(
const HashTableList< Key, Val, Alloc >& from);
355 HashTableList(HashTableList< Key, Val, Alloc >&& from)
noexcept;
385 HashTableList< Key, Val, Alloc >& operator=(
const HashTableList< Key, Val, Alloc >& from);
404 template <
typename OtherAlloc >
405 HashTableList< Key, Val, Alloc >& operator=(
const HashTableList< Key, Val, OtherAlloc >& from);
413 HashTableList< Key, Val, Alloc >& operator=(HashTableList< Key, Val, Alloc >&& from)
noexcept;
429 value_type& at(Size i);
439 const value_type& at(Size i)
const;
447 mapped_type& operator[](
const key_type& key);
455 const mapped_type& operator[](
const key_type& key)
const;
464 bool exists(
const key_type& key)
const;
472 void insert(Bucket* new_elt)
noexcept;
478 void erase(Bucket* ptr);
489 bool empty()
const noexcept;
498 Bucket* bucket(
const Key& key)
const;
504 void setAllocator(BucketAllocator& alloc);
511 template <
typename K,
typename V,
typename A >
512 friend class HashTableList;
513 friend class HashTable< Key, Val, Alloc >;
514 friend class HashTableIterator< Key, Val >;
515 friend class HashTableConstIterator< Key, Val >;
516 friend class HashTableIteratorSafe< Key, Val >;
517 friend class HashTableConstIteratorSafe< Key, Val >;
518 friend std::ostream& operator<<<>(std::ostream&,
const HashTableList< Key, Val, Alloc >&);
519 friend std::ostream& operator<<<>(std::ostream&,
const HashTableList< Key*, Val, Alloc >&);
520 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key, Val, Alloc >&);
521 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key*, Val, Alloc >&);
525 HashTableBucket< Key, Val >* _deb_list_{
nullptr};
528 HashTableBucket< Key, Val >* _end_list_{
nullptr};
531 Size _nb_elements_{Size(0)};
534 mutable BucketAllocator* _alloc_bucket_;
546 template <
typename OtherAlloc >
547 void _copy_(
const HashTableList< Key, Val, OtherAlloc >& from);
667 template <
typename Key,
typename Val,
typename Alloc = std::allocator< std::pair< Key, Val > > >
672 using key_type = Key;
673 using mapped_type = Val;
674 using value_type = std::pair<
const Key, Val >;
675 using reference = value_type&;
676 using const_reference =
const value_type&;
677 using pointer = value_type*;
678 using const_pointer =
const value_type*;
679 using size_type = Size;
680 using difference_type = std::ptrdiff_t;
681 using allocator_type = Alloc;
682 using iterator = HashTableIterator< Key, Val >;
683 using const_iterator = HashTableConstIterator< Key, Val >;
684 using iterator_safe = HashTableIteratorSafe< Key, Val >;
685 using const_iterator_safe = HashTableConstIteratorSafe< Key, Val >;
689 using Bucket = HashTableBucket< Key, Val >;
692 using BucketAllocator =
typename Alloc::
template rebind< Bucket >::other;
716 explicit HashTable(Size size_param = HashTableConst::default_size,
717 bool resize_pol = HashTableConst::default_resize_policy,
718 bool key_uniqueness_pol = HashTableConst::default_uniqueness_policy);
724 explicit HashTable(std::initializer_list< std::pair< Key, Val > > list);
738 HashTable(
const HashTable< Key, Val, Alloc >& from);
752 template <
typename OtherAlloc >
753 HashTable(
const HashTable< Key, Val, OtherAlloc >& from);
759 HashTable(HashTable< Key, Val, Alloc >&& from);
782 const iterator& end()
noexcept;
796 const const_iterator& end()
const noexcept;
810 const const_iterator& cend()
const noexcept;
838 const_iterator begin()
const;
852 const_iterator cbegin()
const;
863 const iterator_safe& endSafe()
noexcept;
876 const const_iterator_safe& endSafe()
const noexcept;
889 const const_iterator_safe& cendSafe()
const noexcept;
902 iterator_safe beginSafe();
915 const_iterator_safe beginSafe()
const;
928 const_iterator_safe cbeginSafe()
const;
967 static const iterator& end4Statics();
1006 static const const_iterator& constEnd4Statics();
1045 static const iterator_safe& endSafe4Statics();
1084 static const const_iterator_safe& constEndSafe4Statics();
1104 HashTable< Key, Val, Alloc >& operator=(
const HashTable< Key, Val, Alloc >& from);
1118 template <
typename OtherAlloc >
1119 HashTable< Key, Val, Alloc >& operator=(
const HashTable< Key, Val, OtherAlloc >& from);
1127 HashTable< Key, Val, Alloc >& operator=(HashTable< Key, Val, Alloc >&& from);
1140 Val& operator[](
const Key& key);
1146 const Val& operator[](
const Key& key)
const;
1159 template <
typename OtherAlloc >
1160 bool operator==(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1174 template <
typename OtherAlloc >
1175 bool operator!=(
const HashTable< Key, Val, OtherAlloc >& from)
const;
1192 Size capacity()
const noexcept;
1212 void resize(Size new_size);
1231 void setResizePolicy(
const bool new_policy)
noexcept;
1237 bool resizePolicy()
const noexcept;
1254 void setKeyUniquenessPolicy(
const bool new_policy)
noexcept;
1260 bool keyUniquenessPolicy()
const noexcept;
1275 Size size()
const noexcept;
1287 bool exists(
const Key& key)
const;
1309 value_type& insert(
const Key& key,
const Val& val);
1329 value_type& insert(Key&& key, Val&& val);
1350 value_type& insert(
const std::pair< Key, Val >& elt);
1369 value_type& insert(std::pair< Key, Val >&& elt);
1387 template <
typename... Args >
1388 value_type& emplace(Args&&... args);
1404 mapped_type& getWithDefault(
const Key& key,
const Val& default_value);
1420 mapped_type& getWithDefault(Key&& key, Val&& default_value);
1433 void set(
const Key& key,
const Val& default_value);
1444 void reset(
const Key& key);
1460 void erase(
const Key& key);
1472 void erase(
const iterator_safe& iter);
1484 void erase(
const const_iterator_safe& iter);
1502 void eraseByVal(
const Val& val);
1514 const Key& keyByVal(
const Val& val)
const;
1528 const Key& key(
const Key& key)
const;
1542 void eraseAllVal(
const Val& val);
1558 bool empty()
const noexcept;
1580 template <
typename Mount,
1582 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1583 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val),
1584 Size size = Size(0),
1585 bool resize_pol = HashTableConst::default_resize_policy,
1586 bool key_uniqueness_pol
1587 = HashTableConst::default_uniqueness_policy)
const;
1609 template <
typename Mount,
1611 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1612 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val&),
1613 Size size = Size(0),
1614 bool resize_pol = HashTableConst::default_resize_policy,
1615 bool key_uniqueness_pol
1616 = HashTableConst::default_uniqueness_policy)
const;
1638 template <
typename Mount,
1640 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1641 HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(
const Val&),
1642 Size size = Size(0),
1643 bool resize_pol = HashTableConst::default_resize_policy,
1644 bool key_uniqueness_pol
1645 = HashTableConst::default_uniqueness_policy)
const;
1669 template <
typename Mount,
1671 =
typename Alloc::
template rebind< std::pair< Key, Mount > >::other >
1672 HashTable< Key, Mount, OtherAlloc > map(
const Mount& val,
1673 Size size = Size(0),
1674 bool resize_pol = HashTableConst::default_resize_policy,
1675 bool key_uniqueness_pol
1676 = HashTableConst::default_uniqueness_policy)
const;
1683 template <
typename K,
typename V,
typename A >
1684 friend class HashTable;
1685 friend class HashTableIterator< Key, Val >;
1686 friend class HashTableConstIterator< Key, Val >;
1687 friend class HashTableIteratorSafe< Key, Val >;
1688 friend class HashTableConstIteratorSafe< Key, Val >;
1690 friend std::ostream& operator<<<>(std::ostream&,
const HashTable< Key, Val, Alloc >&);
1691 friend std::ostream& operator<<<>(std::ostream& s,
const HashTable< Key*, Val, Alloc >& table);
1694 template <
typename T1,
typename T2,
typename A >
1695 friend class Bijection;
1702 std::vector< HashTableList< Key, Val, Alloc > > _nodes_;
1708 Size _nb_elements_{Size(0)};
1711 HashFunc< Key > _hash_func_;
1714 bool _resize_policy_{
true};
1717 bool _key_uniqueness_policy_{
true};
1733 mutable Size _begin_index_{std::numeric_limits< Size >::max()};
1736 mutable std::vector< HashTableConstIteratorSafe< Key, Val >* > _safe_iterators_;
1746 BucketAllocator _alloc_;
1749 void _erase_(HashTableBucket< Key, Val >* bucket, Size index);
1766 template <
typename OtherAlloc >
1767 void _copy_(
const HashTable< Key, Val, OtherAlloc >& table);
1773 void _create_(Size size);
1778 void _clearIterators_();
1796 void _insert_(Bucket* bucket);
1814 class HashTableIteratorStaticEnd {
1817 static const HashTableIterator<
int,
int >* _HashTableIterEnd_;
1820 static const HashTableIteratorSafe<
int,
int >* _HashTableIterEndSafe_;
1826 static const HashTableIterator<
int,
int >* end4Statics();
1832 static const HashTableConstIterator<
int,
int >* constEnd4Statics();
1839 static const HashTableIteratorSafe<
int,
int >* endSafe4Statics();
1846 static const HashTableConstIteratorSafe<
int,
int >* constEndSafe4Statics();
1849 template <
typename Key,
typename Val,
typename Alloc >
1850 friend class HashTable;
1900 template <
typename Key,
typename Val >
1901 class HashTableConstIteratorSafe {
1905 using iterator_category = std::forward_iterator_tag;
1906 using key_type = Key;
1907 using mapped_type = Val;
1908 using value_type = std::pair<
const Key, Val >;
1909 using reference = value_type&;
1910 using const_reference =
const value_type&;
1911 using pointer = value_type*;
1912 using const_pointer =
const value_type*;
1913 using difference_type = std::ptrdiff_t;
1924 HashTableConstIteratorSafe();
1932 template <
typename Alloc >
1933 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
1948 template <
typename Alloc >
1949 HashTableConstIteratorSafe(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
1955 HashTableConstIteratorSafe(
const HashTableConstIteratorSafe< Key, Val >& from);
1961 explicit HashTableConstIteratorSafe(
const HashTableConstIterator< Key, Val >& from);
1967 HashTableConstIteratorSafe(HashTableConstIteratorSafe< Key, Val >&& from);
1972 ~HashTableConstIteratorSafe()
noexcept;
1986 const key_type& key()
const;
1995 const mapped_type& val()
const;
2004 void clear()
noexcept;
2017 HashTableConstIteratorSafe< Key, Val >&
2018 operator=(
const HashTableConstIteratorSafe< Key, Val >& from);
2025 HashTableConstIteratorSafe< Key, Val >&
2026 operator=(
const HashTableConstIterator< Key, Val >& from);
2033 HashTableConstIteratorSafe< Key, Val >&
2034 operator=(HashTableConstIteratorSafe< Key, Val >&& from)
noexcept;
2051 HashTableConstIteratorSafe< Key, Val >& operator++()
noexcept;
2059 HashTableConstIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2068 HashTableConstIteratorSafe< Key, Val > operator+(Size i)
const;
2075 bool operator!=(
const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2082 bool operator==(
const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept;
2090 const value_type& operator*()
const;
2101 template <
typename K,
typename V,
typename A >
2102 friend class HashTable;
2105 const HashTable< Key, Val >* _table_{
nullptr};
2111 Size _index_{Size(0)};
2114 HashTableBucket< Key, Val >* _bucket_{
nullptr};
2124 HashTableBucket< Key, Val >* _next_bucket_{
nullptr};
2127 HashTableBucket< Key, Val >* _getBucket_()
const noexcept;
2135 Size _getIndex_()
const noexcept;
2140 void _removeFromSafeList_()
const;
2145 void _insertIntoSafeList_()
const;
2198 template <
typename Key,
typename Val >
2199 class HashTableIteratorSafe:
public HashTableConstIteratorSafe< Key, Val > {
2203 using iterator_category = std::forward_iterator_tag;
2204 using key_type = Key;
2205 using mapped_type = Val;
2206 using value_type = std::pair<
const Key, Val >;
2207 using reference = value_type&;
2208 using const_reference =
const value_type&;
2209 using pointer = value_type*;
2210 using const_pointer =
const value_type*;
2211 using difference_type = std::ptrdiff_t;
2222 HashTableIteratorSafe();
2229 template <
typename Alloc >
2230 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab);
2244 template <
typename Alloc >
2245 HashTableIteratorSafe(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2252 HashTableIteratorSafe(
const HashTableIteratorSafe< Key, Val >& from);
2259 explicit HashTableIteratorSafe(
const HashTableIterator< Key, Val >& from);
2266 HashTableIteratorSafe(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2271 ~HashTableIteratorSafe()
noexcept;
2281 using HashTableConstIteratorSafe< Key, Val >::key;
2282 using HashTableConstIteratorSafe< Key, Val >::val;
2283 using HashTableConstIteratorSafe< Key, Val >::clear;
2305 HashTableIteratorSafe< Key, Val >& operator=(
const HashTableIteratorSafe< Key, Val >& from);
2312 HashTableIteratorSafe< Key, Val >& operator=(
const HashTableIterator< Key, Val >& from);
2319 HashTableIteratorSafe< Key, Val >& operator=(HashTableIteratorSafe< Key, Val >&& from)
noexcept;
2335 HashTableIteratorSafe< Key, Val >& operator++()
noexcept;
2342 HashTableIteratorSafe< Key, Val >& operator+=(Size i)
noexcept;
2350 HashTableIteratorSafe< Key, Val > operator+(Size i)
const;
2358 bool operator!=(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2366 bool operator==(
const HashTableIteratorSafe< Key, Val >& from)
const noexcept;
2374 value_type& operator*();
2383 const value_type& operator*()
const;
2440 template <
typename Key,
typename Val >
2441 class HashTableConstIterator {
2445 using iterator_category = std::forward_iterator_tag;
2446 using key_type = Key;
2447 using mapped_type = Val;
2448 using value_type = std::pair<
const Key, Val >;
2449 using reference = value_type&;
2450 using const_reference =
const value_type&;
2451 using pointer = value_type*;
2452 using const_pointer =
const value_type*;
2453 using difference_type = std::ptrdiff_t;
2464 HashTableConstIterator()
noexcept;
2472 template <
typename Alloc >
2473 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2486 template <
typename Alloc >
2487 HashTableConstIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2493 HashTableConstIterator(
const HashTableConstIterator< Key, Val >& from)
noexcept;
2499 HashTableConstIterator(HashTableConstIterator< Key, Val >&& from)
noexcept;
2504 ~HashTableConstIterator()
noexcept;
2523 const key_type& key()
const;
2534 const mapped_type& val()
const;
2540 void clear()
noexcept;
2553 HashTableConstIterator< Key, Val >&
2554 operator=(
const HashTableConstIterator< Key, Val >& from)
noexcept;
2561 HashTableConstIterator< Key, Val >&
2562 operator=(HashTableConstIterator< Key, Val >&& from)
noexcept;
2581 HashTableConstIterator< Key, Val >& operator++()
noexcept;
2588 HashTableConstIterator< Key, Val >& operator+=(Size i)
noexcept;
2597 HashTableConstIterator< Key, Val > operator+(Size i)
const noexcept;
2605 bool operator!=(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2613 bool operator==(
const HashTableConstIterator< Key, Val >& from)
const noexcept;
2625 const value_type& operator*()
const;
2640 template <
typename K,
typename V,
typename A >
2641 friend class HashTable;
2644 friend class HashTableConstIteratorSafe< Key, Val >;
2647 const HashTable< Key, Val >* _table_{
nullptr};
2653 Size _index_{Size(0)};
2656 typename HashTable< Key, Val >::Bucket* _bucket_{
nullptr};
2662 typename HashTable< Key, Val >::Bucket* _getBucket_()
const noexcept;
2670 Size _getIndex_()
const noexcept;
2724 template <
typename Key,
typename Val >
2725 class HashTableIterator:
public HashTableConstIterator< Key, Val > {
2729 using iterator_category = std::forward_iterator_tag;
2730 using key_type = Key;
2731 using mapped_type = Val;
2732 using value_type = std::pair<
const Key, Val >;
2733 using reference = value_type&;
2734 using const_reference =
const value_type&;
2735 using pointer = value_type*;
2736 using const_pointer =
const value_type*;
2737 using difference_type = std::ptrdiff_t;
2748 HashTableIterator()
noexcept;
2756 template <
typename Alloc >
2757 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab)
noexcept;
2772 template <
typename Alloc >
2773 HashTableIterator(
const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2779 HashTableIterator(
const HashTableIterator< Key, Val >& from)
noexcept;
2785 HashTableIterator(HashTableIterator< Key, Val >&& from)
noexcept;
2790 ~HashTableIterator()
noexcept;
2800 using HashTableConstIterator< Key, Val >::key;
2801 using HashTableConstIterator< Key, Val >::val;
2802 using HashTableConstIterator< Key, Val >::clear;
2827 HashTableIterator< Key, Val >& operator=(
const HashTableIterator< Key, Val >& from)
noexcept;
2834 HashTableIterator< Key, Val >& operator=(HashTableIterator< Key, Val >&& from)
noexcept;
2852 HashTableIterator< Key, Val >& operator++()
noexcept;
2859 HashTableIterator< Key, Val >& operator+=(Size i)
noexcept;
2866 HashTableIterator< Key, Val > operator+(Size i)
const noexcept;
2874 bool operator!=(
const HashTableIterator< Key, Val >& from)
const noexcept;
2882 bool operator==(
const HashTableIterator< Key, Val >& from)
const noexcept;
2893 value_type& operator*();
2904 const value_type& operator*()
const;
2912 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2913 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2914 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2915 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2916 extern template class gum::HashTable<
int,
int >;
2921 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2922 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2923 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2924 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2925 extern template class gum::HashTable<
int, std::string >;
2930 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2931 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2932 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2933 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2934 extern template class gum::HashTable< std::string, std::string >;
2939 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2940 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2941 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2942 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS 2943 extern template class gum::HashTable< std::string,
int >;
2951 #include <agrum/tools/core/hashTable_tpl.h>