libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_hash_map.hpp
1#ifndef GIMBAL_HASHMAP_HPP
2#define GIMBAL_HASHMAP_HPP
3
5
6namespace gbl {
7
8
9namespace impl {
10 template<typename K,
11 typename V,
12 typename H=std::hash<K>>
13 struct HashMapHasherAdapter;
14
15 template<typename K,
16 typename V,
17 typename P=std::equal_to<K>>
18 struct HashMapEqualToAdapter;
19}
20
21template<typename K,
22 typename T,
23 typename H = std::hash<K>,
24 typename P = std::equal_to<K>>
25class HashMap:
26 public HashSet<std::pair<const K, T>,
27 impl::HashMapHasherAdapter<K, T, H>,
28 impl::HashMapEqualToAdapter<K, T, P>>,
29 public ReadWriteIndexable<HashMap<K, T, H, P>, K, T, true>
30{
31public:
32 friend class ReadWriteIndexable<HashMap<K, T, H, P>, K, T, true>;
33
34 using HashSetType = HashSet<std::pair<const K, T>,
35 impl::HashMapHasherAdapter<K, T, H>,
36 impl::HashMapEqualToAdapter<K, T, P>>;
37 using HashSetBaseType = typename HashSetType::BaseType;
38 using key_type = K;
39 using mapped_type = T;
40 using value_type = std::pair<const K, T>;
41 using size_type = Size;
42 using difference_type = std::ptrdiff_t;
43 using hasher = H;
44 using key_equal = P;
45 using reference = value_type&;
46 using const_reference = const value_type&;
47 using pointer = value_type*;
48 using const_pointer = const pointer;
49 using iterator = typename HashSetType::iterator;
50 using const_iterator = typename HashSetType::const_iterator;
51 /* using iterator =
52 using const_iterator =
53 using local_iterator =
54 using const_local_iterator =
55 using node_type =
56 using insert_return_type = */
57protected:
58 auto getElement_(const K& key) const noexcept -> const T&;
59 void setElement_(const K& key, const T& value) noexcept;
60
61public:
62
63 HashMap(size_type capacity = 0,
64 const H& hash = H(),
65 const P& pred = P(),
66 Context* pCtx = nullptr);
67 HashMap(size_type capacity,
68 const H& hash,
69 Context* pCtx);
70 HashMap(size_type capacity,
71 Context* pCtx);
72 explicit HashMap(Context* pCtx);
73
74 HashMap(std::initializer_list<value_type> init,
75 size_type capacity = 0,
76 const H& hash = H(),
77 const P& pred = P(),
78 Context* pCtx = nullptr);
79 HashMap(std::initializer_list<value_type> init,
80 size_type capacity,
81 const H& hash,
82 Context* pCtx);
83 HashMap(std::initializer_list<value_type> init,
84 size_type capacity,
85 Context* pCtx);
86
87
88 template<typename M>
89 void insert_or_assign(const key_type& k, M&& obj) noexcept;
90
91 bool erase(const key_type& k) noexcept;
92
93 auto at(const key_type& key) const -> const mapped_type&;
94 auto at(const key_type& key) -> mapped_type&;
95
96 auto find(const key_type& key) const noexcept -> const_iterator;
97 auto find(const key_type& key) noexcept -> iterator;
98
99 bool contains(const key_type& key) const noexcept;
100 //iterator find(const key_type& key) const;
101
102};
103
104#if 0
105template<typename K,
106 typename T,
107 typename H = std::hash<K>,
108 typename P = std::equal_to<K>>
109HashMap(std::initializer_list<std::pair<const K, T>> list,
110 Size capacity=0,
111 const H& hash=H(),
112 const P& pred=P(),
113 Context* pCtx=nullptr) -> HashMap<K, T, H, P>;
114#endif
115
116
117
118// ======== IMPLEMENTATION ========
119
120
121namespace impl {
122
123 template<typename K,
124 typename V,
125 typename H>
126 struct HashMapHasherAdapter {
127 const H& hasher;
128
129 HashMapHasherAdapter(const H& hasher_=H()):
130 hasher(hasher_) {}
131
132 Hash operator()(const std::pair<K, V>& value) const {
133 return hasher(value.first);
134 }
135 };
136
137 template<typename K,
138 typename V,
139 typename P>
140 struct HashMapEqualToAdapter {
141 const P& pred;
142
143 HashMapEqualToAdapter(const P& pred_=P()):
144 pred(pred_) {}
145
146 bool operator()(const std::pair<K, V>& lhs, const std::pair<K, V>& rhs) const {
147 return pred(lhs.first, rhs.first);
148 }
149 };
150
151}
152
153template<typename K, typename T, typename H, typename P>
154inline HashMap<K, T, H, P>::HashMap(size_type capacity,
155 const H& hash,
156 const P& pred,
157 Context* pCtx):
158 HashSetType(capacity, hash, pred, pCtx) {}
159
160template<typename K, typename T, typename H, typename P>
161inline HashMap<K, T, H, P>::HashMap(std::initializer_list<value_type> init,
162 size_type capacity,
163 const H& hash,
164 const P& pred,
165 Context* pCtx):
166 HashMap(capacity < init.size()? init.size() : capacity, hash, pred, pCtx)
167{
168 //INEFFICIENT AS SHIT COPYING?
169 for(auto item : init) {
170 HashSetType::insert(item);
171 }
172}
173
174template<typename K, typename T, typename H, typename P>
175inline HashMap<K, T, H, P>::HashMap(size_type capacity,
176 const H& hash,
177 Context* pCtx):
178 HashMap(capacity, hash, P(), pCtx) {}
179
180template<typename K, typename T, typename H, typename P>
181inline HashMap<K, T, H, P>::HashMap(size_type capacity, Context* pCtx):
182 HashMap(capacity, H(), P(), pCtx) {}
183
184template<typename K, typename T, typename H, typename P>
185inline HashMap<K, T, H, P>::HashMap(Context* pCtx):
186 HashMap(0, pCtx) {}
187
188
189template<typename K, typename T, typename H, typename P>
190inline HashMap<K, T, H, P>::HashMap(std::initializer_list<value_type> init,
191 size_type capacity,
192 const H& hash,
193 Context* pCtx):
194 HashMap(std::move(init), capacity, hash, P(), pCtx) {}
195
196template<typename K, typename T, typename H, typename P>
197inline HashMap<K, T, H, P>::HashMap(std::initializer_list<value_type> init,
198 size_type capacity,
199 Context* pCtx):
200 HashMap(std::move(init), capacity, H(), pCtx) {}
201
202template<typename K, typename T, typename H, typename P>
203inline const T& HashMap<K, T, H, P>::getElement_(const K& key) const noexcept {
204 return at(key);
205}
206
207template<typename K, typename T, typename H, typename P>
208inline void HashMap<K, T, H, P>::setElement_(const K& key, const T& value) noexcept {
209 insert_or_assign(key, value);
210}
211
212template<typename K, typename T, typename H, typename P>
213template<typename M>
214inline void HashMap<K, T, H, P>::insert_or_assign(const key_type& k, M&& obj) noexcept {
215 std::pair<K, T> item { k, std::forward<M>(obj) };
216 HashSetType::insert_or_assign(item);
217}
218
219template<typename K, typename T, typename H, typename P>
220inline bool HashMap<K, T, H, P>::erase(const key_type& k) noexcept {
221 std::pair<K, T> pair { k, T{} };
222 return HashSetType::erase(pair);
223}
224
225template<typename K, typename T, typename H, typename P>
226inline auto HashMap<K, T, H, P>::at(const key_type& k) const -> const mapped_type& {
227 std::pair<K, T> pair { k, T{} };
228 const auto& result = HashSetBaseType::at(pair);
229 return result.second;
230}
231
232template<typename K, typename T, typename H, typename P>
233inline auto HashMap<K, T, H, P>::at(const key_type& k) -> mapped_type& {
234 std::pair<K, T> pair { k, T{} };
235 auto& result = HashSetType::at(pair);
236 return result.second;
237}
238
239template<typename K, typename T, typename H, typename P>
240inline auto HashMap<K, T, H, P>::find(const key_type& k) const noexcept -> const_iterator {
241 std::pair<K, T> pair (k, T{});
242 return HashSetType::find(pair);
243}
244
245template<typename K, typename T, typename H, typename P>
246inline auto HashMap<K, T, H, P>::find(const key_type& k) noexcept -> iterator {
247 std::pair<K, T> pair (k, T{});
248 return HashSetType::find(pair);
249}
250
251template<typename K, typename T, typename H, typename P>
252inline bool HashMap<K, T, H, P>::contains(const key_type& k) const noexcept {
253 std::pair<K, T> pair { k, T{} };
254 return HashSetType::contains(pair);
255}
256
257
258}
259
260#endif // GIMBAL_HASHMAP_HPP