Embedded Template Library 1.0
Loading...
Searching...
No Matches
unordered_multiset.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_MULTISET_INCLUDED
32#define ETL_UNORDERED_MULTISET_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_multiset_exception : public etl::exception
70 {
71 public:
72
73 unordered_multiset_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_multiset_full : public etl::unordered_multiset_exception
84 {
85 public:
86
87 unordered_multiset_full(string_type file_name_, numeric_type line_number_)
88 : etl::unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:full", ETL_UNORDERED_MULTISET_FILE_ID"A"), file_name_, line_number_)
89 {
90 }
91 };
92
93 //***************************************************************************
96 //***************************************************************************
97 class unordered_multiset_out_of_range : public etl::unordered_multiset_exception
98 {
99 public:
100
101 unordered_multiset_out_of_range(string_type file_name_, numeric_type line_number_)
102 : etl::unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:range", ETL_UNORDERED_MULTISET_FILE_ID"B"), file_name_, line_number_)
103 {
104 }
105 };
106
107 //***************************************************************************
110 //***************************************************************************
111 class unordered_multiset_iterator : public etl::unordered_multiset_exception
112 {
113 public:
114
115 unordered_multiset_iterator(string_type file_name_, numeric_type line_number_)
116 : etl::unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:iterator", ETL_UNORDERED_MULTISET_FILE_ID"C"), file_name_, line_number_)
117 {
118 }
119 };
120
121 //***************************************************************************
126 //***************************************************************************
127 template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey> >
129 {
130 public:
131
132 typedef TKey value_type;
133 typedef TKey key_type;
134 typedef THash hasher;
135 typedef TKeyEqual key_equal;
136 typedef value_type& reference;
137 typedef const value_type& const_reference;
138#if ETL_USING_CPP11
139 typedef value_type&& rvalue_reference;
140#endif
141 typedef value_type* pointer;
142 typedef const value_type* const_pointer;
143 typedef size_t size_type;
144
145 typedef const TKey& key_parameter_t;
146
147 typedef etl::forward_link<0> link_t;
148
149 //*********************************************************************
150 // The nodes that store the elements.
151 struct node_t : public link_t
152 {
153 node_t(const_reference key_)
154 : key(key_)
155 {
156 }
157
158 value_type key;
159 };
160
161 friend bool operator==(const node_t& lhs, const node_t& rhs)
162 {
163 return (lhs.key == rhs.key);
164 }
165
166 friend bool operator!=(const node_t& lhs, const node_t& rhs)
167 {
168 return !(lhs == rhs);
169 }
170
171 protected:
172
174 typedef etl::ipool pool_t;
175
176 public:
177
178 // Local iterators iterate over one bucket.
179 typedef typename bucket_t::iterator local_iterator;
180 typedef typename bucket_t::const_iterator const_local_iterator;
181
182 //*********************************************************************
183 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>
184 {
185 public:
186
187 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>::value_type value_type;
188 typedef typename iunordered_multiset::key_type key_type;
189 typedef typename iunordered_multiset::hasher hasher;
190 typedef typename iunordered_multiset::key_equal key_equal;
191 typedef typename iunordered_multiset::reference reference;
192 typedef typename iunordered_multiset::const_reference const_reference;
193 typedef typename iunordered_multiset::pointer pointer;
194 typedef typename iunordered_multiset::const_pointer const_pointer;
195 typedef typename iunordered_multiset::size_type size_type;
196
197 friend class iunordered_multiset;
198 friend class const_iterator;
199
200 //*********************************
201 iterator() {}
202
203 //*********************************
204 iterator(const iterator& other)
205 : pbuckets_end(other.pbuckets_end)
206 , pbucket(other.pbucket)
207 , inode(other.inode)
208 {
209 }
210
211 //*********************************
212 iterator& operator++()
213 {
214 ++inode;
215
216 // The end of this node list?
217 if (inode == pbucket->end())
218 {
219 // Search for the next non-empty bucket.
220 ++pbucket;
221 while ((pbucket != pbuckets_end) && (pbucket->empty()))
222 {
223 ++pbucket;
224 }
225
226 // If not past the end, get the first node in the bucket.
227 if (pbucket != pbuckets_end)
228 {
229 inode = pbucket->begin();
230 }
231 }
232
233 return *this;
234 }
235
236 //*********************************
237 iterator operator++(int)
238 {
239 iterator temp(*this);
240 operator++();
241 return temp;
242 }
243
244 //*********************************
245 iterator& operator=(const iterator& other)
246 {
247 pbuckets_end = other.pbuckets_end;
248 pbucket = other.pbucket;
249 inode = other.inode;
250 return *this;
251 }
252
253 //*********************************
254 reference operator*() const
255 {
256 return inode->key;
257 }
258
259 //*********************************
260 pointer operator&() const
261 {
262 return &(inode->key);
263 }
264
265 //*********************************
266 pointer operator->() const
267 {
268 return &(inode->key);
269 }
270
271 //*********************************
272 friend bool operator==(const iterator& lhs, const iterator& rhs)
273 {
274 return lhs.compare(rhs);
275 }
276
277 //*********************************
278 friend bool operator!=(const iterator& lhs, const iterator& rhs)
279 {
280 return !(lhs == rhs);
281 }
282
283 private:
284
285 //*********************************
286 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
287 : pbuckets_end(pbuckets_end_)
288 , pbucket(pbucket_)
289 , inode(inode_)
290 {
291 }
292
293 //*********************************
294 bool compare(const iterator& rhs) const
295 {
296 return rhs.inode == inode;
297 }
298
299 //*********************************
300 bucket_t& get_bucket()
301 {
302 return *pbucket;
303 }
304
305 //*********************************
306 bucket_t*& get_bucket_list_iterator()
307 {
308 return pbucket;
309 }
310
311 //*********************************
312 local_iterator get_local_iterator()
313 {
314 return inode;
315 }
316
317 bucket_t* pbuckets_end;
318 bucket_t* pbucket;
319 local_iterator inode;
320 };
321
322 //*********************************************************************
323 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>
324 {
325 public:
326
327 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>::value_type value_type;
328 typedef typename iunordered_multiset::key_type key_type;
329 typedef typename iunordered_multiset::hasher hasher;
330 typedef typename iunordered_multiset::key_equal key_equal;
331 typedef typename iunordered_multiset::reference reference;
332 typedef typename iunordered_multiset::const_reference const_reference;
333 typedef typename iunordered_multiset::pointer pointer;
334 typedef typename iunordered_multiset::const_pointer const_pointer;
335 typedef typename iunordered_multiset::size_type size_type;
336
337 friend class iunordered_multiset;
338 friend class iterator;
339
340 //*********************************
341 const_iterator() {}
342
343 //*********************************
344 const_iterator(const typename iunordered_multiset::iterator& other)
345 : pbuckets_end(other.pbuckets_end)
346 , pbucket(other.pbucket)
347 , inode(other.inode)
348 {
349 }
350
351 //*********************************
352 const_iterator(const const_iterator& other)
353 : pbuckets_end(other.pbuckets_end)
354 , pbucket(other.pbucket)
355 , inode(other.inode)
356 {
357 }
358
359 //*********************************
360 const_iterator& operator++()
361 {
362 ++inode;
363
364 // The end of this node list?
365 if (inode == pbucket->end())
366 {
367 // Search for the next non-empty bucket.
368
369 ++pbucket;
370 while ((pbucket != pbuckets_end) && (pbucket->empty()))
371 {
372 ++pbucket;
373 }
374
375 // If not past the end, get the first node in the bucket.
376 if (pbucket != pbuckets_end)
377 {
378 inode = pbucket->begin();
379 }
380 }
381
382 return *this;
383 }
384
385 //*********************************
386 const_iterator operator++(int)
387 {
388 const_iterator temp(*this);
389 operator++();
390 return temp;
391 }
392
393 //*********************************
394 const_iterator& operator=(const const_iterator& other)
395 {
396 pbuckets_end = other.pbuckets_end;
397 pbucket = other.pbucket;
398 inode = other.inode;
399 return *this;
400 }
401
402 //*********************************
403 const_reference operator*() const
404 {
405 return inode->key;
406 }
407
408 //*********************************
409 const_pointer operator&() const
410 {
411 return &(inode->key);
412 }
413
414 //*********************************
415 const_pointer operator->() const
416 {
417 return &(inode->key);
418 }
419
420 //*********************************
421 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
422 {
423 return lhs.compare(rhs);
424 }
425
426 //*********************************
427 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
428 {
429 return !(lhs == rhs);
430 }
431
432 private:
433
434 //*********************************
435 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
436 : pbuckets_end(pbuckets_end_)
437 , pbucket(pbucket_)
438 , inode(inode_)
439 {
440 }
441
442 //*********************************
443 bool compare(const const_iterator& rhs) const
444 {
445 return rhs.inode == inode;
446 }
447
448 //*********************************
449 bucket_t& get_bucket()
450 {
451 return *pbucket;
452 }
453
454 //*********************************
455 bucket_t*& get_bucket_list_iterator()
456 {
457 return pbucket;
458 }
459
460 //*********************************
461 local_iterator get_local_iterator()
462 {
463 return inode;
464 }
465
466 bucket_t* pbuckets_end;
467 bucket_t* pbucket;
468 local_iterator inode;
469 };
470
471 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
472
473 //*********************************************************************
476 //*********************************************************************
477 iterator begin()
478 {
479 return iterator((pbuckets + number_of_buckets), first, first->begin());
480 }
481
482 //*********************************************************************
485 //*********************************************************************
486 const_iterator begin() const
487 {
488 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
489 }
490
491 //*********************************************************************
494 //*********************************************************************
495 const_iterator cbegin() const
496 {
497 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
498 }
499
500 //*********************************************************************
503 //*********************************************************************
504 local_iterator begin(size_t i)
505 {
506 return pbuckets[i].begin();
507 }
508
509 //*********************************************************************
514 //*********************************************************************
515 const_local_iterator begin(size_t i) const
516 {
517 return pbuckets[i].cbegin();
518 }
519
520 //*********************************************************************
525 //*********************************************************************
526 const_local_iterator cbegin(size_t i) const
527 {
528 return pbuckets[i].cbegin();
529 }
530
531 //*********************************************************************
534 //*********************************************************************
535 iterator end()
536 {
537 return iterator((pbuckets + number_of_buckets), last, last->end());
538 }
539
540 //*********************************************************************
543 //*********************************************************************
544 const_iterator end() const
545 {
546 return const_iterator((pbuckets + number_of_buckets), last, last->end());
547 }
548
549 //*********************************************************************
552 //*********************************************************************
553 const_iterator cend() const
554 {
555 return const_iterator((pbuckets + number_of_buckets), last, last->end());
556 }
557
558 //*********************************************************************
561 //*********************************************************************
562 local_iterator end(size_t i)
563 {
564 return pbuckets[i].end();
565 }
566
567 //*********************************************************************
570 //*********************************************************************
571 const_local_iterator end(size_t i) const
572 {
573 return pbuckets[i].cend();
574 }
575
576 //*********************************************************************
579 //*********************************************************************
580 const_local_iterator cend(size_t i) const
581 {
582 return pbuckets[i].cend();
583 }
584
585 //*********************************************************************
588 //*********************************************************************
589 size_type get_bucket_index(key_parameter_t key) const
590 {
591 return key_hash_function(key) % number_of_buckets;
592 }
593
594#if ETL_USING_CPP11
595 //*********************************************************************
598 //*********************************************************************
599 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
600 size_type get_bucket_index(const K& key) const
601 {
602 return key_hash_function(key) % number_of_buckets;
603 }
604#endif
605
606 //*********************************************************************
609 //*********************************************************************
610 size_type bucket_size(key_parameter_t key) const
611 {
612 size_t index = bucket(key);
613
614 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
615 }
616
617#if ETL_USING_CPP11
618 //*********************************************************************
621 //*********************************************************************
622 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
623 size_type bucket_size(const K& key) const
624 {
625 size_t index = bucket(key);
626
627 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
628 }
629#endif
630
631 //*********************************************************************
634 //*********************************************************************
635 size_type max_bucket_count() const
636 {
637 return number_of_buckets;
638 }
639
640 //*********************************************************************
643 //*********************************************************************
644 size_type bucket_count() const
645 {
646 return number_of_buckets;
647 }
648
649 //*********************************************************************
657 //*********************************************************************
658 template <typename TIterator>
659 void assign(TIterator first_, TIterator last_)
660 {
661#if ETL_IS_DEBUG_BUILD
662 difference_type d = etl::distance(first_, last_);
663 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_multiset_iterator));
664 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_multiset_full));
665#endif
666
667 clear();
668
669 while (first_ != last_)
670 {
671 insert(*first_);
672 ++first_;
673 }
674 }
675
676 //*********************************************************************
681 //*********************************************************************
682 ETL_OR_STD::pair<iterator, bool> insert(const_reference key)
683 {
684 ETL_OR_STD::pair<iterator, bool> result(end(), false);
685
687
688 // Get the hash index.
689 size_t index = get_bucket_index(key);
690
691 // Get the bucket & bucket iterator.
692 bucket_t* pbucket = pbuckets + index;
693 bucket_t& bucket = *pbucket;
694
695 // The first one in the bucket?
696 if (bucket.empty())
697 {
698 // Get a new node.
699 node_t* node = allocate_data_node();
700 node->clear();
701 ::new (&node->key) value_type(key);
702 ETL_INCREMENT_DEBUG_COUNT;
703
704 // Just add the pointer to the bucket;
705 bucket.insert_after(bucket.before_begin(), *node);
706 adjust_first_last_markers_after_insert(&bucket);
707
708 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
709 result.second = true;
710 }
711 else
712 {
713 // Step though the bucket looking for a place to insert.
714 local_iterator inode_previous = bucket.before_begin();
715 local_iterator inode = bucket.begin();
716
717 while (inode != bucket.end())
718 {
719 // Do we already have this key?
720 if (key_equal_function(inode->key, key))
721 {
722 break;
723 }
724
725 ++inode_previous;
726 ++inode;
727 }
728
729 // Get a new node.
730 node_t* node = allocate_data_node();
731 node->clear();
732 ::new (&node->key) value_type(key);
733 ETL_INCREMENT_DEBUG_COUNT;
734
735 // Add the node to the end of the bucket;
736 bucket.insert_after(inode_previous, *node);
737 adjust_first_last_markers_after_insert(&bucket);
738 ++inode_previous;
739
740 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
741 result.second = true;
742 }
743
744 return result;
745 }
746
747#if ETL_USING_CPP11
748 //*********************************************************************
753 //*********************************************************************
754 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
755 ETL_OR_STD::pair<iterator, bool> insert(const K& key)
756 {
757 ETL_OR_STD::pair<iterator, bool> result(end(), false);
758
760
761 // Get the hash index.
762 size_t index = get_bucket_index(key);
763
764 // Get the bucket & bucket iterator.
765 bucket_t* pbucket = pbuckets + index;
766 bucket_t& bucket = *pbucket;
767
768 // The first one in the bucket?
769 if (bucket.empty())
770 {
771 // Get a new node.
772 node_t* node = allocate_data_node();
773 node->clear();
774 ::new (&node->key) value_type(key);
775 ETL_INCREMENT_DEBUG_COUNT;
776
777 // Just add the pointer to the bucket;
778 bucket.insert_after(bucket.before_begin(), *node);
779 adjust_first_last_markers_after_insert(&bucket);
780
781 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
782 result.second = true;
783 }
784 else
785 {
786 // Step though the bucket looking for a place to insert.
787 local_iterator inode_previous = bucket.before_begin();
788 local_iterator inode = bucket.begin();
789
790 while (inode != bucket.end())
791 {
792 // Do we already have this key?
793 if (key_equal_function(inode->key, key))
794 {
795 break;
796 }
797
798 ++inode_previous;
799 ++inode;
800 }
801
802 // Get a new node.
803 node_t* node = allocate_data_node();
804 node->clear();
805 ::new (&node->key) value_type(key);
806 ETL_INCREMENT_DEBUG_COUNT;
807
808 // Add the node to the end of the bucket;
809 bucket.insert_after(inode_previous, *node);
810 adjust_first_last_markers_after_insert(&bucket);
811 ++inode_previous;
812
813 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
814 result.second = true;
815 }
816
817 return result;
818 }
819#endif
820
821#if ETL_USING_CPP11
822 //*********************************************************************
827 //*********************************************************************
828 ETL_OR_STD::pair<iterator, bool> insert(rvalue_reference key)
829 {
830 ETL_OR_STD::pair<iterator, bool> result(end(), false);
831
832 ETL_ASSERT(!full(), ETL_ERROR(unordered_multiset_full));
833
834 // Get the hash index.
835 size_t index = get_bucket_index(key);
836
837 // Get the bucket & bucket iterator.
838 bucket_t* pbucket = pbuckets + index;
839 bucket_t& bucket = *pbucket;
840
841 // The first one in the bucket?
842 if (bucket.empty())
843 {
844 // Get a new node.
845 node_t* node = allocate_data_node();
846 node->clear();
847 ::new (&node->key) value_type(etl::move(key));
848 ETL_INCREMENT_DEBUG_COUNT;
849
850 // Just add the pointer to the bucket;
851 bucket.insert_after(bucket.before_begin(), *node);
852 adjust_first_last_markers_after_insert(&bucket);
853
854 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
855 result.second = true;
856 }
857 else
858 {
859 // Step though the bucket looking for a place to insert.
860 local_iterator inode_previous = bucket.before_begin();
861 local_iterator inode = bucket.begin();
862
863 while (inode != bucket.end())
864 {
865 // Do we already have this key?
866 if (key_equal_function(inode->key, key))
867 {
868 break;
869 }
870
871 ++inode_previous;
872 ++inode;
873 }
874
875 // Get a new node.
876 node_t* node = allocate_data_node();
877 node->clear();
878 ::new (&node->key) value_type(etl::move(key));
879 ETL_INCREMENT_DEBUG_COUNT;
880
881 // Add the node to the end of the bucket;
882 bucket.insert_after(inode_previous, *node);
883 adjust_first_last_markers_after_insert(&bucket);
884 ++inode_previous;
885
886 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
887 result.second = true;
888 }
889
890 return result;
891 }
892#endif
893
894 //*********************************************************************
900 //*********************************************************************
901 iterator insert(const_iterator /*position*/, const_reference key)
902 {
903 return insert(key).first;
904 }
905
906 //*********************************************************************
913 //*********************************************************************
914 template <class TIterator>
915 void insert(TIterator first_, TIterator last_)
916 {
917 while (first_ != last_)
918 {
919 insert(*first_);
920 ++first_;
921 }
922 }
923
924 //*********************************************************************
928 //*********************************************************************
929 size_t erase(key_parameter_t key)
930 {
931 size_t n = 0UL;
932 size_t bucket_id = get_bucket_index(key);
933
934 bucket_t& bucket = pbuckets[bucket_id];
935
936 local_iterator iprevious = bucket.before_begin();
937 local_iterator icurrent = bucket.begin();
938
939 while (icurrent != bucket.end())
940 {
941 if (key_equal_function(icurrent->key, key))
942 {
943 delete_data_node(iprevious, icurrent, bucket);
944 ++n;
945 icurrent = iprevious;
946 }
947 else
948 {
949 ++iprevious;
950 }
951
952 ++icurrent;
953 }
954
955 return n;
956 }
957
958#if ETL_USING_CPP11
959 //*********************************************************************
963 //*********************************************************************
964 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
965 size_t erase(const K& key)
966 {
967 size_t n = 0UL;
968 size_t bucket_id = get_bucket_index(key);
969
970 bucket_t& bucket = pbuckets[bucket_id];
971
972 local_iterator iprevious = bucket.before_begin();
973 local_iterator icurrent = bucket.begin();
974
975 while (icurrent != bucket.end())
976 {
977 if (key_equal_function(icurrent->key, key))
978 {
979 delete_data_node(iprevious, icurrent, bucket);
980 ++n;
981 icurrent = iprevious;
982 }
983 else
984 {
985 ++iprevious;
986 }
987
988 ++icurrent;
989 }
990
991 return n;
992 }
993#endif
994
995 //*********************************************************************
998 //*********************************************************************
999 iterator erase(const_iterator ielement)
1000 {
1001 // Make a note of the next one.
1002 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1003 ++inext;
1004
1005 bucket_t& bucket = ielement.get_bucket();
1006 local_iterator iprevious = bucket.before_begin();
1007 local_iterator icurrent = ielement.get_local_iterator();
1008
1009 // Find the node previous to the one we're interested in.
1010 while (iprevious->etl_next != &*icurrent)
1011 {
1012 ++iprevious;
1013 }
1014
1015 delete_data_node(iprevious, icurrent, bucket);
1016
1017 return inext;
1018 }
1019
1020 //*********************************************************************
1026 //*********************************************************************
1027 iterator erase(const_iterator first_, const_iterator last_)
1028 {
1029 // Erasing everything?
1030 if ((first_ == begin()) && (last_ == end()))
1031 {
1032 clear();
1033 return end();
1034 }
1035
1036 // Get the starting point.
1037 bucket_t* pbucket = first_.get_bucket_list_iterator();
1038 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1039 local_iterator iprevious = pbucket->before_begin();
1040 local_iterator icurrent = first_.get_local_iterator();
1041 local_iterator iend = last_.get_local_iterator(); // Note: May not be in the same bucket as
1042 // icurrent.
1043
1044 // Find the node previous to the first one.
1045 while (iprevious->etl_next != &*icurrent)
1046 {
1047 ++iprevious;
1048 }
1049
1050 // Remember the item before the first erased one.
1051 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1052
1053 // Until we reach the end.
1054 while ((icurrent != iend) || (pbucket != pend_bucket))
1055 {
1056 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1057
1058 // Have we not reached the end?
1059 if ((icurrent != iend) || (pbucket != pend_bucket))
1060 {
1061 // At the end of this bucket?
1062 if ((icurrent == pbucket->end()))
1063 {
1064 // Find the next non-empty one.
1065 do {
1066 ++pbucket;
1067 } while (pbucket->empty());
1068
1069 iprevious = pbucket->before_begin();
1070 icurrent = pbucket->begin();
1071 }
1072 }
1073 }
1074
1075 return ++ibefore_erased;
1076 }
1077
1078 //*************************************************************************
1080 //*************************************************************************
1081 void clear()
1082 {
1083 initialise();
1084 }
1085
1086 //*********************************************************************
1090 //*********************************************************************
1091 size_t count(key_parameter_t key) const
1092 {
1093 size_t n = 0UL;
1094 const_iterator f = find(key);
1095 const_iterator l = f;
1096
1097 if (l != end())
1098 {
1099 ++l;
1100 ++n;
1101
1102 while ((l != end()) && key_equal_function(key, *l))
1103 {
1104 ++l;
1105 ++n;
1106 }
1107 }
1108
1109 return n;
1110 }
1111
1112#if ETL_USING_CPP11
1113 //*********************************************************************
1117 //*********************************************************************
1118 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1119 size_t count(const K& key) const
1120 {
1121 size_t n = 0UL;
1122 const_iterator f = find(key);
1123 const_iterator l = f;
1124
1125 if (l != end())
1126 {
1127 ++l;
1128 ++n;
1129
1130 while ((l != end()) && key_equal_function(key, *l))
1131 {
1132 ++l;
1133 ++n;
1134 }
1135 }
1136
1137 return n;
1138 }
1139#endif
1140
1141 //*********************************************************************
1145 //*********************************************************************
1146 iterator find(key_parameter_t key)
1147 {
1148 size_t index = get_bucket_index(key);
1149
1150 bucket_t* pbucket = pbuckets + index;
1151 bucket_t& bucket = *pbucket;
1152
1153 // Is the bucket not empty?
1154 if (!bucket.empty())
1155 {
1156 // Step though the list until we find the end or an equivalent key.
1157 local_iterator inode = bucket.begin();
1158 local_iterator iend = bucket.end();
1159
1160 while (inode != iend)
1161 {
1162 // Do we have this one?
1163 if (key_equal_function(key, inode->key))
1164 {
1165 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1166 }
1167
1168 ++inode;
1169 }
1170 }
1171
1172 return end();
1173 }
1174
1175#if ETL_USING_CPP11
1176 //*********************************************************************
1180 //*********************************************************************
1181 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1182 iterator find(const K& key)
1183 {
1184 size_t index = get_bucket_index(key);
1185
1186 bucket_t* pbucket = pbuckets + index;
1187 bucket_t& bucket = *pbucket;
1188
1189 // Is the bucket not empty?
1190 if (!bucket.empty())
1191 {
1192 // Step though the list until we find the end or an equivalent key.
1193 local_iterator inode = bucket.begin();
1194 local_iterator iend = bucket.end();
1195
1196 while (inode != iend)
1197 {
1198 // Do we have this one?
1199 if (key_equal_function(key, inode->key))
1200 {
1201 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1202 }
1203
1204 ++inode;
1205 }
1206 }
1207
1208 return end();
1209 }
1210#endif
1211
1212 //*********************************************************************
1216 //*********************************************************************
1217 const_iterator find(key_parameter_t key) const
1218 {
1219 size_t index = get_bucket_index(key);
1220
1221 bucket_t* pbucket = pbuckets + index;
1222 bucket_t& bucket = *pbucket;
1223
1224 // Is the bucket not empty?
1225 if (!bucket.empty())
1226 {
1227 // Step though the list until we find the end or an equivalent key.
1228 local_iterator inode = bucket.begin();
1229 local_iterator iend = bucket.end();
1230
1231 while (inode != iend)
1232 {
1233 // Do we have this one?
1234 if (key_equal_function(key, inode->key))
1235 {
1236 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1237 }
1238
1239 ++inode;
1240 }
1241 }
1242
1243 return end();
1244 }
1245
1246#if ETL_USING_CPP11
1247 //*********************************************************************
1251 //*********************************************************************
1252 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1253 const_iterator find(const K& key) const
1254 {
1255 size_t index = get_bucket_index(key);
1256
1257 bucket_t* pbucket = pbuckets + index;
1258 bucket_t& bucket = *pbucket;
1259
1260 // Is the bucket not empty?
1261 if (!bucket.empty())
1262 {
1263 // Step though the list until we find the end or an equivalent key.
1264 local_iterator inode = bucket.begin();
1265 local_iterator iend = bucket.end();
1266
1267 while (inode != iend)
1268 {
1269 // Do we have this one?
1270 if (key_equal_function(key, inode->key))
1271 {
1272 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1273 }
1274
1275 ++inode;
1276 }
1277 }
1278
1279 return end();
1280 }
1281#endif
1282
1283 //*********************************************************************
1291 //*********************************************************************
1292 ETL_OR_STD::pair<iterator, iterator> equal_range(key_parameter_t key)
1293 {
1294 iterator f = find(key);
1295 iterator l = f;
1296
1297 if (l != end())
1298 {
1299 ++l;
1300
1301 while ((l != end()) && key_equal_function(key, *l))
1302 {
1303 ++l;
1304 }
1305 }
1306
1307 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1308 }
1309
1310#if ETL_USING_CPP11
1311 //*********************************************************************
1319 //*********************************************************************
1320 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1321 ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
1322 {
1323 iterator f = find(key);
1324 iterator l = f;
1325
1326 if (l != end())
1327 {
1328 ++l;
1329
1330 while ((l != end()) && key_equal_function(key, *l))
1331 {
1332 ++l;
1333 }
1334 }
1335
1336 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1337 }
1338#endif
1339
1340 //*********************************************************************
1348 //*********************************************************************
1349 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(key_parameter_t key) const
1350 {
1351 const_iterator f = find(key);
1352 const_iterator l = f;
1353
1354 if (l != end())
1355 {
1356 ++l;
1357
1358 while ((l != end()) && key_equal_function(key, *l))
1359 {
1360 ++l;
1361 }
1362 }
1363
1364 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1365 }
1366
1367#if ETL_USING_CPP11
1368 //*********************************************************************
1376 //*********************************************************************
1377 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1378 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
1379 {
1380 const_iterator f = find(key);
1381 const_iterator l = f;
1382
1383 if (l != end())
1384 {
1385 ++l;
1386
1387 while ((l != end()) && key_equal_function(key, *l))
1388 {
1389 ++l;
1390 }
1391 }
1392
1393 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1394 }
1395#endif
1396
1397 //*************************************************************************
1399 //*************************************************************************
1400 size_type size() const
1401 {
1402 return pnodepool->size();
1403 }
1404
1405 //*************************************************************************
1407 //*************************************************************************
1408 size_type max_size() const
1409 {
1410 return pnodepool->max_size();
1411 }
1412
1413 //*************************************************************************
1415 //*************************************************************************
1416 size_type capacity() const
1417 {
1418 return pnodepool->max_size();
1419 }
1420
1421 //*************************************************************************
1423 //*************************************************************************
1424 bool empty() const
1425 {
1426 return pnodepool->empty();
1427 }
1428
1429 //*************************************************************************
1431 //*************************************************************************
1432 bool full() const
1433 {
1434 return pnodepool->full();
1435 }
1436
1437 //*************************************************************************
1440 //*************************************************************************
1441 size_t available() const
1442 {
1443 return pnodepool->available();
1444 }
1445
1446 //*************************************************************************
1449 //*************************************************************************
1450 float load_factor() const
1451 {
1452 return static_cast<float>(size()) / static_cast<float>(bucket_count());
1453 }
1454
1455 //*************************************************************************
1458 //*************************************************************************
1459 hasher hash_function() const
1460 {
1461 return key_hash_function;
1462 }
1463
1464 //*************************************************************************
1467 //*************************************************************************
1468 key_equal key_eq() const
1469 {
1470 return key_equal_function;
1471 }
1472
1473 //*************************************************************************
1475 //*************************************************************************
1477 {
1478 // Skip if doing self assignment
1479 if (this != &rhs)
1480 {
1481 key_hash_function = rhs.hash_function();
1482 key_equal_function = rhs.key_eq();
1483 assign(rhs.cbegin(), rhs.cend());
1484 }
1485
1486 return *this;
1487 }
1488
1489#if ETL_USING_CPP11
1490 //*************************************************************************
1492 //*************************************************************************
1494 {
1495 // Skip if doing self assignment
1496 if (this != &rhs)
1497 {
1498 clear();
1499 key_hash_function = rhs.hash_function();
1500 key_equal_function = rhs.key_eq();
1501 move(rhs.begin(), rhs.end());
1502 }
1503
1504 return *this;
1505 }
1506#endif
1507
1508 //*************************************************************************
1510 //*************************************************************************
1511 bool contains(key_parameter_t key) const
1512 {
1513 return find(key) != end();
1514 }
1515
1516#if ETL_USING_CPP11
1517 //*************************************************************************
1519 //*************************************************************************
1520 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1521 bool contains(const K& key) const
1522 {
1523 return find(key) != end();
1524 }
1525#endif
1526
1527 protected:
1528
1529 //*********************************************************************
1531 //*********************************************************************
1532 iunordered_multiset(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1533 : pnodepool(&node_pool_)
1534 , pbuckets(pbuckets_)
1535 , number_of_buckets(number_of_buckets_)
1536 , first(pbuckets)
1537 , last(pbuckets)
1538 , key_hash_function(key_hash_function_)
1539 , key_equal_function(key_equal_function_)
1540 {
1541 }
1542
1543 //*********************************************************************
1545 //*********************************************************************
1547 {
1548 if (!empty())
1549 {
1550 // For each bucket...
1551 for (size_t i = 0UL; i < number_of_buckets; ++i)
1552 {
1553 bucket_t& bucket = pbuckets[i];
1554
1555 if (!bucket.empty())
1556 {
1557 // For each item in the bucket...
1558 local_iterator it = bucket.begin();
1559
1560 while (it != bucket.end())
1561 {
1562 // Destroy the value contents.
1563 it->key.~value_type();
1564 ++it;
1565 ETL_DECREMENT_DEBUG_COUNT;
1566 }
1567
1568 // Now it's safe to clear the bucket.
1569 bucket.clear();
1570 }
1571 }
1572
1573 // Now it's safe to clear the entire pool in one go.
1574 pnodepool->release_all();
1575 }
1576
1577 first = pbuckets;
1578 last = first;
1579 }
1580
1581#if ETL_USING_CPP11
1582 //*************************************************************************
1584 //*************************************************************************
1585 void move(iterator b, iterator e)
1586 {
1587 while (b != e)
1588 {
1589 iterator temp = b;
1590 ++temp;
1591 insert(etl::move(*b));
1592 b = temp;
1593 }
1594 }
1595#endif
1596
1597 private:
1598
1599 //*************************************************************************
1601 //*************************************************************************
1602 node_t* allocate_data_node()
1603 {
1604 node_t* (etl::ipool::*func)() = &etl::ipool::allocate<node_t>;
1605 return (pnodepool->*func)();
1606 }
1607
1608 //*********************************************************************
1610 //*********************************************************************
1611 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1612 {
1613 if (size() == 1)
1614 {
1615 first = pbucket;
1616 last = pbucket;
1617 }
1618 else
1619 {
1620 if (pbucket < first)
1621 {
1622 first = pbucket;
1623 }
1624 else if (pbucket > last)
1625 {
1626 last = pbucket;
1627 }
1628 }
1629 }
1630
1631 //*********************************************************************
1633 //*********************************************************************
1634 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1635 {
1636 if (empty())
1637 {
1638 first = pbuckets;
1639 last = pbuckets;
1640 }
1641 else
1642 {
1643 if (pbucket == first)
1644 {
1645 // We erased the first so, we need to search again from where we
1646 // erased.
1647 while (first->empty())
1648 {
1649 ++first;
1650 }
1651 }
1652 else if (pbucket == last)
1653 {
1654 // We erased the last, so we need to search again. Start from the
1655 // first, go no further than the current last.
1656 pbucket = first;
1657 bucket_t* pend = last;
1658
1659 last = first;
1660
1661 while (pbucket != pend)
1662 {
1663 if (!pbucket->empty())
1664 {
1665 last = pbucket;
1666 }
1667
1668 ++pbucket;
1669 }
1670 }
1671 }
1672 }
1673
1674 //*********************************************************************
1676 //*********************************************************************
1677 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1678 {
1679 local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket.
1680 icurrent->key.~value_type(); // Destroy the value.
1681 pnodepool->release(&*icurrent); // Release it back to the pool.
1682 adjust_first_last_markers_after_erase(&bucket);
1683 ETL_DECREMENT_DEBUG_COUNT;
1684
1685 return inext;
1686 }
1687
1688 // Disable copy construction.
1690
1692 pool_t* pnodepool;
1693
1695 bucket_t* pbuckets;
1696
1698 const size_t number_of_buckets;
1699
1701 bucket_t* first;
1702 bucket_t* last;
1703
1705 hasher key_hash_function;
1706
1708 key_equal key_equal_function;
1709
1711 ETL_DECLARE_DEBUG_COUNT;
1712
1713 //*************************************************************************
1715 //*************************************************************************
1716#if defined(ETL_POLYMORPHIC_UNORDERED_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS)
1717
1718 public:
1719
1720 virtual ~iunordered_multiset() {}
1721#else
1722
1723 protected:
1724
1726#endif
1727 };
1728
1729 //***************************************************************************
1735 //***************************************************************************
1736 template <typename TKey, typename THash, typename TKeyEqual>
1738 {
1739 const bool sizes_match = (lhs.size() == rhs.size());
1740 bool elements_match = true;
1741
1743
1744 if (sizes_match)
1745 {
1746 itr_t l_begin = lhs.begin();
1747 itr_t l_end = lhs.end();
1748
1749 while ((l_begin != l_end) && elements_match)
1750 {
1751 const TKey l_value = *l_begin;
1752
1753 // See if the lhs keys exist in the rhs.
1754 ETL_OR_STD::pair<itr_t, itr_t> l_range = lhs.equal_range(l_value);
1755 ETL_OR_STD::pair<itr_t, itr_t> r_range = rhs.equal_range(l_value);
1756
1757 if (r_range.first != rhs.end())
1758 {
1759 bool distance_match = (etl::distance(l_range.first, l_range.second) == etl::distance(r_range.first, r_range.second));
1760
1761 if (distance_match)
1762 {
1763 elements_match = etl::is_permutation(l_range.first, l_range.second, r_range.first, r_range.second);
1764 }
1765 else
1766 {
1767 elements_match = false;
1768 }
1769 }
1770 else
1771 {
1772 elements_match = false;
1773 }
1774
1775 ++l_begin;
1776 }
1777 }
1778
1779 return (sizes_match && elements_match);
1780 }
1781
1782 //***************************************************************************
1788 //***************************************************************************
1789 template <typename TKey, typename THash, typename TKeyEqual>
1791 {
1792 return !(lhs == rhs);
1793 }
1794
1795 //*************************************************************************
1798 //*************************************************************************
1799 template <typename TKey, const size_t MAX_SIZE_, size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>,
1800 typename TKeyEqual = etl::equal_to<TKey> >
1801 class unordered_multiset : public etl::iunordered_multiset<TKey, THash, TKeyEqual>
1802 {
1803 private:
1804
1806
1807 public:
1808
1809 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
1810 static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_;
1811
1812 //*************************************************************************
1814 //*************************************************************************
1815 unordered_multiset(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1816 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1817 {
1818 }
1819
1820 //*************************************************************************
1822 //*************************************************************************
1824 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1825 {
1826 // Skip if doing self assignment
1827 if (this != &other)
1828 {
1829 base::assign(other.cbegin(), other.cend());
1830 }
1831 }
1832
1833#if ETL_USING_CPP11
1834 //*************************************************************************
1836 //*************************************************************************
1838 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1839 {
1840 // Skip if doing self assignment
1841 if (this != &other)
1842 {
1843 base::move(other.begin(), other.end());
1844 }
1845 }
1846#endif
1847
1848 //*************************************************************************
1853 //*************************************************************************
1854 template <typename TIterator>
1855 unordered_multiset(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1856 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1857 {
1858 base::assign(first_, last_);
1859 }
1860
1861#if ETL_HAS_INITIALIZER_LIST
1862 //*************************************************************************
1864 //*************************************************************************
1865 unordered_multiset(std::initializer_list<TKey> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1866 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1867 {
1868 base::assign(init.begin(), init.end());
1869 }
1870#endif
1871
1872 //*************************************************************************
1874 //*************************************************************************
1876 {
1878 }
1879
1880 //*************************************************************************
1882 //*************************************************************************
1884 {
1885 base::operator=(rhs);
1886
1887 return *this;
1888 }
1889
1890#if ETL_USING_CPP11
1891 //*************************************************************************
1893 //*************************************************************************
1894 unordered_multiset& operator=(unordered_multiset&& rhs)
1895 {
1896 base::operator=(etl::move(rhs));
1897
1898 return *this;
1899 }
1900#endif
1901
1902 private:
1903
1906
1908 typename base::bucket_t buckets[MAX_BUCKETS_];
1909 };
1910
1911 //*************************************************************************
1913 //*************************************************************************
1914#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
1915 template <typename... T>
1916 unordered_multiset(T...) -> unordered_multiset<etl::nth_type_t<0, T...>, sizeof...(T)>;
1917#endif
1918
1919 //*************************************************************************
1921 //*************************************************************************
1922#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
1923 template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey>, typename... T>
1924 constexpr auto make_unordered_multiset(T&&... keys) -> etl::unordered_multiset<TKey, sizeof...(T), sizeof...(T), THash, TKeyEqual>
1925 {
1926 return {etl::forward<T>(keys)...};
1927 }
1928#endif
1929} // namespace etl
1930
1931#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_multiset.h:324
Definition unordered_multiset.h:184
Definition unordered_multiset.h:1802
unordered_multiset(const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Default constructor.
Definition unordered_multiset.h:1815
unordered_multiset & operator=(const unordered_multiset &rhs)
Assignment operator.
Definition unordered_multiset.h:1883
~unordered_multiset()
Destructor.
Definition unordered_multiset.h:1875
unordered_multiset(const unordered_multiset &other)
Copy constructor.
Definition unordered_multiset.h:1823
unordered_multiset(TIterator first_, TIterator last_, const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Definition unordered_multiset.h:1855
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
~iunordered_multiset()
Destructor.
Definition unordered_multiset.h:1725
ETL_OR_STD::pair< iterator, bool > insert(const_reference key)
Definition unordered_multiset.h:682
size_t available() const
Definition unordered_multiset.h:1441
const_iterator cend() const
Definition unordered_multiset.h:553
iunordered_multiset & operator=(const iunordered_multiset &rhs)
Assignment operator.
Definition unordered_multiset.h:1476
const_iterator begin() const
Definition unordered_multiset.h:486
size_t erase(key_parameter_t key)
Definition unordered_multiset.h:929
void initialise()
Initialise the unordered_multiset.
Definition unordered_multiset.h:1546
iterator end()
Definition unordered_multiset.h:535
size_type max_size() const
Gets the maximum possible size of the unordered_multiset.
Definition unordered_multiset.h:1408
iterator insert(const_iterator, const_reference key)
Definition unordered_multiset.h:901
const_local_iterator end(size_t i) const
Definition unordered_multiset.h:571
size_type get_bucket_index(key_parameter_t key) const
Definition unordered_multiset.h:589
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(key_parameter_t key) const
Definition unordered_multiset.h:1349
const_iterator find(key_parameter_t key) const
Definition unordered_multiset.h:1217
local_iterator begin(size_t i)
Definition unordered_multiset.h:504
void assign(TIterator first_, TIterator last_)
Definition unordered_multiset.h:659
const_iterator cbegin() const
Definition unordered_multiset.h:495
iunordered_multiset(pool_t &node_pool_, bucket_t *pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
Constructor.
Definition unordered_multiset.h:1532
const_iterator end() const
Definition unordered_multiset.h:544
size_type bucket_size(key_parameter_t key) const
Definition unordered_multiset.h:610
void insert(TIterator first_, TIterator last_)
Definition unordered_multiset.h:915
void clear()
Clears the unordered_multiset.
Definition unordered_multiset.h:1081
const_local_iterator cend(size_t i) const
Definition unordered_multiset.h:580
bool contains(key_parameter_t key) const
Check if the unordered_multiset contains the key.
Definition unordered_multiset.h:1511
iterator erase(const_iterator first_, const_iterator last_)
Definition unordered_multiset.h:1027
const_local_iterator cbegin(size_t i) const
Definition unordered_multiset.h:526
iterator find(key_parameter_t key)
Definition unordered_multiset.h:1146
iterator begin()
Definition unordered_multiset.h:477
iterator erase(const_iterator ielement)
Definition unordered_multiset.h:999
key_equal key_eq() const
Definition unordered_multiset.h:1468
local_iterator end(size_t i)
Definition unordered_multiset.h:562
const_local_iterator begin(size_t i) const
Definition unordered_multiset.h:515
size_type max_bucket_count() const
Definition unordered_multiset.h:635
size_type size() const
Gets the size of the unordered_multiset.
Definition unordered_multiset.h:1400
hasher hash_function() const
Definition unordered_multiset.h:1459
size_type bucket_count() const
Definition unordered_multiset.h:644
size_type capacity() const
Gets the maximum possible size of the unordered_multiset.
Definition unordered_multiset.h:1416
size_t count(key_parameter_t key) const
Definition unordered_multiset.h:1091
bool full() const
Checks to see if the unordered_multiset is full.
Definition unordered_multiset.h:1432
float load_factor() const
Definition unordered_multiset.h:1450
ETL_OR_STD::pair< iterator, iterator > equal_range(key_parameter_t key)
Definition unordered_multiset.h:1292
bool empty() const
Checks to see if the unordered_multiset is empty.
Definition unordered_multiset.h:1424
Definition unordered_multiset.h:129
Definition unordered_multiset.h:70
Definition unordered_multiset.h:84
Definition unordered_multiset.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_multiset.h:152