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 "parameter_type.h"
46#include "placement_new.h"
47#include "pool.h"
48#include "type_traits.h"
49#include "utility.h"
50#include "vector.h"
51
53
54#include <stddef.h>
55
56//*****************************************************************************
60//*****************************************************************************
61
62namespace etl
63{
64 //***************************************************************************
67 //***************************************************************************
68 class unordered_multimap_exception : public etl::exception
69 {
70 public:
71
72 unordered_multimap_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
73 : etl::exception(reason_, file_name_, line_number_)
74 {
75 }
76 };
77
78 //***************************************************************************
81 //***************************************************************************
82 class unordered_multimap_full : public etl::unordered_multimap_exception
83 {
84 public:
85
86 unordered_multimap_full(string_type file_name_, numeric_type line_number_)
87 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:full", ETL_UNORDERED_MULTIMAP_FILE_ID"A"), file_name_, line_number_)
88 {
89 }
90 };
91
92 //***************************************************************************
95 //***************************************************************************
96 class unordered_multimap_out_of_range : public etl::unordered_multimap_exception
97 {
98 public:
99
100 unordered_multimap_out_of_range(string_type file_name_, numeric_type line_number_)
101 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:range", ETL_UNORDERED_MULTIMAP_FILE_ID"B"), file_name_, line_number_)
102 {
103 }
104 };
105
106 //***************************************************************************
109 //***************************************************************************
110 class unordered_multimap_iterator : public etl::unordered_multimap_exception
111 {
112 public:
113
114 unordered_multimap_iterator(string_type file_name_, numeric_type line_number_)
115 : etl::unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:iterator", ETL_UNORDERED_MULTIMAP_FILE_ID"C"), file_name_, line_number_)
116 {
117 }
118 };
119
120 //***************************************************************************
125 //***************************************************************************
126 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey> >
128 {
129 public:
130
131 typedef ETL_OR_STD::pair<const TKey, T> value_type;
132
133 typedef TKey key_type;
134 typedef T mapped_type;
135 typedef THash hasher;
136 typedef TKeyEqual key_equal;
137 typedef value_type& reference;
138 typedef const value_type& const_reference;
139#if ETL_USING_CPP11
140 typedef value_type&& rvalue_reference;
141#endif
142 typedef value_type* pointer;
143 typedef const value_type* const_pointer;
144 typedef size_t size_type;
145
146 typedef const key_type& const_key_reference;
147#if ETL_USING_CPP11
148 typedef key_type&& rvalue_key_reference;
149#endif
150
151 typedef etl::forward_link<0> link_t; // Default link.
152
153 //*********************************************************************
154 // The nodes that store the elements.
155 struct node_t : public link_t
156 {
157 node_t(const_reference key_value_pair_)
158 : key_value_pair(key_value_pair_)
159 {
160 }
161
162 value_type key_value_pair;
163 };
164
165 friend bool operator==(const node_t& lhs, const node_t& rhs)
166 {
167 return (lhs.key_value_pair.first == rhs.key_value_pair.first) && (lhs.key_value_pair.second == rhs.key_value_pair.second);
168 }
169
170 friend bool operator!=(const node_t& lhs, const node_t& rhs)
171 {
172 return !(lhs == rhs);
173 }
174
175 protected:
176
178 typedef etl::ipool pool_t;
179
180 public:
181
182 // Local iterators iterate over one bucket.
183 typedef typename bucket_t::iterator local_iterator;
184 typedef typename bucket_t::const_iterator const_local_iterator;
185
186 //*********************************************************************
187 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, T>
188 {
189 public:
190
191 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, T>::value_type value_type;
192 typedef typename iunordered_multimap::key_type key_type;
193 typedef typename iunordered_multimap::mapped_type mapped_type;
194 typedef typename iunordered_multimap::hasher hasher;
195 typedef typename iunordered_multimap::key_equal key_equal;
196 typedef typename iunordered_multimap::reference reference;
197 typedef typename iunordered_multimap::const_reference const_reference;
198 typedef typename iunordered_multimap::pointer pointer;
199 typedef typename iunordered_multimap::const_pointer const_pointer;
200 typedef typename iunordered_multimap::size_type size_type;
201
202 friend class iunordered_multimap;
203 friend class const_iterator;
204
205 //*********************************
206 iterator() {}
207
208 //*********************************
209 iterator(const iterator& other)
210 : pbuckets_end(other.pbuckets_end)
211 , pbucket(other.pbucket)
212 , inode(other.inode)
213 {
214 }
215
216 //*********************************
217 iterator& operator++()
218 {
219 ++inode;
220
221 // The end of this node list?
222 if (inode == pbucket->end())
223 {
224 // Search for the next non-empty bucket.
225 ++pbucket;
226 while ((pbucket != pbuckets_end) && (pbucket->empty()))
227 {
228 ++pbucket;
229 }
230
231 // If not past the end, get the first node in the bucket.
232 if (pbucket != pbuckets_end)
233 {
234 inode = pbucket->begin();
235 }
236 }
237
238 return *this;
239 }
240
241 //*********************************
242 iterator operator++(int)
243 {
244 iterator temp(*this);
245 operator++();
246 return temp;
247 }
248
249 //*********************************
250 iterator& operator=(const iterator& other)
251 {
252 pbuckets_end = other.pbuckets_end;
253 pbucket = other.pbucket;
254 inode = other.inode;
255 return *this;
256 }
257
258 //*********************************
259 reference operator*() const
260 {
261 return inode->key_value_pair;
262 }
263
264 //*********************************
265 pointer operator&() const
266 {
267 return &(inode->key_value_pair);
268 }
269
270 //*********************************
271 pointer operator->() const
272 {
273 return &(inode->key_value_pair);
274 }
275
276 //*********************************
277 friend bool operator==(const iterator& lhs, const iterator& rhs)
278 {
279 return lhs.compare(rhs);
280 }
281
282 //*********************************
283 friend bool operator!=(const iterator& lhs, const iterator& rhs)
284 {
285 return !(lhs == rhs);
286 }
287
288 private:
289
290 //*********************************
291 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
292 : pbuckets_end(pbuckets_end_)
293 , pbucket(pbucket_)
294 , inode(inode_)
295 {
296 }
297
298 //*********************************
299 bool compare(const iterator& rhs) const
300 {
301 return rhs.inode == inode;
302 }
303
304 //*********************************
305 bucket_t& get_bucket()
306 {
307 return *pbucket;
308 }
309
310 //*********************************
311 bucket_t*& get_bucket_list_iterator()
312 {
313 return pbucket;
314 }
315
316 //*********************************
317 local_iterator get_local_iterator()
318 {
319 return inode;
320 }
321
322 bucket_t* pbuckets_end;
323 bucket_t* pbucket;
324 local_iterator inode;
325 };
326
327 //*********************************************************************
328 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>
329 {
330 public:
331
332 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>::value_type value_type;
333 typedef typename iunordered_multimap::key_type key_type;
334 typedef typename iunordered_multimap::mapped_type mapped_type;
335 typedef typename iunordered_multimap::hasher hasher;
336 typedef typename iunordered_multimap::key_equal key_equal;
337 typedef typename iunordered_multimap::reference reference;
338 typedef typename iunordered_multimap::const_reference const_reference;
339 typedef typename iunordered_multimap::pointer pointer;
340 typedef typename iunordered_multimap::const_pointer const_pointer;
341 typedef typename iunordered_multimap::size_type size_type;
342
343 friend class iunordered_multimap;
344 friend class iterator;
345
346 //*********************************
347 const_iterator() {}
348
349 //*********************************
350 const_iterator(const typename iunordered_multimap::iterator& other)
351 : pbuckets_end(other.pbuckets_end)
352 , pbucket(other.pbucket)
353 , inode(other.inode)
354 {
355 }
356
357 //*********************************
358 const_iterator(const const_iterator& other)
359 : pbuckets_end(other.pbuckets_end)
360 , pbucket(other.pbucket)
361 , inode(other.inode)
362 {
363 }
364
365 //*********************************
366 const_iterator& operator++()
367 {
368 ++inode;
369
370 // The end of this node list?
371 if (inode == pbucket->end())
372 {
373 // Search for the next non-empty bucket.
374
375 ++pbucket;
376 while ((pbucket != pbuckets_end) && (pbucket->empty()))
377 {
378 ++pbucket;
379 }
380
381 // If not past the end, get the first node in the bucket.
382 if (pbucket != pbuckets_end)
383 {
384 inode = pbucket->begin();
385 }
386 }
387
388 return *this;
389 }
390
391 //*********************************
392 const_iterator operator++(int)
393 {
394 const_iterator temp(*this);
395 operator++();
396 return temp;
397 }
398
399 //*********************************
400 const_iterator& operator=(const const_iterator& other)
401 {
402 pbuckets_end = other.pbuckets_end;
403 pbucket = other.pbucket;
404 inode = other.inode;
405 return *this;
406 }
407
408 //*********************************
409 const_reference operator*() const
410 {
411 return inode->key_value_pair;
412 }
413
414 //*********************************
415 const_pointer operator&() const
416 {
417 return &(inode->key_value_pair);
418 }
419
420 //*********************************
421 const_pointer operator->() const
422 {
423 return &(inode->key_value_pair);
424 }
425
426 //*********************************
427 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
428 {
429 return lhs.compare(rhs);
430 }
431
432 //*********************************
433 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
434 {
435 return !(lhs == rhs);
436 }
437
438 private:
439
440 //*********************************
441 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
442 : pbuckets_end(pbuckets_end_)
443 , pbucket(pbucket_)
444 , inode(inode_)
445 {
446 }
447
448 //*********************************
449 bool compare(const const_iterator& rhs) const
450 {
451 return rhs.inode == inode;
452 }
453
454 //*********************************
455 bucket_t& get_bucket()
456 {
457 return *pbucket;
458 }
459
460 //*********************************
461 bucket_t*& get_bucket_list_iterator()
462 {
463 return pbucket;
464 }
465
466 //*********************************
467 local_iterator get_local_iterator()
468 {
469 return inode;
470 }
471
472 bucket_t* pbuckets_end;
473 bucket_t* pbucket;
474 local_iterator inode;
475 };
476
477 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
478
479 //*********************************************************************
482 //*********************************************************************
483 iterator begin()
484 {
485 return iterator((pbuckets + number_of_buckets), first, first->begin());
486 }
487
488 //*********************************************************************
491 //*********************************************************************
492 const_iterator begin() const
493 {
494 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
495 }
496
497 //*********************************************************************
500 //*********************************************************************
501 const_iterator cbegin() const
502 {
503 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
504 }
505
506 //*********************************************************************
509 //*********************************************************************
510 local_iterator begin(size_t i)
511 {
512 return pbuckets[i].begin();
513 }
514
515 //*********************************************************************
520 //*********************************************************************
521 const_local_iterator begin(size_t i) const
522 {
523 return pbuckets[i].cbegin();
524 }
525
526 //*********************************************************************
531 //*********************************************************************
532 const_local_iterator cbegin(size_t i) const
533 {
534 return pbuckets[i].cbegin();
535 }
536
537 //*********************************************************************
540 //*********************************************************************
541 iterator end()
542 {
543 return iterator((pbuckets + number_of_buckets), last, last->end());
544 }
545
546 //*********************************************************************
549 //*********************************************************************
550 const_iterator end() const
551 {
552 return const_iterator((pbuckets + number_of_buckets), last, last->end());
553 }
554
555 //*********************************************************************
558 //*********************************************************************
559 const_iterator cend() const
560 {
561 return const_iterator((pbuckets + number_of_buckets), last, last->end());
562 }
563
564 //*********************************************************************
567 //*********************************************************************
568 local_iterator end(size_t i)
569 {
570 return pbuckets[i].end();
571 }
572
573 //*********************************************************************
576 //*********************************************************************
577 const_local_iterator end(size_t i) const
578 {
579 return pbuckets[i].cend();
580 }
581
582 //*********************************************************************
585 //*********************************************************************
586 const_local_iterator cend(size_t i) const
587 {
588 return pbuckets[i].cend();
589 }
590
591 //*********************************************************************
594 //*********************************************************************
595 size_type get_bucket_index(const_key_reference key) const
596 {
597 return key_hash_function(key) % number_of_buckets;
598 }
599
600#if ETL_USING_CPP11
601 //*********************************************************************
604 //*********************************************************************
605 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
606 size_type get_bucket_index(const K& key) const
607 {
608 return key_hash_function(key) % number_of_buckets;
609 }
610#endif
611
612 //*********************************************************************
615 //*********************************************************************
616 size_type bucket_size(const_key_reference key) const
617 {
618 size_t index = bucket(key);
619
620 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
621 }
622
623#if ETL_USING_CPP11
624 //*********************************************************************
627 //*********************************************************************
628 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
629 size_type bucket_size(const K& key) const
630 {
631 size_t index = bucket(key);
632
633 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
634 }
635#endif
636
637 //*********************************************************************
640 //*********************************************************************
641 size_type max_bucket_count() const
642 {
643 return number_of_buckets;
644 }
645
646 //*********************************************************************
649 //*********************************************************************
650 size_type bucket_count() const
651 {
652 return number_of_buckets;
653 }
654
655 //*********************************************************************
663 //*********************************************************************
664 template <typename TIterator>
665 void assign(TIterator first_, TIterator last_)
666 {
667#if ETL_IS_DEBUG_BUILD
668 difference_type d = etl::distance(first_, last_);
669 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_multimap_iterator));
670 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_multimap_full));
671#endif
672
673 clear();
674
675 while (first_ != last_)
676 {
677 insert(*first_);
678 ++first_;
679 }
680 }
681
682 //*********************************************************************
687 //*********************************************************************
688 iterator insert(const_reference key_value_pair)
689 {
691
692 iterator result = end();
693
694 const_key_reference key = key_value_pair.first;
695
696 // Get the hash index.
697 size_t index = get_bucket_index(key);
698
699 // Get the bucket & bucket iterator.
700 bucket_t* pbucket = pbuckets + index;
701 bucket_t& bucket = *pbucket;
702
703 // The first one in the bucket?
704 if (bucket.empty())
705 {
706 // Get a new node.
707 node_t* node = allocate_data_node();
708 node->clear();
709 ::new (&node->key_value_pair) value_type(key_value_pair);
710 ETL_INCREMENT_DEBUG_COUNT;
711
712 // Just add the pointer to the bucket;
713 bucket.insert_after(bucket.before_begin(), *node);
714 adjust_first_last_markers_after_insert(pbucket);
715
716 result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
717 }
718 else
719 {
720 // Step though the bucket looking for a place to insert.
721 local_iterator inode_previous = bucket.before_begin();
722 local_iterator inode = bucket.begin();
723
724 while (inode != bucket.end())
725 {
726 // Do we already have this key?
727 if (key_equal_function(inode->key_value_pair.first, key))
728 {
729 break;
730 }
731
732 ++inode_previous;
733 ++inode;
734 }
735
736 // Get a new node.
737 node_t* node = allocate_data_node();
738 node->clear();
739 ::new (&node->key_value_pair) value_type(key_value_pair);
740 ETL_INCREMENT_DEBUG_COUNT;
741
742 // Add the node to the end of the bucket;
743 bucket.insert_after(inode_previous, *node);
744 adjust_first_last_markers_after_insert(&bucket);
745 ++inode_previous;
746
747 result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
748 }
749
750 return result;
751 }
752
753#if ETL_USING_CPP11
754 //*********************************************************************
759 //*********************************************************************
760 iterator insert(rvalue_reference key_value_pair)
761 {
763
764 iterator result = end();
765
766 const_key_reference key = key_value_pair.first;
767
768 // Get the hash index.
769 size_t index = get_bucket_index(key);
770
771 // Get the bucket & bucket iterator.
772 bucket_t* pbucket = pbuckets + index;
773 bucket_t& bucket = *pbucket;
774
775 // The first one in the bucket?
776 if (bucket.empty())
777 {
778 // Get a new node.
779 node_t* node = allocate_data_node();
780 node->clear();
781 ::new (&node->key_value_pair) value_type(etl::move(key_value_pair));
782 ETL_INCREMENT_DEBUG_COUNT;
783
784 // Just add the pointer to the bucket;
785 bucket.insert_after(bucket.before_begin(), *node);
786 adjust_first_last_markers_after_insert(pbucket);
787
788 result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
789 }
790 else
791 {
792 // Step though the bucket looking for a place to insert.
793 local_iterator inode_previous = bucket.before_begin();
794 local_iterator inode = bucket.begin();
795
796 while (inode != bucket.end())
797 {
798 // Do we already have this key?
799 if (key_equal_function(inode->key_value_pair.first, key))
800 {
801 break;
802 }
803
804 ++inode_previous;
805 ++inode;
806 }
807
808 // Get a new node.
809 node_t* node = allocate_data_node();
810 node->clear();
811 ::new (&node->key_value_pair) value_type(etl::move(key_value_pair));
812 ETL_INCREMENT_DEBUG_COUNT;
813
814 // Add the node to the end of the bucket;
815 bucket.insert_after(inode_previous, *node);
816 adjust_first_last_markers_after_insert(&bucket);
817 ++inode_previous;
818
819 result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
820 }
821
822 return result;
823 }
824#endif
825
826 //*********************************************************************
832 //*********************************************************************
833 iterator insert(const_iterator, const_reference key_value_pair)
834 {
835 return insert(key_value_pair);
836 }
837
838#if ETL_USING_CPP11
839 //*********************************************************************
845 //*********************************************************************
846 iterator insert(const_iterator, rvalue_reference key_value_pair)
847 {
848 return insert(etl::move(key_value_pair));
849 }
850#endif
851
852 //*********************************************************************
859 //*********************************************************************
860 template <class TIterator>
861 void insert(TIterator first_, TIterator last_)
862 {
863 while (first_ != last_)
864 {
865 insert(*first_);
866 ++first_;
867 }
868 }
869
870#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
871 //*********************************************************************
874 //*********************************************************************
875 template <typename... Args>
876 iterator emplace(Args&&... args)
877 {
879
880 iterator result = end();
881
882 // Construct the value in a temporary node to get the key for hashing.
883 node_t* node = allocate_data_node();
884 node->clear();
885 ::new ((void*)etl::addressof(node->key_value_pair)) value_type(etl::forward<Args>(args)...);
886 ETL_INCREMENT_DEBUG_COUNT;
887
888 const_key_reference key = node->key_value_pair.first;
889
890 // Get the hash index.
891 size_t index = get_bucket_index(key);
892
893 // Get the bucket & bucket iterator.
894 bucket_t* pbucket = pbuckets + index;
895 bucket_t& bucket = *pbucket;
896
897 // The first one in the bucket?
898 if (bucket.empty())
899 {
900 // Just add the pointer to the bucket;
901 bucket.insert_after(bucket.before_begin(), *node);
902 adjust_first_last_markers_after_insert(pbucket);
903
904 result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
905 }
906 else
907 {
908 // Step though the bucket looking for a place to insert.
909 local_iterator inode_previous = bucket.before_begin();
910 local_iterator inode = bucket.begin();
911
912 while (inode != bucket.end())
913 {
914 // Do we already have this key?
915 if (key_equal_function(inode->key_value_pair.first, key))
916 {
917 break;
918 }
919
920 ++inode_previous;
921 ++inode;
922 }
923
924 // Add the node to the end of the bucket;
925 bucket.insert_after(inode_previous, *node);
926 adjust_first_last_markers_after_insert(&bucket);
927 ++inode_previous;
928
929 result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
930 }
931
932 return result;
933 }
934#endif
935
936 //*********************************************************************
938 //*********************************************************************
939 iterator emplace(const_reference key_value_pair)
940 {
941 return insert(key_value_pair);
942 }
943
944 //*********************************************************************
948 //*********************************************************************
949 size_t erase(const_key_reference key)
950 {
951 size_t n = 0UL;
952 size_t bucket_id = get_bucket_index(key);
953
954 bucket_t& bucket = pbuckets[bucket_id];
955
956 local_iterator iprevious = bucket.before_begin();
957 local_iterator icurrent = bucket.begin();
958
959 while (icurrent != bucket.end())
960 {
961 if (key_equal_function(icurrent->key_value_pair.first, key))
962 {
963 delete_data_node(iprevious, icurrent, bucket);
964 ++n;
965 icurrent = iprevious;
966 }
967 else
968 {
969 ++iprevious;
970 }
971
972 ++icurrent;
973 }
974
975 return n;
976 }
977
978#if ETL_USING_CPP11
979 //*********************************************************************
983 //*********************************************************************
984 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
985 size_t erase(const K& key)
986 {
987 size_t n = 0UL;
988 size_t bucket_id = get_bucket_index(key);
989
990 bucket_t& bucket = pbuckets[bucket_id];
991
992 local_iterator iprevious = bucket.before_begin();
993 local_iterator icurrent = bucket.begin();
994
995 while (icurrent != bucket.end())
996 {
997 if (key_equal_function(icurrent->key_value_pair.first, key))
998 {
999 delete_data_node(iprevious, icurrent, bucket);
1000 ++n;
1001 icurrent = iprevious;
1002 }
1003 else
1004 {
1005 ++iprevious;
1006 }
1007
1008 ++icurrent;
1009 }
1010
1011 return n;
1012 }
1013#endif
1014
1015 //*********************************************************************
1018 //*********************************************************************
1019 iterator erase(const_iterator ielement)
1020 {
1021 // Make a note of the next one.
1022 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1023 ++inext;
1024
1025 bucket_t& bucket = ielement.get_bucket();
1026 local_iterator iprevious = bucket.before_begin();
1027 local_iterator icurrent = ielement.get_local_iterator();
1028
1029 // Find the node previous to the one we're interested in.
1030 while (iprevious->etl_next != &*icurrent)
1031 {
1032 ++iprevious;
1033 }
1034
1035 delete_data_node(iprevious, icurrent, bucket);
1036
1037 return inext;
1038 }
1039
1040 //*********************************************************************
1046 //*********************************************************************
1047 iterator erase(const_iterator first_, const_iterator last_)
1048 {
1049 // Erasing everything?
1050 if ((first_ == begin()) && (last_ == end()))
1051 {
1052 clear();
1053 return end();
1054 }
1055
1056 // Get the starting point.
1057 bucket_t* pbucket = first_.get_bucket_list_iterator();
1058 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1059 local_iterator iprevious = pbucket->before_begin();
1060 local_iterator icurrent = first_.get_local_iterator();
1061 local_iterator iend = last_.get_local_iterator(); // Note: May not be in the same bucket as
1062 // icurrent.
1063
1064 // Find the node previous to the first one.
1065 while (iprevious->etl_next != &*icurrent)
1066 {
1067 ++iprevious;
1068 }
1069
1070 // Remember the item before the first erased one.
1071 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1072
1073 // Until we reach the end.
1074 while ((icurrent != iend) || (pbucket != pend_bucket))
1075 {
1076 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1077
1078 // Have we not reached the end?
1079 if ((icurrent != iend) || (pbucket != pend_bucket))
1080 {
1081 // At the end of this bucket?
1082 if ((icurrent == pbucket->end()))
1083 {
1084 // Find the next non-empty one.
1085 do {
1086 ++pbucket;
1087 } while (pbucket->empty());
1088
1089 iprevious = pbucket->before_begin();
1090 icurrent = pbucket->begin();
1091 }
1092 }
1093 }
1094
1095 return ++ibefore_erased;
1096 }
1097
1098 //*************************************************************************
1100 //*************************************************************************
1101 void clear()
1102 {
1103 initialise();
1104 }
1105
1106 //*********************************************************************
1110 //*********************************************************************
1111 size_t count(const_key_reference key) const
1112 {
1113 size_t n = 0UL;
1114 const_iterator f = find(key);
1115 const_iterator l = f;
1116
1117 if (l != end())
1118 {
1119 ++l;
1120 ++n;
1121
1122 while ((l != end()) && key_equal_function(key, l->first))
1123 {
1124 ++l;
1125 ++n;
1126 }
1127 }
1128
1129 return n;
1130 }
1131
1132#if ETL_USING_CPP11
1133 //*********************************************************************
1137 //*********************************************************************
1138 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1139 size_t count(const K& key) const
1140 {
1141 size_t n = 0UL;
1142 const_iterator f = find(key);
1143 const_iterator l = f;
1144
1145 if (l != end())
1146 {
1147 ++l;
1148 ++n;
1149
1150 while ((l != end()) && key_equal_function(key, l->first))
1151 {
1152 ++l;
1153 ++n;
1154 }
1155 }
1156
1157 return n;
1158 }
1159#endif
1160
1161 //*********************************************************************
1165 //*********************************************************************
1166 iterator find(const_key_reference key)
1167 {
1168 size_t index = get_bucket_index(key);
1169
1170 bucket_t* pbucket = pbuckets + index;
1171 bucket_t& bucket = *pbucket;
1172
1173 // Is the bucket not empty?
1174 if (!bucket.empty())
1175 {
1176 // Step though the list until we find the end or an equivalent key.
1177 local_iterator inode = bucket.begin();
1178 local_iterator iend = bucket.end();
1179
1180 while (inode != iend)
1181 {
1182 // Do we have this one?
1183 if (key_equal_function(key, inode->key_value_pair.first))
1184 {
1185 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1186 }
1187
1188 ++inode;
1189 }
1190 }
1191
1192 return end();
1193 }
1194
1195 //*********************************************************************
1199 //*********************************************************************
1200 const_iterator find(const_key_reference 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
1229#if ETL_USING_CPP11
1230 //*********************************************************************
1234 //*********************************************************************
1235 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1236 iterator find(const K& key)
1237 {
1238 size_t index = get_bucket_index(key);
1239
1240 bucket_t* pbucket = pbuckets + index;
1241 bucket_t& bucket = *pbucket;
1242
1243 // Is the bucket not empty?
1244 if (!bucket.empty())
1245 {
1246 // Step though the list until we find the end or an equivalent key.
1247 local_iterator inode = bucket.begin();
1248 local_iterator iend = bucket.end();
1249
1250 while (inode != iend)
1251 {
1252 // Do we have this one?
1253 if (key_equal_function(key, inode->key_value_pair.first))
1254 {
1255 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1256 }
1257
1258 ++inode;
1259 }
1260 }
1261
1262 return end();
1263 }
1264#endif
1265
1266#if ETL_USING_CPP11
1267 //*********************************************************************
1271 //*********************************************************************
1272 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1273 const_iterator find(const K& key) const
1274 {
1275 size_t index = get_bucket_index(key);
1276
1277 bucket_t* pbucket = pbuckets + index;
1278 bucket_t& bucket = *pbucket;
1279
1280 // Is the bucket not empty?
1281 if (!bucket.empty())
1282 {
1283 // Step though the list until we find the end or an equivalent key.
1284 local_iterator inode = bucket.begin();
1285 local_iterator iend = bucket.end();
1286
1287 while (inode != iend)
1288 {
1289 // Do we have this one?
1290 if (key_equal_function(key, inode->key_value_pair.first))
1291 {
1292 return const_iterator((pbuckets + number_of_buckets), pbucket, inode);
1293 }
1294
1295 ++inode;
1296 }
1297 }
1298
1299 return end();
1300 }
1301#endif
1302
1303 //*********************************************************************
1311 //*********************************************************************
1312 ETL_OR_STD::pair<iterator, iterator> equal_range(const_key_reference key)
1313 {
1314 iterator f = find(key);
1315 iterator l = f;
1316
1317 if (l != end())
1318 {
1319 ++l;
1320
1321 while ((l != end()) && key_equal_function(key, l->first))
1322 {
1323 ++l;
1324 }
1325 }
1326
1327 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1328 }
1329
1330 //*********************************************************************
1338 //*********************************************************************
1339 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const_key_reference key) const
1340 {
1341 const_iterator f = find(key);
1342 const_iterator l = f;
1343
1344 if (l != end())
1345 {
1346 ++l;
1347
1348 while ((l != end()) && key_equal_function(key, l->first))
1349 {
1350 ++l;
1351 }
1352 }
1353
1354 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1355 }
1356
1357#if ETL_USING_CPP11
1358 //*********************************************************************
1366 //*********************************************************************
1367 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1368 ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
1369 {
1370 iterator f = find(key);
1371 iterator l = f;
1372
1373 if (l != end())
1374 {
1375 ++l;
1376
1377 while ((l != end()) && key_equal_function(key, l->first))
1378 {
1379 ++l;
1380 }
1381 }
1382
1383 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1384 }
1385#endif
1386
1387#if ETL_USING_CPP11
1388 //*********************************************************************
1396 //*********************************************************************
1397 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1398 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
1399 {
1400 const_iterator f = find(key);
1401 const_iterator l = f;
1402
1403 if (l != end())
1404 {
1405 ++l;
1406
1407 while ((l != end()) && key_equal_function(key, l->first))
1408 {
1409 ++l;
1410 }
1411 }
1412
1413 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1414 }
1415#endif
1416
1417 //*************************************************************************
1419 //*************************************************************************
1420 size_type size() const
1421 {
1422 return pnodepool->size();
1423 }
1424
1425 //*************************************************************************
1427 //*************************************************************************
1428 size_type max_size() const
1429 {
1430 return pnodepool->max_size();
1431 }
1432
1433 //*************************************************************************
1435 //*************************************************************************
1436 size_type capacity() const
1437 {
1438 return pnodepool->max_size();
1439 }
1440
1441 //*************************************************************************
1443 //*************************************************************************
1444 bool empty() const
1445 {
1446 return pnodepool->empty();
1447 }
1448
1449 //*************************************************************************
1451 //*************************************************************************
1452 bool full() const
1453 {
1454 return pnodepool->full();
1455 }
1456
1457 //*************************************************************************
1460 //*************************************************************************
1461 size_t available() const
1462 {
1463 return pnodepool->available();
1464 }
1465
1466 //*************************************************************************
1469 //*************************************************************************
1470 float load_factor() const
1471 {
1472 return static_cast<float>(size()) / static_cast<float>(bucket_count());
1473 }
1474
1475 //*************************************************************************
1478 //*************************************************************************
1479 hasher hash_function() const
1480 {
1481 return key_hash_function;
1482 }
1483
1484 //*************************************************************************
1487 //*************************************************************************
1488 key_equal key_eq() const
1489 {
1490 return key_equal_function;
1491 }
1492
1493 //*************************************************************************
1495 //*************************************************************************
1497 {
1498 // Skip if doing self assignment
1499 if (this != &rhs)
1500 {
1501 key_hash_function = rhs.hash_function();
1502 key_equal_function = rhs.key_eq();
1503 assign(rhs.cbegin(), rhs.cend());
1504 }
1505
1506 return *this;
1507 }
1508
1509#if ETL_USING_CPP11
1510 //*************************************************************************
1512 //*************************************************************************
1514 {
1515 // Skip if doing self assignment
1516 if (this != &rhs)
1517 {
1518 clear();
1519 key_hash_function = rhs.hash_function();
1520 key_equal_function = rhs.key_eq();
1521 move(rhs.begin(), rhs.end());
1522 }
1523
1524 return *this;
1525 }
1526#endif
1527
1528 //*************************************************************************
1530 //*************************************************************************
1531 bool contains(const_key_reference key) const
1532 {
1533 return find(key) != end();
1534 }
1535
1536#if ETL_USING_CPP11
1537 //*************************************************************************
1539 //*************************************************************************
1540 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1541 bool contains(const K& key) const
1542 {
1543 return find(key) != end();
1544 }
1545#endif
1546
1547 protected:
1548
1549 //*********************************************************************
1551 //*********************************************************************
1552 iunordered_multimap(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1553 : pnodepool(&node_pool_)
1554 , pbuckets(pbuckets_)
1555 , number_of_buckets(number_of_buckets_)
1556 , first(pbuckets)
1557 , last(pbuckets)
1558 , key_hash_function(key_hash_function_)
1559 , key_equal_function(key_equal_function_)
1560 {
1561 }
1562
1563 //*********************************************************************
1565 //*********************************************************************
1567 {
1568 if (!empty())
1569 {
1570 // For each bucket...
1571 for (size_t i = 0UL; i < number_of_buckets; ++i)
1572 {
1573 bucket_t& bucket = pbuckets[i];
1574
1575 if (!bucket.empty())
1576 {
1577 // For each item in the bucket...
1578 local_iterator it = bucket.begin();
1579
1580 while (it != bucket.end())
1581 {
1582 // Destroy the value contents.
1583 it->key_value_pair.~value_type();
1584 ++it;
1585 ETL_DECREMENT_DEBUG_COUNT;
1586 }
1587
1588 // Now it's safe to clear the bucket.
1589 bucket.clear();
1590 }
1591 }
1592
1593 // Now it's safe to clear the entire pool in one go.
1594 pnodepool->release_all();
1595 }
1596
1597 first = pbuckets;
1598 last = first;
1599 }
1600
1601#if ETL_USING_CPP11
1602 //*************************************************************************
1604 //*************************************************************************
1605 void move(iterator b, iterator e)
1606 {
1607 while (b != e)
1608 {
1609 iterator temp = b;
1610 ++temp;
1611 insert(etl::move(*b));
1612 b = temp;
1613 }
1614 }
1615#endif
1616
1617 private:
1618
1619 //*************************************************************************
1621 //*************************************************************************
1622 node_t* allocate_data_node()
1623 {
1624 node_t* (etl::ipool::*func)() = &etl::ipool::allocate<node_t>;
1625 return (pnodepool->*func)();
1626 }
1627
1628 //*********************************************************************
1630 //*********************************************************************
1631 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1632 {
1633 if (size() == 1)
1634 {
1635 first = pbucket;
1636 last = pbucket;
1637 }
1638 else
1639 {
1640 if (pbucket < first)
1641 {
1642 first = pbucket;
1643 }
1644 else if (pbucket > last)
1645 {
1646 last = pbucket;
1647 }
1648 }
1649 }
1650
1651 //*********************************************************************
1653 //*********************************************************************
1654 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1655 {
1656 if (empty())
1657 {
1658 first = pbuckets;
1659 last = pbuckets;
1660 }
1661 else
1662 {
1663 if (pbucket == first)
1664 {
1665 // We erased the first so, we need to search again from where we
1666 // erased.
1667 while (first->empty())
1668 {
1669 ++first;
1670 }
1671 }
1672 else if (pbucket == last)
1673 {
1674 // We erased the last, so we need to search again. Start from the
1675 // first, go no further than the current last.
1676 pbucket = first;
1677 bucket_t* pend = last;
1678
1679 last = first;
1680
1681 while (pbucket != pend)
1682 {
1683 if (!pbucket->empty())
1684 {
1685 last = pbucket;
1686 }
1687
1688 ++pbucket;
1689 }
1690 }
1691 }
1692 }
1693
1694 //*********************************************************************
1696 //*********************************************************************
1697 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1698 {
1699 local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket.
1700 icurrent->key_value_pair.~value_type(); // Destroy the value.
1701 pnodepool->release(&*icurrent); // Release it back to the pool.
1702 adjust_first_last_markers_after_erase(&bucket);
1703 ETL_DECREMENT_DEBUG_COUNT;
1704
1705 return inext;
1706 }
1707
1708 // Disable copy construction.
1710
1712 pool_t* pnodepool;
1713
1715 bucket_t* pbuckets;
1716
1718 const size_t number_of_buckets;
1719
1721 bucket_t* first;
1722 bucket_t* last;
1723
1725 hasher key_hash_function;
1726
1728 key_equal key_equal_function;
1729
1731 ETL_DECLARE_DEBUG_COUNT;
1732
1733 //*************************************************************************
1735 //*************************************************************************
1736#if defined(ETL_POLYMORPHIC_UNORDERED_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS)
1737
1738 public:
1739
1740 virtual ~iunordered_multimap() {}
1741#else
1742
1743 protected:
1744
1746#endif
1747 };
1748
1749 //***************************************************************************
1755 //***************************************************************************
1756 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1758 {
1759 const bool sizes_match = (lhs.size() == rhs.size());
1760 bool elements_match = true;
1761
1763
1764 if (sizes_match)
1765 {
1766 itr_t l_begin = lhs.begin();
1767 itr_t l_end = lhs.end();
1768
1769 while ((l_begin != l_end) && elements_match)
1770 {
1771 const TKey key = l_begin->first;
1772 const T l_value = l_begin->second;
1773
1774 // See if the lhs keys exist in the rhs.
1775 ETL_OR_STD::pair<itr_t, itr_t> l_range = lhs.equal_range(key);
1776 ETL_OR_STD::pair<itr_t, itr_t> r_range = rhs.equal_range(key);
1777
1778 if (r_range.first != rhs.end())
1779 {
1780 bool distance_match = (etl::distance(l_range.first, l_range.second) == etl::distance(r_range.first, r_range.second));
1781
1782 if (distance_match)
1783 {
1784 elements_match = etl::is_permutation(l_range.first, l_range.second, r_range.first, r_range.second);
1785 }
1786 else
1787 {
1788 elements_match = false;
1789 }
1790 }
1791 else
1792 {
1793 elements_match = false;
1794 }
1795
1796 ++l_begin;
1797 }
1798 }
1799
1800 return (sizes_match && elements_match);
1801 }
1802
1803 //***************************************************************************
1809 //***************************************************************************
1810 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1815
1816 //*************************************************************************
1819 //*************************************************************************
1820 template <typename TKey, typename TValue, const size_t MAX_SIZE_, const size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>,
1821 typename TKeyEqual = etl::equal_to<TKey> >
1822 class unordered_multimap : public etl::iunordered_multimap<TKey, TValue, THash, TKeyEqual>
1823 {
1824 private:
1825
1827
1828 public:
1829
1830 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
1831 static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_;
1832
1833 //*************************************************************************
1835 //*************************************************************************
1836 unordered_multimap(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1837 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1838 {
1839 }
1840
1841 //*************************************************************************
1843 //*************************************************************************
1845 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1846 {
1847 // Skip if doing self assignment
1848 if (this != &other)
1849 {
1850 base::assign(other.cbegin(), other.cend());
1851 }
1852 }
1853
1854#if ETL_USING_CPP11
1855 //*************************************************************************
1857 //*************************************************************************
1859 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1860 {
1861 // Skip if doing self assignment
1862 if (this != &other)
1863 {
1864 base::move(other.begin(), other.end());
1865 }
1866 }
1867#endif
1868
1869 //*************************************************************************
1874 //*************************************************************************
1875 template <typename TIterator>
1876 unordered_multimap(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1877 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1878 {
1879 base::assign(first_, last_);
1880 }
1881
1882#if ETL_HAS_INITIALIZER_LIST
1883 //*************************************************************************
1885 //*************************************************************************
1886 unordered_multimap(std::initializer_list<ETL_OR_STD::pair<TKey, TValue>> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1887 : base(node_pool, buckets, MAX_BUCKETS_, hash, equal)
1888 {
1889 base::assign(init.begin(), init.end());
1890 }
1891#endif
1892
1893 //*************************************************************************
1895 //*************************************************************************
1897 {
1899 }
1900
1901 //*************************************************************************
1903 //*************************************************************************
1905 {
1906 base::operator=(rhs);
1907
1908 return *this;
1909 }
1910
1911#if ETL_USING_CPP11
1912 //*************************************************************************
1914 //*************************************************************************
1915 unordered_multimap& operator=(unordered_multimap&& rhs)
1916 {
1917 base::operator=(etl::move(rhs));
1918
1919 return *this;
1920 }
1921#endif
1922
1923 private:
1924
1927
1929 typename base::bucket_t buckets[MAX_BUCKETS_];
1930 };
1931
1932 //*************************************************************************
1934 //*************************************************************************
1935#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
1936 template <typename... TPairs>
1937 unordered_multimap(TPairs...)
1938 -> unordered_multimap<typename etl::nth_type_t<0, TPairs...>::first_type, typename etl::nth_type_t<0, TPairs...>::second_type, sizeof...(TPairs)>;
1939#endif
1940
1941 //*************************************************************************
1943 //*************************************************************************
1944#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
1945 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey>, typename... TPairs>
1946 constexpr auto
1947 make_unordered_multimap(TPairs&&... pairs) -> etl::unordered_multimap<TKey, T, sizeof...(TPairs), sizeof...(TPairs), THash, TKeyEqual>
1948 {
1949 return {etl::forward<TPairs>(pairs)...};
1950 }
1951#endif
1952} // namespace etl
1953
1954#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:329
Definition unordered_multimap.h:188
Definition unordered_multimap.h:1823
unordered_multimap(const unordered_multimap &other)
Copy constructor.
Definition unordered_multimap.h:1844
unordered_multimap & operator=(const unordered_multimap &rhs)
Assignment operator.
Definition unordered_multimap.h:1904
unordered_multimap(TIterator first_, TIterator last_, const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Definition unordered_multimap.h:1876
unordered_multimap(const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Default constructor.
Definition unordered_multimap.h:1836
~unordered_multimap()
Destructor.
Definition unordered_multimap.h:1896
ETL_NODISCARD ETL_CONSTEXPR14 bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2)
Definition algorithm.h:1810
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
T * allocate()
Definition ipool.h:334
Definition ipool.h:110
Definition pool.h:54
iterator end()
Definition unordered_multimap.h:541
iunordered_multimap & operator=(const iunordered_multimap &rhs)
Assignment operator.
Definition unordered_multimap.h:1496
const_local_iterator cend(size_t i) const
Definition unordered_multimap.h:586
const_local_iterator cbegin(size_t i) const
Definition unordered_multimap.h:532
float load_factor() const
Definition unordered_multimap.h:1470
void assign(TIterator first_, TIterator last_)
Definition unordered_multimap.h:665
size_t available() const
Definition unordered_multimap.h:1461
const_local_iterator end(size_t i) const
Definition unordered_multimap.h:577
key_equal key_eq() const
Definition unordered_multimap.h:1488
const_iterator find(const_key_reference key) const
Definition unordered_multimap.h:1200
bool contains(const_key_reference key) const
Check if the unordered_multimap contains the key.
Definition unordered_multimap.h:1531
bool empty() const
Checks to see if the unordered_multimap is empty.
Definition unordered_multimap.h:1444
size_type bucket_count() const
Definition unordered_multimap.h:650
iterator insert(const_reference key_value_pair)
Definition unordered_multimap.h:688
iterator erase(const_iterator ielement)
Definition unordered_multimap.h:1019
local_iterator end(size_t i)
Definition unordered_multimap.h:568
size_type capacity() const
Gets the maximum possible size of the unordered_multimap.
Definition unordered_multimap.h:1436
const_local_iterator begin(size_t i) const
Definition unordered_multimap.h:521
void initialise()
Initialise the unordered_multimap.
Definition unordered_multimap.h:1566
const_iterator end() const
Definition unordered_multimap.h:550
size_t count(const_key_reference key) const
Definition unordered_multimap.h:1111
iterator find(const_key_reference key)
Definition unordered_multimap.h:1166
size_type size() const
Gets the size of the unordered_multimap.
Definition unordered_multimap.h:1420
void clear()
Clears the unordered_multimap.
Definition unordered_multimap.h:1101
const_iterator begin() const
Definition unordered_multimap.h:492
hasher hash_function() const
Definition unordered_multimap.h:1479
iterator erase(const_iterator first_, const_iterator last_)
Definition unordered_multimap.h:1047
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(const_key_reference key) const
Definition unordered_multimap.h:1339
iterator insert(const_iterator, const_reference key_value_pair)
Definition unordered_multimap.h:833
size_type max_size() const
Gets the maximum possible size of the unordered_multimap.
Definition unordered_multimap.h:1428
const_iterator cbegin() const
Definition unordered_multimap.h:501
local_iterator begin(size_t i)
Definition unordered_multimap.h:510
ETL_OR_STD::pair< iterator, iterator > equal_range(const_key_reference key)
Definition unordered_multimap.h:1312
~iunordered_multimap()
Destructor.
Definition unordered_multimap.h:1745
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:1552
size_type bucket_size(const_key_reference key) const
Definition unordered_multimap.h:616
size_type max_bucket_count() const
Definition unordered_multimap.h:641
const_iterator cend() const
Definition unordered_multimap.h:559
void insert(TIterator first_, TIterator last_)
Definition unordered_multimap.h:861
bool full() const
Checks to see if the unordered_multimap is full.
Definition unordered_multimap.h:1452
iterator emplace(const_reference key_value_pair)
Emplaces a value to the unordered_multimap.
Definition unordered_multimap.h:939
size_t erase(const_key_reference key)
Definition unordered_multimap.h:949
size_type get_bucket_index(const_key_reference key) const
Definition unordered_multimap.h:595
iterator begin()
Definition unordered_multimap.h:483
Definition unordered_multimap.h:128
Definition unordered_multimap.h:69
Definition unordered_multimap.h:83
Definition unordered_multimap.h:111
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
TContainer::iterator begin(TContainer &container)
Definition iterator.h:1136
iterator
Definition iterator.h:482
Definition unordered_multimap.h:156
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937