source: mainline/uspace/lib/cpp/include/impl/unordered_map.hpp@ cec6360

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cec6360 was cec6360, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: fixed operator[] for unordered map when the key is not in the map

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_UNORDERED_MAP
30#define LIBCPP_UNORDERED_MAP
31
32#include <initializer_list>
33#include <internal/hash_table.hpp>
34#include <functional>
35#include <memory>
36#include <utility>
37
38namespace std
39{
40 /**
41 * 23.5.4, class template unordered_map:
42 */
43
44 template<
45 class Key, class Value,
46 class Hash = hash<Key>,
47 class Pred = equal_to<Key>,
48 class Alloc = allocator<pair<const Key, Value>>
49 >
50 class unordered_map
51 {
52 public:
53 using key_type = Key;
54 using mapped_type = Value;
55 using value_type = pair<const key_type, mapped_type>;
56 using hasher = Hash;
57 using key_equal = Pred;
58 using allocator_type = Alloc;
59 using pointer = typename allocator_traits<allocator_type>::pointer;
60 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
61 using reference = value_type&;
62 using const_reference = const value_type&;
63 using size_type = size_t;
64 using difference_type = ptrdiff_t;
65
66 using iterator = aux::hash_table_iterator<
67 value_type, reference, pointer, size_type
68 >;
69 using const_iterator = aux::hash_table_const_iterator<
70 value_type, const_reference, const_pointer, size_type
71 >;
72 using local_iterator = aux::hash_table_local_iterator<
73 value_type, reference, pointer
74 >;
75 using const_local_iterator = aux::hash_table_const_local_iterator<
76 value_type, const_reference, const_pointer
77 >;
78
79 unordered_map()
80 : unordered_map{default_bucket_count_}
81 { /* DUMMY BODY */ }
82
83 explicit unordered_map(size_type bucket_count,
84 const hasher& hf = hasher{},
85 const key_equal& eql = key_equal{},
86 const allocator_type& alloc = allocator_type{})
87 : table_{bucket_count, hf, eql}, allocator_{alloc}
88 { /* DUMMY BODY */ }
89
90 template<class InputIterator>
91 unordered_map(InputIterator first, InputIterator last,
92 size_type bucket_count = default_bucket_count_,
93 const hasher& hf = hasher{},
94 const key_equal& eql = key_equal{},
95 const allocator_type& alloc = allocator_type{})
96 : unordered_map{bucket_count, hf, eql, alloc}
97 {
98 insert(first, last);
99 }
100
101 unordered_map(const unordered_map& other)
102 : unordered_map{other, other.allocator_}
103 { /* DUMMY BODY */ }
104
105 unordered_map(unordered_map&& other)
106 : table_{move(other.table_)}, allocator_{move(other.allocator_)}
107 { /* DUMMY BODY */ }
108
109 explicit unordered_map(const allocator_type& alloc)
110 : table_{default_bucket_count_}, allocator_{alloc}
111 { /* DUMMY BODY */ }
112
113 unordered_map(const unordered_map& other, const allocator_type& alloc)
114 : table_{other.table_}, allocator_{alloc}
115 { /* DUMMY BODY */ }
116
117 unordered_map(unordered_map&& other, const allocator_type& alloc)
118 : table_{move(other.table_)}, allocator_{alloc}
119 { /* DUMMY BODY */ }
120
121 unordered_map(initializer_list<value_type> init,
122 size_type bucket_count = default_bucket_count_,
123 const hasher& hf = hasher{},
124 const key_equal& eql = key_equal{},
125 const allocator_type& alloc = allocator_type{})
126 : unordered_map{bucket_count, hf, eql, alloc}
127 {
128 insert(init.begin(), init.end());
129 }
130
131 unordered_map(size_type bucket_count, const allocator_type& alloc)
132 : unordered_map{bucket_count, hasher{}, key_equal{}, alloc}
133 { /* DUMMY BODY */ }
134
135 unordered_map(size_type bucket_count, const hasher& hf, const allocator_type& alloc)
136 : unordered_map{bucket_count, hf, key_equal{}, alloc}
137 { /* DUMMY BODY */ }
138
139 template<class InputIterator>
140 unordered_map(InputIterator first, InputIterator last,
141 size_type bucket_count, const allocator_type& alloc)
142 : unordered_map{first, last, bucket_count, hasher{}, key_equal{}, alloc}
143 { /* DUMMY BODY */ }
144
145 template<class InputIterator>
146 unordered_map(InputIterator first, InputIterator last,
147 size_type bucket_count, const hasher& hf, const allocator_type& alloc)
148 : unordered_map{first, last, bucket_count, hf, key_equal{}, alloc}
149 { /* DUMMY BODY */ }
150
151 unordered_map(initializer_list<value_type> init, size_type bucket_count,
152 const allocator_type& alloc)
153 : unordered_map{init, bucket_count, hasher{}, key_equal{}, alloc}
154 { /* DUMMY BODY */ }
155
156 unordered_map(initializer_list<value_type> init, size_type bucket_count,
157 const hasher& hf, const allocator_type& alloc)
158 : unordered_map{init, bucket_count, hf, key_equal{}, alloc}
159 { /* DUMMY BODY */ }
160
161 ~unordered_map()
162 { /* DUMMY BODY */ }
163
164 unordered_map& operator=(const unordered_map& other)
165 {
166 // TODO: implement
167 return *this;
168 }
169
170 unordered_map& operator=(unordered_map&& other)
171 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
172 is_nothrow_move_assignable<hasher>::value &&
173 is_nothrow_move_assignable<key_equal>::value)
174 {
175 // TODO: implement
176 return *this;
177 }
178
179 unordered_map& operator=(initializer_list<value_type>& init)
180 {
181 table_.clear();
182 table_.reserve(init.size());
183
184 insert(init.begin(), init.end());
185
186 return *this;
187 }
188
189 allocator_type get_allocator() const noexcept
190 {
191 return allocator_;
192 }
193
194 bool empty() const noexcept
195 {
196 return table_.empty();
197 }
198
199 size_type size() const noexcept
200 {
201 return table_.size();
202 }
203
204 size_type max_size() const noexcept
205 {
206 return table_.max_size();
207 }
208
209 iterator begin() noexcept
210 {
211 return table_.begin();
212 }
213
214 const_iterator begin() const noexcept
215 {
216 return table_.begin();
217 }
218
219 iterator end() noexcept
220 {
221 return table_.end();
222 }
223
224 const_iterator end() const noexcept
225 {
226 return table_.end();
227 }
228
229 const_iterator cbegin() const noexcept
230 {
231 return table_.cbegin();
232 }
233
234 const_iterator cend() const noexcept
235 {
236 return table_.cend();
237 }
238
239 template<class... Args>
240 pair<iterator, bool> emplace(Args&&... args)
241 {
242 // TODO: implement
243 }
244
245 template<class... Args>
246 iterator emplace_hint(const_iterator position, Args&&... args)
247 {
248 // TODO: implement
249 }
250
251 pair<iterator, bool> insert(const value_type& val)
252 {
253 // TODO: implement
254 }
255
256 pair<iterator, bool> insert(value_type&& val)
257 {
258 // TODO: implement
259 }
260
261 template<class T>
262 pair<iterator, bool> insert(T&& val)
263 {
264 // TODO: implement
265 }
266
267 iterator insert(const_iterator hint, const value_type& val)
268 {
269 // TODO: implement
270 }
271
272 iterator insert(const_iterator hint, value_type&& val)
273 {
274 // TODO: implement
275 }
276
277 template<class T>
278 iterator insert(const_iterator hint, T&& val)
279 {
280 // TODO: implement
281 }
282
283 template<class InputIterator>
284 void insert(InputIterator first, InputIterator last)
285 {
286 // TODO: implement
287 }
288
289 void insert(initializer_list<value_type> init)
290 {
291 insert(init.begin(), init.end());
292 }
293
294 template<class... Args>
295 pair<iterator, bool> try_emplace(const key_type& key, Args&&... args)
296 {
297 // TODO: implement
298 }
299
300 template<class... Args>
301 pair<iterator, bool> try_emplace(key_type&& key, Args&&... args)
302 {
303 // TODO: implement
304 }
305
306 template<class... Args>
307 iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args)
308 {
309 // TODO: implement
310 }
311
312 template<class... Args>
313 iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args)
314 {
315 // TODO: implement
316 }
317
318 template<class T>
319 pair<iterator, bool> insert_or_assign(const key_type& key, T&& val)
320 {
321 // TODO: implement
322 }
323
324 template<class T>
325 pair<iterator, bool> insert_or_assign(key_type&& key, T&& val)
326 {
327 // TODO: implement
328 }
329
330 template<class T>
331 iterator insert_or_assign(const_iterator hint, const key_type& key, T&& val)
332 {
333 // TODO: implement
334 }
335
336 template<class T>
337 iterator insert_or_assign(const_iterator hint, key_type&& key, T&& val)
338 {
339 // TODO: implement
340 }
341
342 iterator erase(const_iterator position)
343 {
344 return table_.erase(position);
345 }
346
347 size_type erase(const key_type& key)
348 {
349 return table_.erase(key);
350 }
351
352 iterator erase(const_iterator first, const_iterator last)
353 {
354 while (first != last)
355 first = erase(first);
356
357 return iterator{
358 table_.table(), first.idx(),
359 table_.size(), table_.head(first.idx())
360 };
361 }
362
363 void clear() noexcept
364 {
365 table_.clear();
366 }
367
368 void swap(unordered_map& other)
369 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
370 noexcept(std::swap(declval<hasher>(), declval<hasher>())) &&
371 noexcept(std::swap(declval<key_equal>(), declval<key_equal>())))
372 {
373 table_.swap(other.table_);
374 std::swap(allocator_, other.allocator_);
375 }
376
377 hasher hash_function() const
378 {
379 return table_.hash_function();
380 }
381
382 key_equal key_eq() const
383 {
384 return table_.key_eq();
385 }
386
387 iterator find(const key_type& key)
388 {
389 return table_.find(key);
390 }
391
392 const_iterator find(const key_type& key) const
393 {
394 return table_.find(key);
395 }
396
397 size_type count(const key_type& key) const
398 {
399 return table_.count(key);
400 }
401
402 pair<iterator, iterator> equal_range(const key_type& key)
403 {
404 return table_.equal_range(key);
405 }
406
407 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
408 {
409 return table_.equal_range(key);
410 }
411
412 mapped_type& operator[](const key_type& key)
413 {
414 auto spot = table_.find_insertion_spot(key);
415 auto bucket = get<0>(spot);
416
417 if (bucket->head)
418 {
419 auto head = bucket->head;
420 auto current = bucket->head;
421
422 do
423 {
424 if (table_.keys_equal(key, current->value))
425 return current->value.second;
426 else
427 current = current->next;
428 }
429 while (current != head);
430 }
431
432 auto node = new node_type{key, mapped_type{}};
433 bucket->append(node);
434
435 return node->value.second;
436 }
437
438 mapped_type& operator[](key_type&& key)
439 {
440 auto spot = table_.find_insertion_spot(key);
441 auto bucket = get<0>(spot);
442
443 if (bucket->head)
444 {
445 auto head = bucket->head;
446 auto current = bucket->head;
447
448 do
449 {
450 if (table_.keys_equal(key, current->value))
451 return current->value.second;
452 else
453 current = current->next;
454 }
455 while (current != head);
456 }
457
458 auto node = new node_type{move(key), mapped_type{}};
459 bucket->append(node);
460
461 return node->value.second;
462 }
463
464 mapped_type& at(const key_type& key)
465 {
466 // TODO: implement
467 }
468
469 const mapped_type& at(const key_type& key) const
470 {
471 // TODO: implement
472 }
473
474 size_type bucket_count() const noexcept
475 {
476 return table_.bucket_count();
477 }
478
479 size_type max_bucket_count() const noexcept
480 {
481 return table_.max_bucket_count();
482 }
483
484 size_type bucket_size(size_type idx) const
485 {
486 return table_.bucket_size(idx);
487 }
488
489 size_type bucket(const key_type& key) const
490 {
491 return table_.bucket(key);
492 }
493
494 local_iterator begin(size_type idx)
495 {
496 return table_.begin(idx);
497 }
498
499 const_local_iterator begin(size_type idx) const
500 {
501 return table_.begin(idx);
502 }
503
504 local_iterator end(size_type idx)
505 {
506 return table_.end(idx);
507 }
508
509 const_local_iterator end(size_type idx) const
510 {
511 return table_.end(idx);
512 }
513
514 const_local_iterator cbegin(size_type idx) const
515 {
516 return table_.cbegin(idx);
517 }
518
519 const_local_iterator cend(size_type idx) const
520 {
521 return table_.cend(idx);
522 }
523
524 float load_factor() const noexcept
525 {
526 return table_.load_factor();
527 }
528
529 float max_load_factor() const noexcept
530 {
531 return table_.max_load_factor();
532 }
533
534 void max_load_factor(float factor)
535 {
536 table_.max_load_factor(factor);
537 }
538
539 void rehash(size_type bucket_count)
540 {
541 table_.rehash(bucket_count);
542 }
543
544 void reserve(size_type count)
545 {
546 table_.reserve(count);
547 }
548
549 private:
550 using table_type = aux::hash_table<
551 value_type, key_type, aux::key_value_key_extractor<key_type, mapped_type>,
552 hasher, key_equal, allocator_type, size_type,
553 iterator, const_iterator, local_iterator, const_local_iterator,
554 aux::hash_single_policy
555 >;
556 using node_type = typename table_type::node_type;
557
558 table_type table_;
559 allocator_type allocator_;
560
561 static constexpr size_type default_bucket_count_{16};
562 };
563
564 /**
565 * 23.5.5, class template unordered_multimap:
566 */
567
568 template<
569 class Key, class Value,
570 class Hash = hash<Key>,
571 class Pred = equal_to<Key>,
572 class Alloc = allocator<pair<const Key, Value>>
573 >
574 class unordered_multimap;
575
576 template<class Key, class Value, class Hash, class Pred, class Alloc>
577 void swap(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
578 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
579 noexcept(noexcept(lhs.swap(rhs)))
580 {
581 lhs.swap(rhs);
582 }
583
584 template<class Key, class Value, class Hash, class Pred, class Alloc>
585 void swap(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
586 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
587 noexcept(noexcept(lhs.swap(rhs)))
588 {
589 lhs.swap(rhs);
590 }
591
592 template<class Key, class Value, class Hash, class Pred, class Alloc>
593 bool operator==(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
594 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
595 {
596 // TODO: implement
597 return false;
598 }
599
600 template<class Key, class Value, class Hash, class Pred, class Alloc>
601 bool operator!=(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
602 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
603 {
604 return !(lhs == rhs);
605 }
606
607 template<class Key, class Value, class Hash, class Pred, class Alloc>
608 bool operator==(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
609 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
610 {
611 // TODO: implement
612 return false;
613 }
614
615 template<class Key, class Value, class Hash, class Pred, class Alloc>
616 bool operator!=(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
617 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
618 {
619 return !(lhs == rhs);
620 }
621}
622
623#endif
Note: See TracBrowser for help on using the repository browser.