4#ifndef _Stroika_Foundation_Containers_DataStructures_HashTable_h_
5#define _Stroika_Foundation_Containers_DataStructures_HashTable_h_
7#include "Stroika/Foundation/StroikaPreComp.h"
9#include "Stroika/Foundation/Common/Common.h"
11#include "Stroika/Foundation/Common/KeyValuePair.h"
12#include "Stroika/Foundation/Containers/Common.h"
13#include "Stroika/Foundation/Cryptography/Digest/HashBase.h"
32 namespace HashTable_Support {
47 template <
typename KEY_TYPE,
typename MAPPED_TYPE,
size_t INLINE_ELTS_PER_CHAIN = 2,
size_t INLINE_BUCKETS = 5>
49 static constexpr size_t kBufferedElementsPerChain = INLINE_ELTS_PER_CHAIN;
50 static constexpr size_t kBufferedBuckets = INLINE_BUCKETS;
59 template <
typename KEY_TYPE,
typename MAPPED_TYPE, Cryptography::Digest::IHashFunction<KEY_TYPE> HASHER = hash<KEY_TYPE>,
60 Common::IEqualsComparer<KEY_TYPE> EQUALS_COMPARER = equal_to<KEY_TYPE>,
typename LAYOUT_OPTIONS = SeparateChainingOptions<KEY_TYPE, MAPPED_TYPE>,
61 AddOrExtendOrReplaceMode addOrExtendOrReplace = AddOrExtendOrReplaceMode::eAddExtras,
typename ALTERNATE_FIND_TYPE =
void>
65 using key_type = KEY_TYPE;
69 using mapped_type = MAPPED_TYPE;
77 using KeyHasherType = HASHER;
81 using KeyEqualsComparerType = EQUALS_COMPARER;
101 static constexpr bool kAutoShrinkBucketCount =
false;
107 template <
typename TRAITS,
typename KEY_TYPE,
typename MAPPED_TYPE>
111 { declval<typename TRAITS::LayoutType> () };
112 { TRAITS::kAddOrExtendOrReplace } -> convertible_to<AddOrExtendOrReplaceMode>;
113 { TRAITS::kAutoShrinkBucketCount } -> convertible_to<bool>;
114 } and (same_as<typename TRAITS::AlternateFindType, void> or
requires (TRAITS traits) {
115 { declval<typename TRAITS::AlternateFindType> () };
117 declval<typename TRAITS::KeyHasherType> ()
131 template <
typename KEY_TYPE,
typename MAPPED_TYPE =
void, HashTable_Support::IVal
idTraits<KEY_TYPE, MAPPED_TYPE> TRAITS = HashTable_Support::DefaultTraits<KEY_TYPE, MAPPED_TYPE>>
136 using key_type =
typename TRAITS::key_type;
141 using mapped_type =
typename TRAITS::mapped_type;
146 using value_type =
typename TRAITS::value_type;
151 using KeyHasherType =
typename TRAITS::KeyHasherType;
156 using KeyEqualsComparerType =
typename TRAITS::KeyEqualsComparerType;
167 using TraitsType = TRAITS;
174 HashTable (
const KeyHasherType& hashFunction = {},
const KeyEqualsComparerType& keyComparer = {});
175 HashTable (
size_t bucketCount,
const KeyHasherType& hashFunction = {},
const KeyEqualsComparerType& keyComparer = {});
176 HashTable (HashTable&& src)
noexcept =
default;
177 HashTable (
const HashTable& src) =
default;
178 ~HashTable () =
default;
183 nonvirtual HashTable& operator= (
const HashTable&) =
default;
184 nonvirtual HashTable& operator= (HashTable&&) =
default;
198 nonvirtual KeyEqualsComparerType
key_eq ()
const;
201 class ForwardIterator;
206 nonvirtual ForwardIterator begin ();
211 constexpr static ForwardIterator end ();
222 nonvirtual
void MoveIteratorHereAfterClone (ForwardIterator* pi,
const HashTable* movedFrom)
const;
240 nonvirtual
bool Add (
const value_type& t);
241 nonvirtual
bool Add (
const key_type& t)
242 requires (same_as<MAPPED_TYPE, void>);
243 template <same_as<MAPPED_TYPE> MAPPED_TYPE2 = MAPPED_TYPE>
244 nonvirtual
bool Add (
const key_type& t,
const MAPPED_TYPE2& m)
245 requires (not same_as<MAPPED_TYPE, void>);
254 nonvirtual
void insert (
const pair<KEY_TYPE, MAPPED_TYPE>& p);
259 nonvirtual optional<value_type> Lookup (
const key_type& t);
265 nonvirtual
void Remove (
const ForwardIterator& i, ForwardIterator* nextI =
nullptr);
266 nonvirtual
void Remove (
const key_type& t);
271 nonvirtual
bool RemoveIf (
const key_type& t);
277 nonvirtual ForwardIterator
erase (
const ForwardIterator& i);
289 nonvirtual
void ReHash (
size_t newBucketCount);
310 nonvirtual
size_t bucket_size (
size_t bucketIdx)
const;
317 nonvirtual
size_t size ()
const;
324 nonvirtual
bool empty ()
const;
349 nonvirtual
void clear ();
359 nonvirtual
bool contains (ArgByValueType<key_type> key)
const;
366 template <invocable<
typename TRAITS::value_type> FUNCTION>
384 template <
typename ARG_T =
typename TRAITS::AlternateFindType>
386 requires (not same_as<typename TRAITS::AlternateFindType, void> and same_as<remove_cvref_t<ARG_T>,
typename TRAITS::AlternateFindType>);
387 template <predicate<
typename TRAITS::key_type> FUNCTION>
401 template <
typename ARG_T =
typename TRAITS::AlternateFindType>
403 requires (not same_as<typename TRAITS::AlternateFindType, void> and same_as<remove_cvref_t<ARG_T>,
typename TRAITS::AlternateFindType>);
409 template <
typename CHECKED_T = MAPPED_TYPE>
411 requires (not same_as<MAPPED_TYPE, void>);
414 constexpr void Invariant () const noexcept;
416#if qStroika_Foundation_Debug_AssertionsChecked
418 nonvirtual
void Invariant_ () const noexcept;
422 using LayoutType_ =
typename TraitsType::LayoutType;
423 static constexpr size_t kBufferedElementsPerChain_ = LayoutType_::kBufferedElementsPerChain;
424 static constexpr size_t kBufferedBuckets_ = LayoutType_::kBufferedBuckets;
435 [[no_unique_address]] KeyHasherType fHasher_;
436 [[no_unique_address]] KeyEqualsComparerType fKeyComparer_;
438 size_t fCachedSize_{0};
441 nonvirtual
size_t Hash_ (
const key_type& v)
const
443 Require (fBuckets_.
size () > 0);
444 return fHasher_ (v) % fBuckets_.
size ();
446 template <
typename AT =
typename TRAITS::AlternateFindType>
447 requires (not same_as<AT, void>)
448 nonvirtual
size_t Hash_ (
const AT& v)
const
450 Require (fBuckets_.
size () > 0);
451 return fHasher_ (v) % fBuckets_.
size ();
456 float fMaxLoadFactor_{1.0};
463 template <
typename KEY_TYPE,
typename MAPPED_TYPE, HashTable_Support::IVal
idTraits<KEY_TYPE, MAPPED_TYPE> TRAITS>
467 using iterator_category = forward_iterator_tag;
468 using value_type = HashTable::value_type;
469 using difference_type = ptrdiff_t;
470 using pointer =
const value_type*;
471 using reference =
const value_type&;
489#if qStroika_Foundation_Debug_AssertionsChecked
498 explicit operator bool ()
const;
501 nonvirtual
bool Done () const noexcept;
504 nonvirtual const value_type& operator* () const;
507 nonvirtual const value_type* operator->() const;
538 template <
typename CHECKED_T = MAPPED_TYPE>
539 nonvirtual
void UpdateValue (ArgByValueType<CHECKED_T> newValue)
540 requires (not same_as<MAPPED_TYPE, void>);
549 constexpr void Invariant () const noexcept;
551#if qStroika_Foundation_Debug_AssertionsChecked
553 nonvirtual
void Invariant_ () const noexcept;
558 nonvirtual
void AdvanceOverEmptyBuckets_ ();
562 size_t fBucketIndex_{0};
563 size_t fIntraBucketIndex_{0};
566 friend class HashTable;
568 static_assert (ranges::input_range<HashTable<int>>);
577#include "HashTable.inl"
constexpr ForwardIterator() noexcept=default
implement hash table support in a lightweight standard template library style. Use traits to describe...
nonvirtual size_t size() const
nonvirtual ForwardIterator erase(const ForwardIterator &i)
stdlib like names and semantics (though may want to rethink the ForwardIterator vs UnderlyingIterator...
nonvirtual void Apply(FUNCTION &&doToElement, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
nonvirtual KeyEqualsComparerType key_eq() const
nonvirtual void Update(const ForwardIterator &it, ArgByValueType< CHECKED_T > newValue)
nonvirtual bool empty() const
nonvirtual bool contains(ArgByValueType< key_type > key) const
nonvirtual void insert(const pair< KEY_TYPE, MAPPED_TYPE > &p)
somewhat stdlib-like names - that will do what is expected of someone from stdc++,...
nonvirtual size_t bucket_count() const
tuple< size_t, size_t > UnderlyingIteratorRep
nonvirtual void ReHash(size_t newBucketCount)
nonvirtual ForwardIterator Find(ArgByValueType< key_type > key) const
nonvirtual KeyHasherType hash_function() const
nonvirtual ForwardIterator find(ArgByValueType< key_type > key) const
stdlib-ish API for 'Find' - returns iterator for found object in hashtable
nonvirtual size_t bucket_size(size_t bucketIdx) const
nonvirtual void ReHashIfNeeded()
nonvirtual void Remove(const ForwardIterator &i, ForwardIterator *nextI=nullptr)
nonvirtual float load_factor() const
average number of elements per bucket
nonvirtual bool Add(const value_type &t)
Add an item (key value pair typically, but the value can be void). Return true on list change; Respec...
nonvirtual float max_load_factor() const
average number of elements per bucket
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual size_t size() const noexcept
validated the HashTable provided TRAITS object looks healthy (for better compiler diagnostics and usa...
check argument FUNCTION is callable with a HASHABLE_T, and produces (something convertible to) size_t
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
constexpr void AssertDataMatches(const DoublyLinkedList *data) const
nonvirtual ForwardIterator & operator++() noexcept
nonvirtual size_t CurrentIndex(const DoublyLinkedList *data) const
AddOrExtendOrReplaceMode
Mode flag to say if Adding to a container replaces, or if the first addition wins (Logically AddOrExt...
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...
ALTERNATE_FIND_TYPE AlternateFindType
static constexpr AddOrExtendOrReplaceMode kAddOrExtendOrReplace
LAYOUT_OPTIONS LayoutType
used internally to select HashTable implementation strategies. NOT YET IMPLEMENTED OR THOUGHT OUT (se...
use as LAYOUT_OPTIONS for HashTable DefaultTraits<> template
used internally to select HashTable implementation strategies. Callers dont use directly,...