Embedded Template Library 1.0
Loading...
Searching...
No Matches
unordered_multimap.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2016 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_UNORDERED_MULTIMAP_INCLUDED
32#define ETL_UNORDERED_MULTIMAP_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "debug_count.h"
37#include "error_handler.h"
38#include "exception.h"
39#include "functional.h"
40#include "hash.h"
41#include "initializer_list.h"
43#include "iterator.h"
44#include "nth_type.h"
45#include "nullptr.h"
46#include "parameter_type.h"
47#include "placement_new.h"
48#include "pool.h"
49#include "type_traits.h"
50#include "utility.h"
51#include "vector.h"
52
54
55#include <stddef.h>
56
57//*****************************************************************************
61//*****************************************************************************
62
63namespace etl
64{
65 //***************************************************************************
68 //***************************************************************************
69 class unordered_multimap_exception : public etl::exception
70 {
71 public:
72
73 unordered_multimap_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
74 : etl::exception(reason_, file_name_, line_number_)
75 {
76 }
77 };
78
79 //***************************************************************************
82 //***************************************************************************
83 class unordered_multimap_full : public etl::unordered_multimap_exception
84 {
85 public:
86
87 unordered_multimap_full(string_type file_name_, numeric_type line_number_)
88 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:full", ETL_UNORDERED_MULTIMAP_FILE_ID"A"), file_name_, line_number_)
89 {
90 }
91 };
92
93 //***************************************************************************
96 //***************************************************************************
97 class unordered_multimap_out_of_range : public etl::unordered_multimap_exception
98 {
99 public:
100
101 unordered_multimap_out_of_range(string_type file_name_, numeric_type line_number_)
102 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:range", ETL_UNORDERED_MULTIMAP_FILE_ID"B"), file_name_, line_number_)
103 {
104 }
105 };
106
107 //***************************************************************************
110 //***************************************************************************
111 class unordered_multimap_iterator : public etl::unordered_multimap_exception
112 {
113 public:
114
115 unordered_multimap_iterator(string_type file_name_, numeric_type line_number_)
116 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:iterator", ETL_UNORDERED_MULTIMAP_FILE_ID"C"), file_name_, line_number_)
117 {
118 }
119 };
120
121 //***************************************************************************
126 //***************************************************************************
127 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey> >
129 {
130 public:
131
132 typedef ETL_OR_STD::pair<const TKey, T> value_type;
133
134 typedef TKey key_type;
135 typedef T mapped_type;
136 typedef THash hasher;
137 typedef TKeyEqual key_equal;
138 typedef value_type& reference;
139 typedef const value_type& const_reference;
140#if ETL_USING_CPP11
141 typedef value_type&& rvalue_reference;
142#endif
143 typedef value_type* pointer;
144 typedef const value_type* const_pointer;
145 typedef size_t size_type;
146
147 typedef const key_type& const_key_reference;
148#if ETL_USING_CPP11
149 typedef key_type&& rvalue_key_reference;
150#endif
151
152 typedef etl::forward_link<0> link_t; // Default link.
153
154 //*********************************************************************
155 // The nodes that store the elements.
156 struct node_t : public link_t
157 {
158 node_t(const_reference key_value_pair_)
159 : key_value_pair(key_value_pair_)
160 {
161 }
162
163 value_type key_value_pair;
164 };
165
166 friend bool operator==(const node_t& lhs, const node_t& rhs)
167 {
168 return (lhs.key_value_pair.first == rhs.key_value_pair.first) && (lhs.key_value_pair.second == rhs.key_value_pair.second);
169 }
170
171 friend bool operator!=(const node_t& lhs, const node_t& rhs)
172 {
173 return !(lhs == rhs);
174 }
175
176 protected:
177
179 typedef etl::ipool pool_t;
180
181 public:
182
183 // Local iterators iterate over one bucket.
184 typedef typename bucket_t::iterator local_iterator;
185 typedef typename bucket_t::const_iterator const_local_iterator;
186
187 //*********************************************************************
188 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, T>
189 {
190 public:
191
192 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, T>::value_type value_type;
193 typedef typename iunordered_multimap::key_type key_type;
194 typedef typename iunordered_multimap::mapped_type mapped_type;
195 typedef typename iunordered_multimap::hasher hasher;
196 typedef typename iunordered_multimap::key_equal key_equal;
197 typedef typename iunordered_multimap::reference reference;
198 typedef typename iunordered_multimap::const_reference const_reference;
199 typedef typename iunordered_multimap::pointer pointer;
200 typedef typename iunordered_multimap::const_pointer const_pointer;
201 typedef typename iunordered_multimap::size_type size_type;
202
203 friend class iunordered_multimap;
204 friend class const_iterator;
205
206 //*********************************
207 iterator() {}
208
209 //*********************************
210 iterator(const iterator& other)
211 : pbuckets_end(other.pbuckets_end)
212 , pbucket(other.pbucket)
213 , inode(other.inode)
214 {
215 }
216
217 //*********************************
218 iterator& operator++()
219 {
220 ++inode;
221
222 // The end of this node list?
223 if (inode == pbucket->end())
224 {
225 // Search for the next non-empty bucket.
226 ++pbucket;
227 while ((pbucket != pbuckets_end) && (pbucket->empty()))
228 {
229 ++pbucket;
230 }
231
232 // If not past the end, get the first node in the bucket.
233 if (pbucket != pbuckets_end)
234 {
235 inode = pbucket->begin();
236 }
237 }
238
239 return *this;
240 }
241
242 //*********************************
243 iterator operator++(int)
244 {
245 iterator temp(*this);
246 operator++();
247 return temp;
248 }
249
250 //*********************************
251 iterator& operator=(const iterator& other)
252 {
253 pbuckets_end = other.pbuckets_end;
254 pbucket = other.pbucket;
255 inode = other.inode;
256 return *this;
257 }
258
259 //*********************************
260 reference operator*() const
261 {
262 return inode->key_value_pair;
263 }
264
265 //*********************************
266 pointer operator&() const
267 {
268 return &(inode->key_value_pair);
269 }
270
271 //*********************************
272 pointer operator->() const
273 {
274 return &(inode->key_value_pair);
275 }
276
277 //*********************************
278 friend bool operator==(const iterator& lhs, const iterator& rhs)
279 {
280 return lhs.compare(rhs);
281 }
282
283 //*********************************
284 friend bool operator!=(const iterator& lhs, const iterator& rhs)
285 {
286 return !(lhs == rhs);
287 }
288
289 private:
290
291 //*********************************
292 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
293 : pbuckets_end(pbuckets_end_)
294 , pbucket(pbucket_)
295 , inode(inode_)
296 {
297 }
298
299 //*********************************
300 bool compare(const iterator& rhs) const
301 {
302 return rhs.inode == inode;
303 }
304
305 //*********************************
306 bucket_t& get_bucket()
307 {
308 return *pbucket;
309 }
310
311 //*********************************
312 bucket_t*& get_bucket_list_iterator()
313 {
314 return pbucket;
315 }
316
317 //*********************************
318 local_iterator get_local_iterator()
319 {
320 return inode;
321 }
322
323 bucket_t* pbuckets_end;
324 bucket_t* pbucket;
325 local_iterator inode;
326 };
327
328 //*********************************************************************
329 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>
330 {
331 public:
332
333 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>::value_type value_type;
334 typedef typename iunordered_multimap::key_type key_type;
335 typedef typename iunordered_multimap::mapped_type mapped_type;
336 typedef typename iunordered_multimap::hasher hasher;
337 typedef typename iunordered_multimap::key_equal key_equal;
338 typedef typename iunordered_multimap::reference reference;
339 typedef typename iunordered_multimap::const_reference const_reference;
340 typedef typename iunordered_multimap::pointer pointer;
341 typedef typename iunordered_multimap::const_pointer const_pointer;
342 typedef typename iunordered_multimap::size_type size_type;
343
344 friend class iunordered_multimap;
345 friend class iterator;
346
347 //*********************************
348 const_iterator() {}
349
350 //*********************************
351 const_iterator(const typename iunordered_multimap::iterator& other)
352 : pbuckets_end(other.pbuckets_end)
353 , pbucket(other.pbucket)
354 , inode(other.inode)
355 {
356 }
357
358 //*********************************
359 const_iterator(const const_iterator& other)
360 : pbuckets_end(other.pbuckets_end)
361 , pbucket(other.pbucket)
362 , inode(other.inode)
363 {
364 }
365
366 //*********************************
367 const_iterator& operator++()
368 {
369 ++inode;
370
371 // The end of this node list?
372 if (inode == pbucket->end())
373 {
374 // Search for the next non-empty bucket.
375
376 ++pbucket;
377 while ((pbucket != pbuckets_end) && (pbucket->empty()))
378 {
379 ++pbucket;
380 }
381
382 // If not past the end, get the first node in the bucket.
383 if (pbucket != pbuckets_end)
384 {
385 inode = pbucket->begin();
386 }
387 }
388
389 return *this;
390 }
391
392 //*********************************
393 const_iterator operator++(int)
394 {
395 const_iterator temp(*this);
396 operator++();
397 return temp;
398 }
399
400 //*********************************
401 const_iterator& operator=(const const_iterator& other)
402 {
403 pbuckets_end = other.pbuckets_end;
404 pbucket = other.pbucket;
405 inode = other.inode;
406 return *this;
407 }
408
409 //*********************************
410 const_reference operator*() const
411 {
412 return inode->key_value_pair;
413 }
414
415 //*********************************
416 const_pointer operator&() const
417 {
418 return &(inode->key_value_pair);
419 }
420
421 //*********************************
422 const_pointer operator->() const
423 {
424 return &(inode->key_value_pair);
425 }
426
427 //*********************************
428 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
429 {
430 return lhs.compare(rhs);
431 }
432
433 //*********************************
434 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
435 {
436 return !(lhs == rhs);
437 }
438
439 private:
440
441 //*********************************
442 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
443 : pbuckets_end(pbuckets_end_)
444 , pbucket(pbucket_)
445 , inode(inode_)
446 {
447 }
448
449 //*********************************
450 bool compare(const const_iterator& rhs) const
451 {
452 return rhs.inode == inode;
453 }
454
455 //*********************************
456 bucket_t& get_bucket()
457 {
458 return *pbucket;
459 }
460
461 //*********************************
462 bucket_t*& get_bucket_list_iterator()
463 {
464 return pbucket;
465 }
466
467 //*********************************
468 local_iterator get_local_iterator()
469 {
470 return inode;
471 }
472
473 bucket_t* pbuckets_end;
474 bucket_t* pbucket;
475 local_iterator inode;
476 };
477
478 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
479
480 //*********************************************************************
483 //*********************************************************************
484 iterator begin()
485 {
486 return iterator((pbuckets + number_of_buckets), first, first->begin());
487 }
488
489 //*********************************************************************
492 //*********************************************************************
493 const_iterator begin() const
494 {
495 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
496 }
497
498 //*********************************************************************
501 //*********************************************************************
502 const_iterator cbegin() const
503 {
504 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
505 }
506
507 //*********************************************************************
510 //*********************************************************************
511 local_iterator begin(size_t i)
512 {
513 return pbuckets[i].begin();
514 }
515
516 //*********************************************************************
521 //*********************************************************************
522 const_local_iterator begin(size_t i) const
523 {
524 return pbuckets[i].cbegin();
525 }
526
527 //*********************************************************************
532 //*********************************************************************
533 const_local_iterator cbegin(size_t i) const
534 {
535 return pbuckets[i].cbegin();
536 }
537
538 //*********************************************************************
541 //*********************************************************************
542 iterator end()
543 {
544 return iterator((pbuckets + number_of_buckets), last, last->end());
545 }
546
547 //*********************************************************************
550 //*********************************************************************
551 const_iterator end() const
552 {
553 return const_iterator((pbuckets + number_of_buckets), last, last->end());
554 }
555
556 //*********************************************************************
559 //*********************************************************************
560 const_iterator cend() const
561 {
562 return const_iterator((pbuckets + number_of_buckets), last, last->end());
563 }
564
565 //*********************************************************************
568 //*********************************************************************
569 local_iterator end(size_t i)
570 {
571 return pbuckets[i].end();
572 }
573
574 //*********************************************************************
577 //*********************************************************************
578 const_local_iterator end(size_t i) const
579 {
580 return pbuckets[i].cend();
581 }
582
583 //*********************************************************************
586 //*********************************************************************
587 const_local_iterator cend(size_t i) const
588 {
589 return pbuckets[i].cend();
590 }
591
592 //*********************************************************************
595 //*********************************************************************
596 size_type get_bucket_index(const_key_reference key) const
597 {
598 return key_hash_function(key) % number_of_buckets;
599 }
600
601#if ETL_USING_CPP11
602 //*********************************************************************
605 //*********************************************************************
606 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
607 size_type get_bucket_index(const K& key) const
608 {
609 return key_hash_function(key) % number_of_buckets;
610 }
611#endif
612
613 //*********************************************************************
616 //*********************************************************************
617 size_type bucket_size(const_key_reference key) const
618 {
619 size_t index = bucket(key);
620
621 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
622 }
623
624#if ETL_USING_CPP11
625 //*********************************************************************
628 //*********************************************************************
629 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
630 size_type bucket_size(const K& key) const
631 {
632 size_t index = bucket(key);
633
634 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
635 }
636#endif
637
638 //*********************************************************************
641 //*********************************************************************
642 size_type max_bucket_count() const
643 {
644 return number_of_buckets;
645 }
646
647 //*********************************************************************
650 //*********************************************************************
651 size_type bucket_count() const
652 {
653 return number_of_buckets;
654 }
655
656 //*********************************************************************
664 //*********************************************************************
665 template <typename TIterator>
666 void assign(TIterator first_, TIterator last_)
667 {
668#if ETL_IS_DEBUG_BUILD
669 difference_type d = etl::distance(first_, last_);
670 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_multimap_iterator));
671 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_multimap_full));
672#endif
673
674 clear();
675
676 while (first_ != last_)
677 {
678 insert(*first_);
679 ++first_;
680 }
681 }
682
683 //*********************************************************************
688 //*********************************************************************
689 iterator insert(const_reference key_value_pair)
690 {
691 iterator result = end();
692
694
695 const_key_reference key = key_value_pair.first;
696
697 // Get the hash index.
698 size_t index = get_bucket_index(key);
699
700 // Get the bucket & bucket iterator.
701 bucket_t* pbucket = pbuckets + index;
702 bucket_t& bucket = *pbucket;
703
704 // The first one in the bucket?
705 if (bucket.empty())
706 {
707 // Get a new node.
708 node_t* node = allocate_data_node();
709 node->clear();
710 ::new (&node->key_value_pair) value_type(key_value_pair);
711 ETL_INCREMENT_DEBUG_COUNT;
712
713 // Just add the pointer to the bucket;
714 bucket.insert_after(bucket.before_begin(), *node);
715 adjust_first_last_markers_after_insert(pbucket);
716
717 result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
718 }
719 else
720 {
721 // Step though the bucket looking for a place to insert.
722 local_iterator inode_previous = bucket.before_begin();
723 local_iterator inode = bucket.begin();
724
725 while (inode != bucket.end())
726 {
727 // Do we already have this key?
728 if (key_equal_function(inode->key_value_pair.first, key))
729 {
730 break;
731 }
732
733 ++inode_previous;
734 ++inode;
735 }
736
737 // Get a new node.
738 node_t* node = allocate_data_node();
739 node->clear();
740 ::new (&node->key_value_pair) value_type(key_value_pair);
741 ETL_INCREMENT_DEBUG_COUNT;
742
743 // Add the node to the end of the bucket;
744 bucket.insert_after(inode_previous, *node);
745 adjust_first_last_markers_after_insert(&bucket);
746 ++inode_previous;
747
748 result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
749 }
750
751 return result;
752 }
753
754#if ETL_USING_CPP11
755 //*********************************************************************
760 //*********************************************************************
761 iterator insert(rvalue_reference key_value_pair)
762 {
763 iterator result = end();
764
766
767 const_key_reference key = key_value_pair.first;
768
769 // Get the hash index.
770 size_t index = get_bucket_index(key);
771
772 // Get the bucket & bucket iterator.
773 bucket_t* pbucket = pbuckets + index;
774 bucket_t& bucket = *pbucket;
775
776 // The first one in the bucket?
777 if (bucket.empty())
778 {
779 // Get a new node.
780 node_t* node = allocate_data_node();
781 node->clear();
782 ::new (&node->key_value_pair) value_type(etl::move(key_value_pair));
783 ETL_INCREMENT_DEBUG_COUNT;
784
785 // Just add the pointer to the bucket;
786 bucket.insert_after(bucket.before_begin(), *node);
787 adjust_first_last_markers_after_insert(pbucket);
788
789 result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
790 }
791 else
792 {
793 // Step though the bucket looking for a place to insert.
794 local_iterator inode_previous = bucket.before_begin();
795 local_iterator inode = bucket.begin();
796
797 while (inode != bucket.end())
798 {
799 // Do we already have this key?
800 if (key_equal_function(inode->key_value_pair.first, key))
801 {
802 break;
803 }
804
805 ++inode_previous;
806 ++inode;
807 }
808
809 // Get a new node.
810 node_t* node = allocate_data_node();
811 node->clear();
812 ::new (&node->key_value_pair) value_type(etl::move(key_value_pair));
813 ETL_INCREMENT_DEBUG_COUNT;
814
815 // Add the node to the end of the bucket;
816 bucket.insert_after(inode_previous, *node);
817 adjust_first_last_markers_after_insert(&bucket);
818 ++inode_previous;
819
820 result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
821 }
822
823 return result;
824 }
825#endif
826
827 //*********************************************************************
833 //*********************************************************************
834 iterator insert(const_iterator, const_reference key_value_pair)
835 {
836 return insert(key_value_pair);
837 }
838
839#if ETL_USING_CPP11
840 //*********************************************************************
846 //*********************************************************************
847 iterator insert(const_iterator, rvalue_reference key_value_pair)
848 {
849 return insert(etl::move(key_value_pair));
850 }
851#endif
852
853 //*********************************************************************
860 //*********************************************************************
861 template <class TIterator>
862 void insert(TIterator first_, TIterator last_)
863 {
864 while (first_ != last_)
865 {
866 insert(*first_);
867 ++first_;
868 }
869 }
870
871 //*********************************************************************
875 //*********************************************************************
876 size_t erase(const_key_reference key)
877 {
878 size_t n = 0UL;
879 size_t bucket_id = get_bucket_index(key);
880
881 bucket_t& bucket = pbuckets[bucket_id];
882
883 local_iterator iprevious = bucket.before_begin();
884 local_iterator icurrent = bucket.begin();
885
886 while (icurrent != bucket.end())
887 {
888 if (key_equal_function(icurrent->key_value_pair.first, key))
889 {
890 delete_data_node(iprevious, icurrent, bucket);
891 ++n;
892 icurrent = iprevious;
893 }
894 else
895 {
896 ++iprevious;
897 }
898
899 ++icurrent;
900 }
901
902 return n;
903 }
904
905#if ETL_USING_CPP11
906 //*********************************************************************
910 //*********************************************************************
911 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
912 size_t erase(const K& key)
913 {
914 size_t n = 0UL;
915 size_t bucket_id = get_bucket_index(key);
916
917 bucket_t& bucket = pbuckets[bucket_id];
918
919 local_iterator iprevious = bucket.before_begin();
920 local_iterator icurrent = bucket.begin();
921
922 while (icurrent != bucket.end())
923 {
924 if (key_equal_function(icurrent->key_value_pair.first, key))
925 {
926 delete_data_node(iprevious, icurrent, bucket);
927 ++n;
928 icurrent = iprevious;
929 }
930 else
931 {
932 ++iprevious;
933 }
934
935 ++icurrent;
936 }
937
938 return n;
939 }
940#endif
941
942 //*********************************************************************
945 //*********************************************************************
946 iterator erase(const_iterator ielement)
947 {
948 // Make a note of the next one.
949 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
950 ++inext;
951
952 bucket_t& bucket = ielement.get_bucket();
953 local_iterator iprevious = bucket.before_begin();
954 local_iterator icurrent = ielement.get_local_iterator();
955
956 // Find the node previous to the one we're interested in.
957 while (iprevious->etl_next != &*icurrent)
958 {
959 ++iprevious;
960 }
961
962 delete_data_node(iprevious, icurrent, bucket);
963
964 return inext;
965 }
966
967 //*********************************************************************
973 //*********************************************************************
974 iterator erase(const_iterator first_, const_iterator last_)
975 {
976 // Erasing everything?
977 if ((first_ == begin()) && (last_ == end()))
978 {
979 clear();
980 return end();
981 }
982
983 // Get the starting point.
984 bucket_t* pbucket = first_.get_bucket_list_iterator();
985 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
986 local_iterator iprevious = pbucket->before_begin();
987 local_iterator icurrent = first_.get_local_iterator();
988 local_iterator iend = last_.get_local_iterator(); // Note: May not be in the same bucket as
989 // icurrent.
990
991 // Find the node previous to the first one.
992 while (iprevious->etl_next != &*icurrent)
993 {
994 ++iprevious;
995 }
996
997 // Remember the item before the first erased one.
998 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
999
1000 // Until we reach the end.
1001 while ((icurrent != iend) || (pbucket != pend_bucket))
1002 {
1003 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1004
1005 // Have we not reached the end?
1006 if ((icurrent != iend) || (pbucket != pend_bucket))
1007 {
1008 // At the end of this bucket?
1009 if ((icurrent == pbucket->end()))
1010 {
1011 // Find the next non-empty one.
1012 do {
1013 ++pbucket;
1014 } while (pbucket->empty());
1015
1016 iprevious = pbucket->before_begin();
1017 icurrent = pbucket->begin();
1018 }
1019 }
1020 }
1021
1022 return ++ibefore_erased;
1023 }
1024
1025 //*************************************************************************
1027 //*************************************************************************
1028 void clear()
1029 {
1030 initialise();
1031 }
1032
1033 //*********************************************************************
1037 //*********************************************************************
1038 size_t count(const_key_reference key) const
1039 {
1040 size_t n = 0UL;
1041 const_iterator f = find(key);
1042 const_iterator l = f;
1043
1044 if (l != end())
1045 {
1046 ++l;
1047 ++n;
1048
1049 while ((l != end()) && key_equal_function(key, l->first))
1050 {
1051 ++l;
1052 ++n;
1053 }
1054 }
1055
1056 return n;
1057 }
1058
1059#if ETL_USING_CPP11
1060 //*********************************************************************
1064 //*********************************************************************
1065 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1066 size_t count(const K& key) const
1067 {
1068 size_t n = 0UL;
1069 const_iterator f = find(key);
1070 const_iterator l = f;
1071
1072 if (l != end())
1073 {
1074 ++l;
1075 ++n;
1076
1077 while ((l != end()) && key_equal_function(key, l->first))
1078 {
1079 ++l;
1080 ++n;
1081 }
1082 }
1083
1084 return n;
1085 }
1086#endif
1087
1088 //*********************************************************************
1092 //*********************************************************************
1093 iterator find(const_key_reference key)
1094 {
1095 size_t index = get_bucket_index(key);
1096
1097 bucket_t* pbucket = pbuckets + index;
1098 bucket_t& bucket = *pbucket;
1099
1100 // Is the bucket not empty?
1101 if (!bucket.empty())
1102 {
1103 // Step though the list until we find the end or an equivalent key.
1104 local_iterator inode = bucket.begin();
1105 local_iterator iend = bucket.end();
1106
1107 while (inode != iend)
1108 {
1109 // Do we have this one?
1110 if (key_equal_function(key, inode->key_value_pair.first))
1111 {
1112 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1113 }
1114
1115 ++inode;
1116 }
1117 }
1118
1119 return end();
1120 }
1121
1122 //*********************************************************************
1126 //*********************************************************************
1127 const_iterator find(const_key_reference key) const
1128 {
1129 size_t index = get_bucket_index(key);
1130
1131 bucket_t* pbucket = pbuckets + index;
1132 bucket_t& bucket = *pbucket;
1133
1134 // Is the bucket not empty?
1135 if (!bucket.empty())
1136 {
1137 // Step though the list until we find the end or an equivalent key.
1138 local_iterator inode = bucket.begin();
1139 local_iterator iend = bucket.end();
1140
1141 while (inode != iend)
1142 {
1143 // Do we have this one?
1144 if (key_equal_function(key, inode->key_value_pair.first))
1145 {
1146 return const_iterator((pbuckets + number_of_buckets), pbucket, inode);
1147 }
1148
1149 ++inode;
1150 }
1151 }
1152
1153 return end();
1154 }
1155
1156#if ETL_USING_CPP11
1157 //*********************************************************************
1161 //*********************************************************************
1162 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1163 iterator find(const K& key)
1164 {
1165 size_t index = get_bucket_index(key);
1166
1167 bucket_t* pbucket = pbuckets + index;
1168 bucket_t& bucket = *pbucket;
1169
1170 // Is the bucket not empty?
1171 if (!bucket.empty())
1172 {
1173 // Step though the list until we find the end or an equivalent key.
1174 local_iterator inode = bucket.begin();
1175 local_iterator iend = bucket.end();
1176
1177 while (inode != iend)
1178 {
1179 // Do we have this one?
1180 if (key_equal_function(key, inode->key_value_pair.first))
1181 {
1182 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1183 }
1184
1185 ++inode;
1186 }
1187 }
1188
1189 return end();
1190 }
1191#endif
1192
1193#if ETL_USING_CPP11
1194 //*********************************************************************
1198 //*********************************************************************
1199 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1200 const_iterator find(const K& key) const
1201 {
1202 size_t index = get_bucket_index(key);
1203
1204 bucket_t* pbucket = pbuckets + index;
1205 bucket_t& bucket = *pbucket;
1206
1207 // Is the bucket not empty?
1208 if (!bucket.empty())
1209 {
1210 // Step though the list until we find the end or an equivalent key.
1211 local_iterator inode = bucket.begin();
1212 local_iterator iend = bucket.end();
1213
1214 while (inode != iend)
1215 {
1216 // Do we have this one?
1217 if (key_equal_function(key, inode->key_value_pair.first))
1218 {
1219 return const_iterator((pbuckets + number_of_buckets), pbucket, inode);
1220 }
1221
1222 ++inode;
1223 }
1224 }
1225
1226 return end();
1227 }
1228#endif
1229
1230 //*********************************************************************
1238 //*********************************************************************
1239 ETL_OR_STD::pair<iterator, iterator> equal_range(const_key_reference key)
1240 {
1241 iterator f = find(key);
1242 iterator l = f;
1243
1244 if (l != end())
1245 {
1246 ++l;
1247
1248 while ((l != end()) && key_equal_function(key, l->first))
1249 {
1250 ++l;
1251 }
1252 }
1253
1254 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1255 }
1256
1257 //*********************************************************************
1265 //*********************************************************************
1266 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const_key_reference key) const
1267 {
1268 const_iterator f = find(key);
1269 const_iterator l = f;
1270
1271 if (l != end())
1272 {
1273 ++l;
1274
1275 while ((l != end()) && key_equal_function(key, l->first))
1276 {
1277 ++l;
1278 }
1279 }
1280
1281 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1282 }
1283
1284#if ETL_USING_CPP11
1285 //*********************************************************************
1293 //*********************************************************************
1294 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1295 ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
1296 {
1297 iterator f = find(key);
1298 iterator l = f;
1299
1300 if (l != end())
1301 {
1302 ++l;
1303
1304 while ((l != end()) && key_equal_function(key, l->first))
1305 {
1306 ++l;
1307 }
1308 }
1309
1310 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1311 }
1312#endif
1313
1314#if ETL_USING_CPP11
1315 //*********************************************************************
1323 //*********************************************************************
1324 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1325 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
1326 {
1327 const_iterator f = find(key);
1328 const_iterator l = f;
1329
1330 if (l != end())
1331 {
1332 ++l;
1333
1334 while ((l != end()) && key_equal_function(key, l->first))
1335 {
1336 ++l;
1337 }
1338 }
1339
1340 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1341 }
1342#endif
1343
1344 //*************************************************************************
1346 //*************************************************************************
1347 size_type size() const
1348 {
1349 return pnodepool->size();
1350 }
1351
1352 //*************************************************************************
1354 //*************************************************************************
1355 size_type max_size() const
1356 {
1357 return pnodepool->max_size();
1358 }
1359
1360 //*************************************************************************
1362 //*************************************************************************
1363 size_type capacity() const
1364 {
1365 return pnodepool->max_size();
1366 }
1367
1368 //*************************************************************************
1370 //*************************************************************************
1371 bool empty() const
1372 {
1373 return pnodepool->empty();
1374 }
1375
1376 //*************************************************************************
1378 //*************************************************************************
1379 bool full() const
1380 {
1381 return pnodepool->full();
1382 }
1383
1384 //*************************************************************************
1387 //*************************************************************************
1388 size_t available() const
1389 {
1390 return pnodepool->available();
1391 }
1392
1393 //*************************************************************************
1396 //*************************************************************************
1397 float load_factor() const
1398 {
1399 return static_cast<float>(size()) / static_cast<float>(bucket_count());
1400 }
1401
1402 //*************************************************************************
1405 //*************************************************************************
1406 hasher hash_function() const
1407 {
1408 return key_hash_function;
1409 }
1410
1411 //*************************************************************************
1414 //*************************************************************************
1415 key_equal key_eq() const
1416 {
1417 return key_equal_function;
1418 }
1419
1420 //*************************************************************************
1422 //*************************************************************************
1424 {
1425 // Skip if doing self assignment
1426 if (this != &rhs)
1427 {
1428 key_hash_function = rhs.hash_function();
1429 key_equal_function = rhs.key_eq();
1430 assign(rhs.cbegin(), rhs.cend());
1431 }
1432
1433 return *this;
1434 }
1435
1436#if ETL_USING_CPP11
1437 //*************************************************************************
1439 //*************************************************************************
1441 {
1442 // Skip if doing self assignment
1443 if (this != &rhs)
1444 {
1445 clear();
1446 key_hash_function = rhs.hash_function();
1447 key_equal_function = rhs.key_eq();
1448 move(rhs.begin(), rhs.end());
1449 }
1450
1451 return *this;
1452 }
1453#endif
1454
1455 //*************************************************************************
1457 //*************************************************************************
1458 bool contains(const_key_reference key) const
1459 {
1460 return find(key) != end();
1461 }
1462
1463#if ETL_USING_CPP11
1464 //*************************************************************************
1466 //*************************************************************************
1467 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1468 bool contains(const K& key) const
1469 {
1470 return find(key) != end();
1471 }
1472#endif
1473
1474 protected:
1475
1476 //*********************************************************************
1478 //*********************************************************************
1479 iunordered_multimap(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1480 : pnodepool(&node_pool_)
1481 , pbuckets(pbuckets_)
1482 , number_of_buckets(number_of_buckets_)
1483 , first(pbuckets)
1484 , last(pbuckets)
1485 , key_hash_function(key_hash_function_)
1486 , key_equal_function(key_equal_function_)
1487 {
1488 }
1489
1490 //*********************************************************************
1492 //*********************************************************************
1494 {
1495 if (!empty())
1496 {
1497 // For each bucket...
1498 for (size_t i = 0UL; i < number_of_buckets; ++i)
1499 {
1500 bucket_t& bucket = pbuckets[i];
1501
1502 if (!bucket.empty())
1503 {
1504 // For each item in the bucket...
1505 local_iterator it = bucket.begin();
1506
1507 while (it != bucket.end())
1508 {
1509 // Destroy the value contents.
1510 it->key_value_pair.~value_type();
1511 ++it;
1512 ETL_DECREMENT_DEBUG_COUNT;
1513 }
1514
1515 // Now it's safe to clear the bucket.
1516 bucket.clear();
1517 }
1518 }
1519
1520 // Now it's safe to clear the entire pool in one go.
1521 pnodepool->release_all();
1522 }
1523
1524 first = pbuckets;
1525 last = first;
1526 }
1527
1528#if ETL_USING_CPP11
1529 //*************************************************************************
1531 //*************************************************************************
1532 void move(iterator b, iterator e)
1533 {
1534 while (b != e)
1535 {
1536 iterator temp = b;
1537 ++temp;
1538 insert(etl::move(*b));
1539 b = temp;
1540 }
1541 }
1542#endif
1543
1544 private:
1545
1546 //*************************************************************************
1548 //*************************************************************************
1549 node_t* allocate_data_node()
1550 {
1551 node_t* (etl::ipool::*func)() = &etl::ipool::allocate<node_t>;
1552 return (pnodepool->*func)();
1553 }
1554
1555 //*********************************************************************
1557 //*********************************************************************
1558 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1559 {
1560 if (size() == 1)
1561 {
1562 first = pbucket;
1563 last = pbucket;
1564 }
1565 else
1566 {
1567 if (pbucket < first)
1568 {
1569 first = pbucket;
1570 }
1571 else if (pbucket > last)
1572 {
1573 last = pbucket;
1574 }
1575 }
1576 }
1577
1578 //*********************************************************************
1580 //*********************************************************************
1581 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1582 {
1583 if (empty())
1584 {
1585 first = pbuckets;
1586 last = pbuckets;
1587 }
1588 else
1589 {
1590 if (pbucket == first)
1591 {
1592 // We erased the first so, we need to search again from where we
1593 // erased.
1594 while (first->empty())
1595 {
1596 ++first;
1597 }
1598 }
1599 else if (pbucket == last)
1600 {
1601 // We erased the last, so we need to search again. Start from the
1602 // first, go no further than the current last.
1603 pbucket = first;
1604 bucket_t* pend = last;
1605
1606 last = first;
1607
1608 while (pbucket != pend)
1609 {
1610 if (!pbucket->empty())
1611 {
1612 last = pbucket;
1613 }
1614
1615 ++pbucket;
1616 }
1617 }
1618 }
1619 }
1620
1621 //*********************************************************************
1623 //*********************************************************************
1624 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1625 {
1626 local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket.
1627 icurrent->key_value_pair.~value_type(); // Destroy the value.
1628 pnodepool->release(&*icurrent); // Release it back to the pool.
1629 adjust_first_last_markers_after_erase(&bucket);
1630 ETL_DECREMENT_DEBUG_COUNT;
1631
1632 return inext;
1633 }
1634
1635 // Disable copy construction.
1637
1639 pool_t* pnodepool;
1640
1642 bucket_t* pbuckets;
1643
1645 const size_t number_of_buckets;
1646
1648 bucket_t* first;
1649 bucket_t* last;
1650
1652 hasher key_hash_function;
1653
1655 key_equal key_equal_function;
1656
1658 ETL_DECLARE_DEBUG_COUNT;
1659
1660 //*************************************************************************
1662 //*************************************************************************
1663#if defined(ETL_POLYMORPHIC_UNORDERED_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS)
1664
1665 public:
1666
1667 virtual ~iunordered_multimap() {}
1668#else
1669
1670 protected:
1671
1673#endif
1674 };
1675
1676 //***************************************************************************
1682 //***************************************************************************
1683 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1685 {
1686 const bool sizes_match = (lhs.size() == rhs.size());
1687 bool elements_match = true;
1688
1690
1691 if (sizes_match)
1692 {
1693 itr_t l_begin = lhs.begin();
1694 itr_t l_end = lhs.end();
1695
1696 while ((l_begin != l_end) && elements_match)
1697 {
1698 const TKey key = l_begin->first;
1699 const T l_value = l_begin->second;
1700
1701 // See if the lhs keys exist in the rhs.
1702 ETL_OR_STD::pair<itr_t, itr_t> l_range = lhs.equal_range(key);
1703 ETL_OR_STD::pair<itr_t, itr_t> r_range = rhs.equal_range(key);
1704
1705 if (r_range.first != rhs.end())
1706 {
1707 bool distance_match = (etl::distance(l_range.first, l_range.second) == etl::distance(r_range.first, r_range.second));
1708
1709 if (distance_match)
1710 {
1711 elements_match = etl::is_permutation(l_range.first, l_range.second, r_range.first, r_range.second);
1712 }
1713 else
1714 {
1715 elements_match = false;
1716 }
1717 }
1718 else
1719 {
1720 elements_match = false;
1721 }
1722
1723 ++l_begin;
1724 }
1725 }
1726
1727 return (sizes_match && elements_match);
1728 }
1729
1730 //***************************************************************************
1736 //***************************************************************************
1737 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1742
1743 //*************************************************************************
1746 //*************************************************************************
1747 template <typename TKey, typename TValue, const size_t MAX_SIZE_, const size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>,
1748 typename TKeyEqual = etl::equal_to<TKey> >
1749 class unordered_multimap : public etl::iunordered_multimap<TKey, TValue, THash, TKeyEqual>
1750 {
1751 private:
1752
1754
1755 public:
1756
1757 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
1758 static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_;
1759
1760 //*************************************************************************
1762 //*************************************************************************
1763 unordered_multimap(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1764 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1765 {
1766 }
1767
1768 //*************************************************************************
1770 //*************************************************************************
1772 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1773 {
1774 // Skip if doing self assignment
1775 if (this != &other)
1776 {
1777 base::assign(other.cbegin(), other.cend());
1778 }
1779 }
1780
1781#if ETL_USING_CPP11
1782 //*************************************************************************
1784 //*************************************************************************
1786 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1787 {
1788 // Skip if doing self assignment
1789 if (this != &other)
1790 {
1791 base::move(other.begin(), other.end());
1792 }
1793 }
1794#endif
1795
1796 //*************************************************************************
1801 //*************************************************************************
1802 template <typename TIterator>
1803 unordered_multimap(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1804 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1805 {
1806 base::assign(first_, last_);
1807 }
1808
1809#if ETL_HAS_INITIALIZER_LIST
1810 //*************************************************************************
1812 //*************************************************************************
1813 unordered_multimap(std::initializer_list<ETL_OR_STD::pair<TKey, TValue>> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1814 : base(node_pool, buckets, MAX_BUCKETS_, hash, equal)
1815 {
1816 base::assign(init.begin(), init.end());
1817 }
1818#endif
1819
1820 //*************************************************************************
1822 //*************************************************************************
1824 {
1826 }
1827
1828 //*************************************************************************
1830 //*************************************************************************
1832 {
1833 base::operator=(rhs);
1834
1835 return *this;
1836 }
1837
1838#if ETL_USING_CPP11
1839 //*************************************************************************
1841 //*************************************************************************
1842 unordered_multimap& operator=(unordered_multimap&& rhs)
1843 {
1844 base::operator=(etl::move(rhs));
1845
1846 return *this;
1847 }
1848#endif
1849
1850 private:
1851
1854
1856 typename base::bucket_t buckets[MAX_BUCKETS_];
1857 };
1858
1859 //*************************************************************************
1861 //*************************************************************************
1862#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
1863 template <typename... TPairs>
1864 unordered_multimap(TPairs...)
1865 -> unordered_multimap<typename etl::nth_type_t<0, TPairs...>::first_type, typename etl::nth_type_t<0, TPairs...>::second_type, sizeof...(TPairs)>;
1866#endif
1867
1868 //*************************************************************************
1870 //*************************************************************************
1871#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
1872 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey>, typename... TPairs>
1873 constexpr auto
1874 make_unordered_multimap(TPairs&&... pairs) -> etl::unordered_multimap<TKey, T, sizeof...(TPairs), sizeof...(TPairs), THash, TKeyEqual>
1875 {
1876 return {etl::forward<TPairs>(pairs)...};
1877 }
1878#endif
1879} // namespace etl
1880
1881#endif
bool empty() const
Returns true if the list has no elements.
Definition intrusive_forward_list.h:250
void clear()
Clears the intrusive_forward_list.
Definition intrusive_forward_list.h:154
Definition intrusive_forward_list.h:457
iterator insert_after(iterator position, value_type &value)
Definition intrusive_forward_list.h:760
iterator end()
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:713
iterator before_begin()
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:689
iterator begin()
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:673
Definition unordered_multimap.h:330
Definition unordered_multimap.h:189
Definition unordered_multimap.h:1750
unordered_multimap(const unordered_multimap &other)
Copy constructor.
Definition unordered_multimap.h:1771
unordered_multimap & operator=(const unordered_multimap &rhs)
Assignment operator.
Definition unordered_multimap.h:1831
unordered_multimap(TIterator first_, TIterator last_, const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Definition unordered_multimap.h:1803
unordered_multimap(const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Default constructor.
Definition unordered_multimap.h:1763
~unordered_multimap()
Destructor.
Definition unordered_multimap.h:1823
ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2)
Definition algorithm.h:1801
ETL_CONSTEXPR14 bool operator!=(const etl::bitset< Active_Bits, TElement > &lhs, const etl::bitset< Active_Bits, TElement > &rhs) ETL_NOEXCEPT
Definition bitset_new.h:2529
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
T * allocate()
Definition ipool.h:333
Definition ipool.h:109
Definition pool.h:54
iterator end()
Definition unordered_multimap.h:542
iunordered_multimap & operator=(const iunordered_multimap &rhs)
Assignment operator.
Definition unordered_multimap.h:1423
const_local_iterator cend(size_t i) const
Definition unordered_multimap.h:587
const_local_iterator cbegin(size_t i) const
Definition unordered_multimap.h:533
float load_factor() const
Definition unordered_multimap.h:1397
void assign(TIterator first_, TIterator last_)
Definition unordered_multimap.h:666
size_t available() const
Definition unordered_multimap.h:1388
const_local_iterator end(size_t i) const
Definition unordered_multimap.h:578
key_equal key_eq() const
Definition unordered_multimap.h:1415
const_iterator find(const_key_reference key) const
Definition unordered_multimap.h:1127
bool contains(const_key_reference key) const
Check if the unordered_multimap contains the key.
Definition unordered_multimap.h:1458
bool empty() const
Checks to see if the unordered_multimap is empty.
Definition unordered_multimap.h:1371
size_type bucket_count() const
Definition unordered_multimap.h:651
iterator insert(const_reference key_value_pair)
Definition unordered_multimap.h:689
iterator erase(const_iterator ielement)
Definition unordered_multimap.h:946
local_iterator end(size_t i)
Definition unordered_multimap.h:569
size_type capacity() const
Gets the maximum possible size of the unordered_multimap.
Definition unordered_multimap.h:1363
const_local_iterator begin(size_t i) const
Definition unordered_multimap.h:522
void initialise()
Initialise the unordered_multimap.
Definition unordered_multimap.h:1493
const_iterator end() const
Definition unordered_multimap.h:551
size_t count(const_key_reference key) const
Definition unordered_multimap.h:1038
iterator find(const_key_reference key)
Definition unordered_multimap.h:1093
size_type size() const
Gets the size of the unordered_multimap.
Definition unordered_multimap.h:1347
void clear()
Clears the unordered_multimap.
Definition unordered_multimap.h:1028
const_iterator begin() const
Definition unordered_multimap.h:493
hasher hash_function() const
Definition unordered_multimap.h:1406
iterator erase(const_iterator first_, const_iterator last_)
Definition unordered_multimap.h:974
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(const_key_reference key) const
Definition unordered_multimap.h:1266
iterator insert(const_iterator, const_reference key_value_pair)
Definition unordered_multimap.h:834
size_type max_size() const
Gets the maximum possible size of the unordered_multimap.
Definition unordered_multimap.h:1355
const_iterator cbegin() const
Definition unordered_multimap.h:502
local_iterator begin(size_t i)
Definition unordered_multimap.h:511
ETL_OR_STD::pair< iterator, iterator > equal_range(const_key_reference key)
Definition unordered_multimap.h:1239
~iunordered_multimap()
Destructor.
Definition unordered_multimap.h:1672
iunordered_multimap(pool_t &node_pool_, bucket_t *pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
Constructor.
Definition unordered_multimap.h:1479
size_type bucket_size(const_key_reference key) const
Definition unordered_multimap.h:617
size_type max_bucket_count() const
Definition unordered_multimap.h:642
const_iterator cend() const
Definition unordered_multimap.h:560
void insert(TIterator first_, TIterator last_)
Definition unordered_multimap.h:862
bool full() const
Checks to see if the unordered_multimap is full.
Definition unordered_multimap.h:1379
size_t erase(const_key_reference key)
Definition unordered_multimap.h:876
size_type get_bucket_index(const_key_reference key) const
Definition unordered_multimap.h:596
iterator begin()
Definition unordered_multimap.h:484
Definition unordered_multimap.h:129
Definition unordered_multimap.h:70
Definition unordered_multimap.h:84
Definition unordered_multimap.h:112
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967
iterator
Definition iterator.h:424
Definition unordered_multimap.h:157