Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
KeyedCollection_HashTable.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Containers_Concrete_KeyedCollection_HashTable_h_
5#define _Stroika_Foundation_Containers_Concrete_KeyedCollection_HashTable_h_
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
10#include "Stroika/Foundation/Containers/DataStructures/HashTable.h"
11#include "Stroika/Foundation/Containers/KeyedCollection.h"
13#include "Stroika/Foundation/Cryptography/Digest/HashBase.h"
14
15/**
16 * \file
17 *
18 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
19 */
21
22 /**
23 * \brief mostly internal concept validator for hash-table that resides inside KeyedCollection_HashTable
24 */
25 namespace KeyedCollection_HashTable_Support {
26 template <typename TRAITS, typename T, typename KEY_TYPE>
28 TRAITS::kAddOrExtendOrReplace == AddOrExtendOrReplaceMode::eAddReplaces;
29 }
30
31 /**
32 * \brief KeyedCollection_HashTable<T,KEY_TYPE> is a HashTable based concrete implementation of the KeyedCollection<T,KEY_TYPE> container pattern.
33 *
34 * \note Runtime performance/complexity:
35 * o Add (typical O(1), worst case O(N))
36 * o Find (typical O(1), worst case O(N))
37 *
38 * key is quality of hash; if you hash well - get constant time access, if you have collisions, get poor (array or linked list like) performance.
39 *
40 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
41 */
42 template <typename T, typename KEY_TYPE, typename TRAITS = KeyedCollection_DefaultTraits<T, KEY_TYPE>>
44 : public Private::HashTableBasedContainer<KeyedCollection_HashTable<T, KEY_TYPE, TRAITS>, KeyedCollection<T, KEY_TYPE, TRAITS>> {
45 private:
47
48 public:
49 using TraitsType = typename inherited::TraitsType;
50 using KeyExtractorType = typename inherited::KeyExtractorType;
51 using KeyEqualityComparerType = typename inherited::KeyEqualityComparerType;
52 using KeyType = typename inherited::KeyType;
53 using key_type = typename inherited::key_type;
54 using value_type = typename inherited::value_type;
55
56 public:
57 /**
58 * An ELEMENT is of type T, but the KEY is of a separate type.
59 * For a keyed collection, we auto-extract the key from the type T, but store the type T.
60 * We internally must count on comparing elements of type KEY_TYPE (after extraction).
61 *
62 * This helper allows comparing either KEY or T types interchangeably.
63 *
64 * Used in STDHASHSET definition, and typically nowhere else
65 */
66 template <IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER = equal_to<key_type>>
67 struct ElementEqualsComparer : Common::ComparisonRelationDeclarationBase<Common::ComparisonRelationType::eEquals> {
68 static_assert (not is_reference_v<KEY_EQUALS_COMPARER>);
69 constexpr ElementEqualsComparer (const KeyExtractorType& keyExtractor = {}, const KEY_EQUALS_COMPARER& keyEqualsComparer = {})
70 : fKeyExtractor_{keyExtractor}
71 , fKeyComparer{keyEqualsComparer}
72 {
73 }
74 constexpr int operator() (const value_type& lhs, const KEY_TYPE& rhs) const
75 {
76 return fKeyComparer (fKeyExtractor_ (lhs), rhs);
77 };
78 constexpr int operator() (const KEY_TYPE& lhs, const value_type& rhs) const
79 {
80 return fKeyComparer (lhs, fKeyExtractor_ (rhs));
81 };
82 constexpr int operator() (const value_type& lhs, const value_type& rhs) const
83 {
84 return fKeyComparer (fKeyExtractor_ (lhs), fKeyExtractor_ (rhs));
85 };
86 [[no_unique_address]] const KeyExtractorType fKeyExtractor_;
87 [[no_unique_address]] const KEY_EQUALS_COMPARER fKeyComparer;
88 using is_transparent = int; // see https://en.cppreference.com/w/cpp/container/set/find - allows overloads to lookup by key
89 };
90
91 public:
92 /**
93 * An ELEMENT is of type T, but the KEY is of a separate type.
94 * For a keyed collection, we auto-extract the key from the type T, but store the type T.
95 * We internally must count on comparing elements of type KEY_TYPE (after extraction).
96 *
97 * This helper allows hashing either KEY or T types interchangeably.
98 *
99 * Used in STDHASHSET definition, and typically nowhere else
100 */
101 template <Cryptography::Digest::IHashFunction<KEY_TYPE> KEY_HASHER = hash<key_type>>
102 struct ElementHash {
103 constexpr ElementHash (const KeyExtractorType& keyExtractor = {}, const KEY_HASHER& kh = {})
104 : fKeyExtractor_{keyExtractor}
105 , fKeyHasher{kh}
106 {
107 }
108 auto operator() (const key_type& k) const noexcept
109 {
110 return fKeyHasher (k);
111 }
112 auto operator() (const value_type& v) const noexcept
113 {
114 return fKeyHasher (fKeyExtractor_ (v));
115 }
116 [[no_unique_address]] const KeyExtractorType fKeyExtractor_;
117 [[no_unique_address]] const KEY_HASHER fKeyHasher;
118
119 using is_transparent = int; // see https://en.cppreference.com/w/cpp/container/set/find - allows overloads to lookup by key
120 };
121
122 public:
123 /**
124 * DESIGN CHOICE - could use HashTable<KEY_TYPE,T> or HASH_TABLE<T,void>. The former would be simpler, and the later more compact.
125 * For now - try the more compact choice.
126 *
127 * Note this means that KEY_TYPE in the KeyedCollection_HashTable is VERY different from the KEY_TYPE in
128 * the HashTable (which is 'T' aka value_type from the KeyedCollection_HashTable); which is why we use the HashTable TRAITS AlternateFindType to be KEY_TYPE
129 */
130 template <Cryptography::Digest::IHashFunction<KEY_TYPE> HASHER = hash<KEY_TYPE>, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER = equal_to<KEY_TYPE>,
131 typename LAYOUT_OPTIONS = DataStructures::HashTable_Support::SeparateChainingOptions<T, void>>
134 LAYOUT_OPTIONS, AddOrExtendOrReplaceMode::eAddReplaces, KEY_TYPE>;
135
136 public:
137 /**
138 * \brief HashTable is DataStructures::HashTable<...> that can be used inside KeyedCollection_HashTable
139 */
140 template <KeyedCollection_HashTable_Support::IValidHashTableTraits<T, KEY_TYPE> HASH_TABLE_TRAITS = DefaultTraits<>>
142
143 public:
144 /**
145 * Convenient shorthand - not 100% sure why I couldn't just do this with default template arg to HASHTABLE, but didn't compile on gcc/clang?
146 */
147 template <typename K = KEY_TYPE>
148 requires (Cryptography::Digest::IHashFunction<hash<K>, K> and IEqualsComparer<equal_to<K>, K>)
149 using DEFAULT_HASHTABLE = DataStructures::HashTable<T, void, DefaultTraits<hash<K>, equal_to<K>>>;
150
151 public:
152 /**
153 * @todo consider adding more CTOR overloads... Like with base class KeyedCollection
154 */
157 Cryptography::Digest::IHashFunction<hash<KEY_TYPE>, KEY_TYPE> and IEqualsComparer<std::equal_to<KEY_TYPE>, KEY_TYPE>);
158 template <KeyedCollection_HashTable_Support::IValidHashTableTraits<T, KEY_TYPE> HASH_TABLE_TRAITS>
159 KeyedCollection_HashTable (const KeyExtractorType& keyExtractor, HASHTABLE<HASH_TABLE_TRAITS>&& src);
160 template <KeyedCollection_HashTable_Support::IValidHashTableTraits<T, KEY_TYPE> HASH_TABLE_TRAITS>
162#if !qCompilerAndStdLib_template_ConstraintDiffersInTemplateRedeclaration_Buggy
164#endif
165 ;
166 template <Cryptography::Digest::IHashFunction<KEY_TYPE> KEY_HASH = hash<KEY_TYPE>, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER = equal_to<KEY_TYPE>>
167 KeyedCollection_HashTable (const KeyExtractorType& keyExtractor = {}, KEY_HASH&& keyHasher = {},
168 KEY_EQUALS_COMPARER&& keyComparer = KEY_EQUALS_COMPARER{});
169 KeyedCollection_HashTable (KeyedCollection_HashTable&& src) noexcept = default;
170 KeyedCollection_HashTable (const KeyedCollection_HashTable& src) noexcept = default;
171
172 public:
173 /**
174 */
175 nonvirtual KeyedCollection_HashTable& operator= (KeyedCollection_HashTable&& rhs) noexcept = default;
176 nonvirtual KeyedCollection_HashTable& operator= (const KeyedCollection_HashTable& rhs) = default;
177
178 private:
180 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (KeyedCollection_HashTable_Support::IValidHashTableTraits<T, KEY_TYPE>) HASH_TABLE_TRAITS>
181 class Rep_;
182
183 private:
184 nonvirtual void AssertRepValidType_ () const;
185
186 private:
187 friend inherited;
188 };
189
190}
191
192/*
193 ********************************************************************************
194 ******************************* Implementation Details *************************
195 ********************************************************************************
196 */
197#include "KeyedCollection_HashTable.inl"
198
199#endif /*_Stroika_Foundation_Containers_Concrete_KeyedCollection_HashTable_h_ */
KeyedCollection_HashTable<T,KEY_TYPE> is a HashTable based concrete implementation of the KeyedCollec...
implement hash table support in a lightweight standard template library style. Use traits to describe...
Definition HashTable.h:132
a cross between Mapping<KEY, T> and Collection<T> and Set<T>
HashTableBasedContainer is a Stroika implementation detail, but its public methods are fair game and ...
validated the HashTable provided TRAITS object looks healthy (for better compiler diagnostics and usa...
Definition HashTable.h:108
check argument FUNCTION is callable with a HASHABLE_T, and produces (something convertible to) size_t
Definition HashBase.h:28