Embedded Template Library 1.0
Loading...
Searching...
No Matches
unordered_set.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_SET_INCLUDED
32#define ETL_UNORDERED_SET_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_set_exception : public etl::exception
69 {
70 public:
71
72 unordered_set_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_set_full : public etl::unordered_set_exception
83 {
84 public:
85
86 unordered_set_full(string_type file_name_, numeric_type line_number_)
87 : etl::unordered_set_exception(ETL_ERROR_TEXT("unordered_set:full", ETL_UNORDERED_SET_FILE_ID"A"), file_name_, line_number_)
88 {
89 }
90 };
91
92 //***************************************************************************
95 //***************************************************************************
96 class unordered_set_out_of_range : public etl::unordered_set_exception
97 {
98 public:
99
100 unordered_set_out_of_range(string_type file_name_, numeric_type line_number_)
101 : etl::unordered_set_exception(ETL_ERROR_TEXT("unordered_set:range", ETL_UNORDERED_SET_FILE_ID"B"), file_name_, line_number_)
102 {
103 }
104 };
105
106 //***************************************************************************
109 //***************************************************************************
110 class unordered_set_iterator : public etl::unordered_set_exception
111 {
112 public:
113
114 unordered_set_iterator(string_type file_name_, numeric_type line_number_)
115 : etl::unordered_set_exception(ETL_ERROR_TEXT("unordered_set:iterator", ETL_UNORDERED_SET_FILE_ID"C"), file_name_, line_number_)
116 {
117 }
118 };
119
120 //***************************************************************************
125 //***************************************************************************
126 template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey> >
128 {
129 public:
130
131 typedef TKey value_type;
132 typedef TKey key_type;
133 typedef THash hasher;
134 typedef TKeyEqual key_equal;
135 typedef value_type& reference;
136 typedef const value_type& const_reference;
137#if ETL_USING_CPP11
138 typedef value_type&& rvalue_reference;
139#endif
140 typedef value_type* pointer;
141 typedef const value_type* const_pointer;
142 typedef size_t size_type;
143
144 typedef const TKey& key_parameter_t;
145
146 typedef etl::forward_link<0> link_t;
147
148 //*********************************************************************
149 // The nodes that store the elements.
150 struct node_t : public link_t
151 {
152 node_t(const_reference key_)
153 : key(key_)
154 {
155 }
156
157 value_type key;
158 };
159
160 friend bool operator==(const node_t& lhs, const node_t& rhs)
161 {
162 return (lhs.key == rhs.key);
163 }
164
165 friend bool operator!=(const node_t& lhs, const node_t& rhs)
166 {
167 return !(lhs == rhs);
168 }
169
170 protected:
171
173 typedef etl::ipool pool_t;
174
175 public:
176
177 // Local iterators iterate over one bucket.
178 typedef typename bucket_t::iterator local_iterator;
179 typedef typename bucket_t::const_iterator const_local_iterator;
180
181 //*********************************************************************
182 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>
183 {
184 public:
185
186 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, TKey>::value_type value_type;
187 typedef typename iunordered_set::key_type key_type;
188 typedef typename iunordered_set::hasher hasher;
189 typedef typename iunordered_set::key_equal key_equal;
190 typedef typename iunordered_set::reference reference;
191 typedef typename iunordered_set::const_reference const_reference;
192 typedef typename iunordered_set::pointer pointer;
193 typedef typename iunordered_set::const_pointer const_pointer;
194 typedef typename iunordered_set::size_type size_type;
195
196 friend class iunordered_set;
197 friend class const_iterator;
198
199 //*********************************
200 iterator() {}
201
202 //*********************************
203 iterator(const iterator& other)
204 : pbuckets_end(other.pbuckets_end)
205 , pbucket(other.pbucket)
206 , inode(other.inode)
207 {
208 }
209
210 //*********************************
211 iterator& operator++()
212 {
213 ++inode;
214
215 // The end of this node list?
216 if (inode == pbucket->end())
217 {
218 // Search for the next non-empty bucket.
219 ++pbucket;
220 while ((pbucket != pbuckets_end) && (pbucket->empty()))
221 {
222 ++pbucket;
223 }
224
225 // If not past the end, get the first node in the bucket.
226 if (pbucket != pbuckets_end)
227 {
228 inode = pbucket->begin();
229 }
230 }
231
232 return *this;
233 }
234
235 //*********************************
236 iterator operator++(int)
237 {
238 iterator temp(*this);
239 operator++();
240 return temp;
241 }
242
243 //*********************************
244 iterator& operator=(const iterator& other)
245 {
246 pbuckets_end = other.pbuckets_end;
247 pbucket = other.pbucket;
248 inode = other.inode;
249 return *this;
250 }
251
252 //*********************************
253 reference operator*() const
254 {
255 return inode->key;
256 }
257
258 //*********************************
259 pointer operator&() const
260 {
261 return &(inode->key);
262 }
263
264 //*********************************
265 pointer operator->() const
266 {
267 return &(inode->key);
268 }
269
270 //*********************************
271 friend bool operator==(const iterator& lhs, const iterator& rhs)
272 {
273 return lhs.compare(rhs);
274 }
275
276 //*********************************
277 friend bool operator!=(const iterator& lhs, const iterator& rhs)
278 {
279 return !(lhs == rhs);
280 }
281
282 private:
283
284 //*********************************
285 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
286 : pbuckets_end(pbuckets_end_)
287 , pbucket(pbucket_)
288 , inode(inode_)
289 {
290 }
291
292 //*********************************
293 bool compare(const iterator& rhs) const
294 {
295 return rhs.inode == inode;
296 }
297
298 //*********************************
299 bucket_t& get_bucket()
300 {
301 return *pbucket;
302 }
303
304 //*********************************
305 bucket_t*& get_bucket_list_iterator()
306 {
307 return pbucket;
308 }
309
310 //*********************************
311 local_iterator get_local_iterator()
312 {
313 return inode;
314 }
315
316 bucket_t* pbuckets_end;
317 bucket_t* pbucket;
318 local_iterator inode;
319 };
320
321 //*********************************************************************
322 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>
323 {
324 public:
325
326 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const TKey>::value_type value_type;
327 typedef typename iunordered_set::key_type key_type;
328 typedef typename iunordered_set::hasher hasher;
329 typedef typename iunordered_set::key_equal key_equal;
330 typedef typename iunordered_set::reference reference;
331 typedef typename iunordered_set::const_reference const_reference;
332 typedef typename iunordered_set::pointer pointer;
333 typedef typename iunordered_set::const_pointer const_pointer;
334 typedef typename iunordered_set::size_type size_type;
335
336 friend class iunordered_set;
337 friend class iterator;
338
339 //*********************************
340 const_iterator() {}
341
342 //*********************************
343 const_iterator(const typename iunordered_set::iterator& other)
344 : pbuckets_end(other.pbuckets_end)
345 , pbucket(other.pbucket)
346 , inode(other.inode)
347 {
348 }
349
350 //*********************************
351 const_iterator(const const_iterator& other)
352 : pbuckets_end(other.pbuckets_end)
353 , pbucket(other.pbucket)
354 , inode(other.inode)
355 {
356 }
357
358 //*********************************
359 const_iterator& operator++()
360 {
361 ++inode;
362
363 // The end of this node list?
364 if (inode == pbucket->end())
365 {
366 // Search for the next non-empty bucket.
367
368 ++pbucket;
369 while ((pbucket != pbuckets_end) && (pbucket->empty()))
370 {
371 ++pbucket;
372 }
373
374 // If not past the end, get the first node in the bucket.
375 if (pbucket != pbuckets_end)
376 {
377 inode = pbucket->begin();
378 }
379 }
380
381 return *this;
382 }
383
384 //*********************************
385 const_iterator operator++(int)
386 {
387 const_iterator temp(*this);
388 operator++();
389 return temp;
390 }
391
392 //*********************************
393 const_iterator& operator=(const const_iterator& other)
394 {
395 pbuckets_end = other.pbuckets_end;
396 pbucket = other.pbucket;
397 inode = other.inode;
398 return *this;
399 }
400
401 //*********************************
402 const_reference operator*() const
403 {
404 return inode->key;
405 }
406
407 //*********************************
408 const_pointer operator&() const
409 {
410 return &(inode->key);
411 }
412
413 //*********************************
414 const_pointer operator->() const
415 {
416 return &(inode->key);
417 }
418
419 //*********************************
420 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
421 {
422 return lhs.compare(rhs);
423 }
424
425 //*********************************
426 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
427 {
428 return !(lhs == rhs);
429 }
430
431 private:
432
433 //*********************************
434 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
435 : pbuckets_end(pbuckets_end_)
436 , pbucket(pbucket_)
437 , inode(inode_)
438 {
439 }
440
441 //*********************************
442 bool compare(const const_iterator& rhs) const
443 {
444 return rhs.inode == inode;
445 }
446
447 //*********************************
448 bucket_t& get_bucket()
449 {
450 return *pbucket;
451 }
452
453 //*********************************
454 bucket_t*& get_bucket_list_iterator()
455 {
456 return pbucket;
457 }
458
459 //*********************************
460 local_iterator get_local_iterator()
461 {
462 return inode;
463 }
464
465 bucket_t* pbuckets_end;
466 bucket_t* pbucket;
467 local_iterator inode;
468 };
469
470 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
471
472 //*********************************************************************
475 //*********************************************************************
476 iterator begin()
477 {
478 return iterator(pbuckets + number_of_buckets, first, first->begin());
479 }
480
481 //*********************************************************************
484 //*********************************************************************
485 const_iterator begin() const
486 {
487 return const_iterator(pbuckets + number_of_buckets, first, first->begin());
488 }
489
490 //*********************************************************************
493 //*********************************************************************
494 const_iterator cbegin() const
495 {
496 return const_iterator(pbuckets + number_of_buckets, first, first->begin());
497 }
498
499 //*********************************************************************
502 //*********************************************************************
503 local_iterator begin(size_t i)
504 {
505 return pbuckets[i].begin();
506 }
507
508 //*********************************************************************
511 //*********************************************************************
512 const_local_iterator begin(size_t i) const
513 {
514 return pbuckets[i].cbegin();
515 }
516
517 //*********************************************************************
520 //*********************************************************************
521 const_local_iterator cbegin(size_t i) const
522 {
523 return pbuckets[i].cbegin();
524 }
525
526 //*********************************************************************
529 //*********************************************************************
530 iterator end()
531 {
532 return iterator(pbuckets + number_of_buckets, last, last->end());
533 }
534
535 //*********************************************************************
538 //*********************************************************************
539 const_iterator end() const
540 {
541 return const_iterator(pbuckets + number_of_buckets, last, last->end());
542 }
543
544 //*********************************************************************
547 //*********************************************************************
548 const_iterator cend() const
549 {
550 return const_iterator(pbuckets + number_of_buckets, last, last->end());
551 }
552
553 //*********************************************************************
556 //*********************************************************************
557 local_iterator end(size_t i)
558 {
559 return pbuckets[i].end();
560 }
561
562 //*********************************************************************
565 //*********************************************************************
566 const_local_iterator end(size_t i) const
567 {
568 return pbuckets[i].cend();
569 }
570
571 //*********************************************************************
574 //*********************************************************************
575 const_local_iterator cend(size_t i) const
576 {
577 return pbuckets[i].cend();
578 }
579
580 //*********************************************************************
583 //*********************************************************************
584 size_type get_bucket_index(key_parameter_t key) const
585 {
586 return key_hash_function(key) % number_of_buckets;
587 }
588
589#if ETL_USING_CPP11
590 //*********************************************************************
593 //*********************************************************************
594 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
595 size_type get_bucket_index(const K& key) const
596 {
597 return key_hash_function(key) % number_of_buckets;
598 }
599#endif
600
601 //*********************************************************************
604 //*********************************************************************
605 size_type bucket_size(key_parameter_t key) const
606 {
607 size_t index = bucket(key);
608
609 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
610 }
611
612#if ETL_USING_CPP11
613 //*********************************************************************
616 //*********************************************************************
617 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
618 size_type bucket_size(const K& key) const
619 {
620 size_t index = bucket(key);
621
622 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
623 }
624#endif
625
626 //*********************************************************************
629 //*********************************************************************
630 size_type max_bucket_count() const
631 {
632 return number_of_buckets;
633 }
634
635 //*********************************************************************
638 //*********************************************************************
639 size_type bucket_count() const
640 {
641 return number_of_buckets;
642 }
643
644 //*********************************************************************
651 //*********************************************************************
652 template <typename TIterator>
653 void assign(TIterator first_, TIterator last_)
654 {
655#if ETL_IS_DEBUG_BUILD
656 difference_type d = etl::distance(first_, last_);
657 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_set_iterator));
658 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_set_full));
659#endif
660
661 clear();
662
663 while (first_ != last_)
664 {
665 insert(*first_);
666 ++first_;
667 }
668 }
669
670 //*********************************************************************
675 //*********************************************************************
676 ETL_OR_STD::pair<iterator, bool> insert(const_reference key)
677 {
678 ETL_OR_STD::pair<iterator, bool> result(end(), false);
679
680 if (full())
681 {
682 iterator iter = find(key);
683 if (iter == end())
684 {
685 ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
686 }
687 else
688 {
689 result.first = iter;
690 result.second = false;
691 return result;
692 }
693 }
694
695 // Get the hash index.
696 size_t index = get_bucket_index(key);
697
698 // Get the bucket & bucket iterator.
699 bucket_t* pbucket = pbuckets + index;
700 bucket_t& bucket = *pbucket;
701
702 // The first one in the bucket?
703 if (bucket.empty())
704 {
705 // Get a new node.
706 node_t* node = allocate_data_node();
707 node->clear();
708 ::new (&node->key) value_type(key);
709 ETL_INCREMENT_DEBUG_COUNT;
710
711 // Just add the pointer to the bucket;
712 bucket.insert_after(bucket.before_begin(), *node);
713 adjust_first_last_markers_after_insert(&bucket);
714
715 result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
716 result.second = true;
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, key))
728 {
729 break;
730 }
731
732 ++inode_previous;
733 ++inode;
734 }
735
736 // Not already there?
737 if (inode == bucket.end())
738 {
739 // Get a new node.
740 node_t* node = allocate_data_node();
741 node->clear();
742 ::new (&node->key) value_type(key);
743 ETL_INCREMENT_DEBUG_COUNT;
744
745 // Add the node to the end of the bucket;
746 bucket.insert_after(inode_previous, *node);
747 adjust_first_last_markers_after_insert(&bucket);
748 ++inode_previous;
749
750 result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
751 result.second = true;
752 }
753 }
754
755 return result;
756 }
757
758#if ETL_USING_CPP11
759 //*********************************************************************
764 //*********************************************************************
765 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
766 ETL_OR_STD::pair<iterator, bool> insert(const K& key)
767 {
768 ETL_OR_STD::pair<iterator, bool> result(end(), false);
769
770 if (full())
771 {
772 iterator iter = find(key);
773 if (iter == end())
774 {
775 ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
776 }
777 else
778 {
779 result.first = iter;
780 result.second = false;
781 return result;
782 }
783 }
784
785 // Get the hash index.
786 size_t index = get_bucket_index(key);
787
788 // Get the bucket & bucket iterator.
789 bucket_t* pbucket = pbuckets + index;
790 bucket_t& bucket = *pbucket;
791
792 // The first one in the bucket?
793 if (bucket.empty())
794 {
795 // Get a new node.
796 node_t* node = allocate_data_node();
797 node->clear();
798 ::new (&node->key) value_type(key);
799 ETL_INCREMENT_DEBUG_COUNT;
800
801 // Just add the pointer to the bucket;
802 bucket.insert_after(bucket.before_begin(), *node);
803 adjust_first_last_markers_after_insert(&bucket);
804
805 result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
806 result.second = true;
807 }
808 else
809 {
810 // Step though the bucket looking for a place to insert.
811 local_iterator inode_previous = bucket.before_begin();
812 local_iterator inode = bucket.begin();
813
814 while (inode != bucket.end())
815 {
816 // Do we already have this key?
817 if (key_equal_function(inode->key, key))
818 {
819 break;
820 }
821
822 ++inode_previous;
823 ++inode;
824 }
825
826 // Not already there?
827 if (inode == bucket.end())
828 {
829 // Get a new node.
830 node_t* node = allocate_data_node();
831 node->clear();
832 ::new (&node->key) value_type(key);
833 ETL_INCREMENT_DEBUG_COUNT;
834
835 // Add the node to the end of the bucket;
836 bucket.insert_after(inode_previous, *node);
837 adjust_first_last_markers_after_insert(&bucket);
838 ++inode_previous;
839
840 result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
841 result.second = true;
842 }
843 }
844
845 return result;
846 }
847#endif
848
849#if ETL_USING_CPP11
850 //*********************************************************************
855 //*********************************************************************
856 ETL_OR_STD::pair<iterator, bool> insert(rvalue_reference key)
857 {
858 ETL_OR_STD::pair<iterator, bool> result(end(), false);
859
860 if (full())
861 {
862 iterator iter = find(key);
863 if (iter == end())
864 {
865 ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
866 }
867 else
868 {
869 result.first = iter;
870 result.second = false;
871 return result;
872 }
873 }
874
875 // Get the hash index.
876 size_t index = get_bucket_index(key);
877
878 // Get the bucket & bucket iterator.
879 bucket_t* pbucket = pbuckets + index;
880 bucket_t& bucket = *pbucket;
881
882 // The first one in the bucket?
883 if (bucket.empty())
884 {
885 // Get a new node.
886 node_t* node = allocate_data_node();
887 node->clear();
888 ::new (&node->key) value_type(etl::move(key));
889 ETL_INCREMENT_DEBUG_COUNT;
890
891 // Just add the pointer to the bucket;
892 bucket.insert_after(bucket.before_begin(), *node);
893 adjust_first_last_markers_after_insert(&bucket);
894
895 result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
896 result.second = true;
897 }
898 else
899 {
900 // Step though the bucket looking for a place to insert.
901 local_iterator inode_previous = bucket.before_begin();
902 local_iterator inode = bucket.begin();
903
904 while (inode != bucket.end())
905 {
906 // Do we already have this key?
907 if (key_equal_function(inode->key, key))
908 {
909 break;
910 }
911
912 ++inode_previous;
913 ++inode;
914 }
915
916 // Not already there?
917 if (inode == bucket.end())
918 {
919 // Get a new node.
920 node_t* node = allocate_data_node();
921 node->clear();
922 ::new (&node->key) value_type(etl::move(key));
923 ETL_INCREMENT_DEBUG_COUNT;
924
925 // Add the node to the end of the bucket;
926 bucket.insert_after(inode_previous, *node);
927 adjust_first_last_markers_after_insert(&bucket);
928 ++inode_previous;
929
930 result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
931 result.second = true;
932 }
933 }
934
935 return result;
936 }
937#endif
938
939 //*********************************************************************
945 //*********************************************************************
946 iterator insert(const_iterator, const_reference key)
947 {
948 return insert(key).first;
949 }
950
951#if ETL_USING_CPP11
952 //*********************************************************************
958 //*********************************************************************
959 iterator insert(const_iterator, rvalue_reference key)
960 {
961 return insert(etl::move(key)).first;
962 }
963#endif
964
965 //*********************************************************************
972 //*********************************************************************
973 template <class TIterator>
974 void insert(TIterator first_, TIterator last_)
975 {
976 while (first_ != last_)
977 {
978 insert(*first_);
979 ++first_;
980 }
981 }
982
983#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
984 //*********************************************************************
986 //*********************************************************************
987 template <typename... Args>
988 ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
989 {
990 ETL_OR_STD::pair<iterator, bool> result(end(), false);
991
992 if (full())
993 {
994 // A duplicate key does not require a free node, so emplacing it is not
995 // a capacity failure. Construct a temporary to obtain its key and only
996 // emit unordered_set_full if the key is not already present. This keeps
997 // emplace consistent with insert when the unordered_set is full.
998 value_type temp_value(etl::forward<Args>(args)...);
999 iterator position = find(temp_value);
1000
1001 if (position == end())
1002 {
1003 ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
1004 return result;
1005 }
1006
1007 result.first = position;
1008 result.second = false;
1009 return result;
1010 }
1011
1012 // Construct the value in a temporary to get the key for hashing.
1013 node_t* node = allocate_data_node();
1014 node->clear();
1015 ::new (&node->key) value_type(etl::forward<Args>(args)...);
1016 ETL_INCREMENT_DEBUG_COUNT;
1017
1018 key_parameter_t key = node->key;
1019
1020 // Get the hash index.
1021 size_t index = get_bucket_index(key);
1022
1023 // Get the bucket & bucket iterator.
1024 bucket_t* pbucket = pbuckets + index;
1025 bucket_t& bucket = *pbucket;
1026
1027 // The first one in the bucket?
1028 if (bucket.empty())
1029 {
1030 // Just add the pointer to the bucket;
1031 bucket.insert_after(bucket.before_begin(), *node);
1032 adjust_first_last_markers_after_insert(&bucket);
1033
1034 result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
1035 result.second = true;
1036 }
1037 else
1038 {
1039 // Step though the bucket looking for a place to insert.
1040 local_iterator inode_previous = bucket.before_begin();
1041 local_iterator inode = bucket.begin();
1042
1043 while (inode != bucket.end())
1044 {
1045 // Do we already have this key?
1046 if (key_equal_function(inode->key, key))
1047 {
1048 break;
1049 }
1050
1051 ++inode_previous;
1052 ++inode;
1053 }
1054
1055 // Not already there?
1056 if (inode == bucket.end())
1057 {
1058 // Add the node to the end of the bucket;
1059 bucket.insert_after(inode_previous, *node);
1060 adjust_first_last_markers_after_insert(&bucket);
1061 ++inode_previous;
1062
1063 result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
1064 result.second = true;
1065 }
1066 else
1067 {
1068 // Duplicate found, destroy the node
1069 node->key.~value_type();
1070 pnodepool->release(node);
1071 ETL_DECREMENT_DEBUG_COUNT;
1072 }
1073 }
1074
1075 return result;
1076 }
1077#endif
1078
1079 //*********************************************************************
1083 //*********************************************************************
1084 size_t erase(key_parameter_t key)
1085 {
1086 size_t n = 0UL;
1087 size_t index = get_bucket_index(key);
1088
1089 bucket_t& bucket = pbuckets[index];
1090
1091 local_iterator iprevious = bucket.before_begin();
1092 local_iterator icurrent = bucket.begin();
1093
1094 // Search for the key, if we have it.
1095 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key, key)))
1096 {
1097 ++iprevious;
1098 ++icurrent;
1099 }
1100
1101 // Did we find it?
1102 if (icurrent != bucket.end())
1103 {
1104 delete_data_node(iprevious, icurrent, bucket);
1105 n = 1;
1106 }
1107
1108 return n;
1109 }
1110
1111#if ETL_USING_CPP11
1112 //*********************************************************************
1116 //*********************************************************************
1117 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1118 size_t erase(const K& key)
1119 {
1120 size_t n = 0UL;
1121 size_t index = get_bucket_index(key);
1122
1123 bucket_t& bucket = pbuckets[index];
1124
1125 local_iterator iprevious = bucket.before_begin();
1126 local_iterator icurrent = bucket.begin();
1127
1128 // Search for the key, if we have it.
1129 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key, key)))
1130 {
1131 ++iprevious;
1132 ++icurrent;
1133 }
1134
1135 // Did we find it?
1136 if (icurrent != bucket.end())
1137 {
1138 delete_data_node(iprevious, icurrent, bucket);
1139 n = 1;
1140 }
1141
1142 return n;
1143 }
1144#endif
1145
1146 //*********************************************************************
1149 //*********************************************************************
1150 iterator erase(const_iterator ielement)
1151 {
1152 // Make a note of the next one.
1153 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1154 ++inext;
1155
1156 bucket_t& bucket = ielement.get_bucket();
1157 local_iterator iprevious = bucket.before_begin();
1158 local_iterator icurrent = ielement.get_local_iterator();
1159
1160 // Find the node previous to the one we're interested in.
1161 while (iprevious->etl_next != &*icurrent)
1162 {
1163 ++iprevious;
1164 }
1165
1166 delete_data_node(iprevious, icurrent, bucket);
1167
1168 return inext;
1169 }
1170
1171 //*********************************************************************
1177 //*********************************************************************
1178 iterator erase(const_iterator first_, const_iterator last_)
1179 {
1180 // Erasing everything?
1181 if ((first_ == begin()) && (last_ == end()))
1182 {
1183 clear();
1184 return end();
1185 }
1186
1187 // Get the starting point.
1188 bucket_t* pbucket = first_.get_bucket_list_iterator();
1189 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1190 local_iterator iprevious = pbucket->before_begin();
1191 local_iterator icurrent = first_.get_local_iterator();
1192 local_iterator iend = last_.get_local_iterator(); // Note: May not be in the same bucket as
1193 // icurrent.
1194
1195 // Find the node previous to the first one.
1196 while (iprevious->etl_next != &*icurrent)
1197 {
1198 ++iprevious;
1199 }
1200
1201 // Remember the item before the first erased one.
1202 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1203
1204 // Until we reach the end.
1205 while ((icurrent != iend) || (pbucket != pend_bucket))
1206 {
1207 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1208
1209 // Have we not reached the end?
1210 if ((icurrent != iend) || (pbucket != pend_bucket))
1211 {
1212 // At the end of this bucket?
1213 if ((icurrent == pbucket->end()))
1214 {
1215 // Find the next non-empty one.
1216 do {
1217 ++pbucket;
1218 } while (pbucket->empty());
1219
1220 iprevious = pbucket->before_begin();
1221 icurrent = pbucket->begin();
1222 }
1223 }
1224 }
1225
1226 return ++ibefore_erased;
1227 }
1228
1229 //*************************************************************************
1231 //*************************************************************************
1232 void clear()
1233 {
1234 initialise();
1235 }
1236
1237 //*********************************************************************
1241 //*********************************************************************
1242 size_t count(key_parameter_t key) const
1243 {
1244 return (find(key) == end()) ? 0 : 1;
1245 }
1246
1247#if ETL_USING_CPP11
1248 //*********************************************************************
1252 //*********************************************************************
1253 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1254 size_t count(const K& key) const
1255 {
1256 return (find(key) == end()) ? 0 : 1;
1257 }
1258#endif
1259
1260 //*********************************************************************
1264 //*********************************************************************
1265 iterator find(key_parameter_t key)
1266 {
1267 size_t index = get_bucket_index(key);
1268
1269 bucket_t* pbucket = pbuckets + index;
1270 bucket_t& bucket = *pbucket;
1271
1272 // Is the bucket not empty?
1273 if (!bucket.empty())
1274 {
1275 // Step though the list until we find the end or an equivalent key.
1276 local_iterator inode = bucket.begin();
1277 local_iterator iend = bucket.end();
1278
1279 while (inode != iend)
1280 {
1281 // Do we have this one?
1282 if (key_equal_function(key, inode->key))
1283 {
1284 return iterator(pbuckets + number_of_buckets, pbucket, inode);
1285 }
1286
1287 ++inode;
1288 }
1289 }
1290
1291 return end();
1292 }
1293
1294 //*********************************************************************
1298 //*********************************************************************
1299 const_iterator find(key_parameter_t key) const
1300 {
1301 size_t index = get_bucket_index(key);
1302
1303 bucket_t* pbucket = pbuckets + index;
1304 bucket_t& bucket = *pbucket;
1305
1306 // Is the bucket not empty?
1307 if (!bucket.empty())
1308 {
1309 // Step though the list until we find the end or an equivalent key.
1310 local_iterator inode = bucket.begin();
1311 local_iterator iend = bucket.end();
1312
1313 while (inode != iend)
1314 {
1315 // Do we have this one?
1316 if (key_equal_function(key, inode->key))
1317 {
1318 return iterator(pbuckets + number_of_buckets, pbucket, inode);
1319 }
1320
1321 ++inode;
1322 }
1323 }
1324
1325 return end();
1326 }
1327
1328#if ETL_USING_CPP11
1329 //*********************************************************************
1333 //*********************************************************************
1334 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1335 iterator find(const K& key)
1336 {
1337 size_t index = get_bucket_index(key);
1338
1339 bucket_t* pbucket = pbuckets + index;
1340 bucket_t& bucket = *pbucket;
1341
1342 // Is the bucket not empty?
1343 if (!bucket.empty())
1344 {
1345 // Step though the list until we find the end or an equivalent key.
1346 local_iterator inode = bucket.begin();
1347 local_iterator iend = bucket.end();
1348
1349 while (inode != iend)
1350 {
1351 // Do we have this one?
1352 if (key_equal_function(key, inode->key))
1353 {
1354 return iterator(pbuckets + number_of_buckets, pbucket, inode);
1355 }
1356
1357 ++inode;
1358 }
1359 }
1360
1361 return end();
1362 }
1363#endif
1364
1365#if ETL_USING_CPP11
1366 //*********************************************************************
1370 //*********************************************************************
1371 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1372 const_iterator find(const K& key) const
1373 {
1374 size_t index = get_bucket_index(key);
1375
1376 bucket_t* pbucket = pbuckets + index;
1377 bucket_t& bucket = *pbucket;
1378
1379 // Is the bucket not empty?
1380 if (!bucket.empty())
1381 {
1382 // Step though the list until we find the end or an equivalent key.
1383 local_iterator inode = bucket.begin();
1384 local_iterator iend = bucket.end();
1385
1386 while (inode != iend)
1387 {
1388 // Do we have this one?
1389 if (key_equal_function(key, inode->key))
1390 {
1391 return iterator(pbuckets + number_of_buckets, pbucket, inode);
1392 }
1393
1394 ++inode;
1395 }
1396 }
1397
1398 return end();
1399 }
1400#endif
1401
1402 //*********************************************************************
1410 //*********************************************************************
1411 ETL_OR_STD::pair<iterator, iterator> equal_range(key_parameter_t key)
1412 {
1413 iterator f = find(key);
1414 iterator l = f;
1415
1416 if (l != end())
1417 {
1418 ++l;
1419 }
1420
1421 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1422 }
1423
1424 //*********************************************************************
1432 //*********************************************************************
1433 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(key_parameter_t key) const
1434 {
1435 const_iterator f = find(key);
1436 const_iterator l = f;
1437
1438 if (l != end())
1439 {
1440 ++l;
1441 }
1442
1443 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1444 }
1445
1446#if ETL_USING_CPP11
1447 //*********************************************************************
1455 //*********************************************************************
1456 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1457 ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
1458 {
1459 iterator f = find(key);
1460 iterator l = f;
1461
1462 if (l != end())
1463 {
1464 ++l;
1465 }
1466
1467 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1468 }
1469#endif
1470
1471#if ETL_USING_CPP11
1472 //*********************************************************************
1480 //*********************************************************************
1481 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1482 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
1483 {
1484 const_iterator f = find(key);
1485 const_iterator l = f;
1486
1487 if (l != end())
1488 {
1489 ++l;
1490 }
1491
1492 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1493 }
1494#endif
1495
1496 //*************************************************************************
1498 //*************************************************************************
1499 size_type size() const
1500 {
1501 return pnodepool->size();
1502 }
1503
1504 //*************************************************************************
1506 //*************************************************************************
1507 size_type max_size() const
1508 {
1509 return pnodepool->max_size();
1510 }
1511
1512 //*************************************************************************
1514 //*************************************************************************
1515 size_type capacity() const
1516 {
1517 return pnodepool->max_size();
1518 }
1519
1520 //*************************************************************************
1522 //*************************************************************************
1523 bool empty() const
1524 {
1525 return pnodepool->empty();
1526 }
1527
1528 //*************************************************************************
1530 //*************************************************************************
1531 bool full() const
1532 {
1533 return pnodepool->full();
1534 }
1535
1536 //*************************************************************************
1539 //*************************************************************************
1540 size_t available() const
1541 {
1542 return pnodepool->available();
1543 }
1544
1545 //*************************************************************************
1548 //*************************************************************************
1549 float load_factor() const
1550 {
1551 return static_cast<float>(size()) / static_cast<float>(bucket_count());
1552 }
1553
1554 //*************************************************************************
1557 //*************************************************************************
1558 hasher hash_function() const
1559 {
1560 return key_hash_function;
1561 }
1562
1563 //*************************************************************************
1566 //*************************************************************************
1567 key_equal key_eq() const
1568 {
1569 return key_equal_function;
1570 }
1571
1572 //*************************************************************************
1574 //*************************************************************************
1576 {
1577 // Skip if doing self assignment
1578 if (this != &rhs)
1579 {
1580 key_hash_function = rhs.hash_function();
1581 key_equal_function = rhs.key_eq();
1582 assign(rhs.cbegin(), rhs.cend());
1583 }
1584
1585 return *this;
1586 }
1587
1588#if ETL_USING_CPP11
1589 //*************************************************************************
1591 //*************************************************************************
1593 {
1594 // Skip if doing self assignment
1595 if (this != &rhs)
1596 {
1597 clear();
1598 key_hash_function = rhs.hash_function();
1599 key_equal_function = rhs.key_eq();
1600 move(rhs.begin(), rhs.end());
1601 }
1602
1603 return *this;
1604 }
1605#endif
1606
1607 //*************************************************************************
1609 //*************************************************************************
1610 bool contains(key_parameter_t key) const
1611 {
1612 return find(key) != end();
1613 }
1614
1615#if ETL_USING_CPP11
1616 //*************************************************************************
1618 //*************************************************************************
1619 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1620 bool contains(const K& key) const
1621 {
1622 return find(key) != end();
1623 }
1624#endif
1625
1626 protected:
1627
1628 //*********************************************************************
1630 //*********************************************************************
1631 iunordered_set(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1632 : pnodepool(&node_pool_)
1633 , pbuckets(pbuckets_)
1634 , number_of_buckets(number_of_buckets_)
1635 , first(pbuckets)
1636 , last(pbuckets)
1637 , key_hash_function(key_hash_function_)
1638 , key_equal_function(key_equal_function_)
1639 {
1640 }
1641
1642 //*********************************************************************
1644 //*********************************************************************
1646 {
1647 if (!empty())
1648 {
1649 // For each bucket...
1650 for (size_t i = 0UL; i < number_of_buckets; ++i)
1651 {
1652 bucket_t& bucket = pbuckets[i];
1653
1654 if (!bucket.empty())
1655 {
1656 // For each item in the bucket...
1657 local_iterator it = bucket.begin();
1658
1659 while (it != bucket.end())
1660 {
1661 // Destroy the value contents.
1662 it->key.~value_type();
1663 ++it;
1664 ETL_DECREMENT_DEBUG_COUNT;
1665 }
1666
1667 // Now it's safe to clear the bucket.
1668 bucket.clear();
1669 }
1670 }
1671
1672 // Now it's safe to clear the entire pool in one go.
1673 pnodepool->release_all();
1674 }
1675
1676 first = pbuckets;
1677 last = first;
1678 }
1679
1680#if ETL_USING_CPP11
1681 //*************************************************************************
1683 //*************************************************************************
1684 void move(iterator b, iterator e)
1685 {
1686 #if ETL_IS_DEBUG_BUILD
1687 difference_type d = etl::distance(b, e);
1688 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_set_iterator));
1689 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_set_full));
1690 #endif
1691
1692 while (b != e)
1693 {
1694 iterator temp = b;
1695 ++temp;
1696 insert(etl::move(*b));
1697 b = temp;
1698 }
1699 }
1700#endif
1701
1702 private:
1703
1704 //*************************************************************************
1706 //*************************************************************************
1707 node_t* allocate_data_node()
1708 {
1709 node_t* (etl::ipool::*func)() = &etl::ipool::allocate<node_t>;
1710 return (pnodepool->*func)();
1711 }
1712
1713 //*********************************************************************
1715 //*********************************************************************
1716 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1717 {
1718 if (size() == 1)
1719 {
1720 first = pbucket;
1721 last = pbucket;
1722 }
1723 else
1724 {
1725 if (pbucket < first)
1726 {
1727 first = pbucket;
1728 }
1729 else if (pbucket > last)
1730 {
1731 last = pbucket;
1732 }
1733 }
1734 }
1735
1736 //*********************************************************************
1738 //*********************************************************************
1739 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1740 {
1741 if (empty())
1742 {
1743 first = pbuckets;
1744 last = pbuckets;
1745 }
1746 else
1747 {
1748 if (pbucket == first)
1749 {
1750 // We erased the first so, we need to search again from where we
1751 // erased.
1752 while (first->empty())
1753 {
1754 ++first;
1755 }
1756 }
1757 else if (pbucket == last)
1758 {
1759 // We erased the last, so we need to search again. Start from the
1760 // first, go no further than the current last.
1761 pbucket = first;
1762 bucket_t* pend = last;
1763
1764 last = first;
1765
1766 while (pbucket != pend)
1767 {
1768 if (!pbucket->empty())
1769 {
1770 last = pbucket;
1771 }
1772
1773 ++pbucket;
1774 }
1775 }
1776 }
1777 }
1778
1779 //*********************************************************************
1781 //*********************************************************************
1782 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1783 {
1784 local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket.
1785 icurrent->key.~value_type(); // Destroy the value.
1786 pnodepool->release(&*icurrent); // Release it back to the pool.
1787 adjust_first_last_markers_after_erase(&bucket);
1788 ETL_DECREMENT_DEBUG_COUNT;
1789
1790 return inext;
1791 }
1792
1793 // Disable copy construction.
1795
1797 pool_t* pnodepool;
1798
1800 bucket_t* pbuckets;
1801
1803 const size_t number_of_buckets;
1804
1806 bucket_t* first;
1807 bucket_t* last;
1808
1810 hasher key_hash_function;
1811
1813 key_equal key_equal_function;
1814
1816 ETL_DECLARE_DEBUG_COUNT;
1817
1818 //*************************************************************************
1820 //*************************************************************************
1821#if defined(ETL_POLYMORPHIC_UNORDERED_SET) || defined(ETL_POLYMORPHIC_CONTAINERS)
1822
1823 public:
1824
1825 virtual ~iunordered_set() {}
1826#else
1827
1828 protected:
1829
1831#endif
1832 };
1833
1834 //***************************************************************************
1840 //***************************************************************************
1841 template <typename TKey, typename THash, typename TKeyEqual>
1843 {
1844 const bool sizes_match = (lhs.size() == rhs.size());
1845 bool elements_match = true;
1846
1848
1849 if (sizes_match)
1850 {
1851 itr_t l_begin = lhs.begin();
1852 itr_t l_end = lhs.end();
1853
1854 while ((l_begin != l_end) && elements_match)
1855 {
1856 const TKey l_value = *l_begin;
1857
1858 // See if the lhs key exists in the rhs.
1859 ETL_OR_STD::pair<itr_t, itr_t> range = rhs.equal_range(l_value);
1860
1861 if (range.first != rhs.end())
1862 {
1863 // See if the values match
1864 const TKey r_value = *(range.first);
1865
1866 elements_match = (r_value == l_value);
1867 }
1868 else
1869 {
1870 elements_match = false;
1871 }
1872
1873 ++l_begin;
1874 }
1875 }
1876
1877 return (sizes_match && elements_match);
1878 }
1879
1880 //***************************************************************************
1886 //***************************************************************************
1887 template <typename TKey, typename THash, typename TKeyEqual>
1889 {
1890 return !(lhs == rhs);
1891 }
1892
1893 //*************************************************************************
1895 //*************************************************************************
1896 template <typename TKey, const size_t MAX_SIZE_, size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>,
1897 typename TKeyEqual = etl::equal_to<TKey> >
1898 class unordered_set : public etl::iunordered_set<TKey, THash, TKeyEqual>
1899 {
1900 private:
1901
1903
1904 public:
1905
1906 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
1907 static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_;
1908
1909 //*************************************************************************
1911 //*************************************************************************
1912 unordered_set(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1913 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1914 {
1915 }
1916
1917 //*************************************************************************
1919 //*************************************************************************
1921 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1922 {
1923 // Skip if doing self assignment
1924 if (this != &other)
1925 {
1926 base::assign(other.cbegin(), other.cend());
1927 }
1928 }
1929
1930#if ETL_USING_CPP11
1931 //*************************************************************************
1933 //*************************************************************************
1935 : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq())
1936 {
1937 // Skip if doing self assignment
1938 if (this != &other)
1939 {
1940 base::move(other.begin(), other.end());
1941 }
1942 }
1943#endif
1944
1945 //*************************************************************************
1950 //*************************************************************************
1951 template <typename TIterator>
1952 unordered_set(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1953 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1954 {
1955 base::assign(first_, last_);
1956 }
1957
1958#if ETL_HAS_INITIALIZER_LIST
1959 //*************************************************************************
1961 //*************************************************************************
1962 unordered_set(std::initializer_list<TKey> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1963 : base(node_pool, buckets, MAX_BUCKETS, hash, equal)
1964 {
1965 base::assign(init.begin(), init.end());
1966 }
1967#endif
1968
1969 //*************************************************************************
1971 //*************************************************************************
1973 {
1975 }
1976
1977 //*************************************************************************
1979 //*************************************************************************
1981 {
1982 base::operator=(rhs);
1983
1984 return *this;
1985 }
1986
1987#if ETL_USING_CPP11
1988 //*************************************************************************
1990 //*************************************************************************
1991 unordered_set& operator=(unordered_set&& rhs)
1992 {
1993 base::operator=(etl::move(rhs));
1994
1995 return *this;
1996 }
1997#endif
1998
1999 private:
2000
2003
2005 typename base::bucket_t buckets[MAX_BUCKETS_];
2006 };
2007
2008 //*************************************************************************
2010 //*************************************************************************
2011#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
2012 template <typename... T>
2013 unordered_set(T...) -> unordered_set<etl::nth_type_t<0, T...>, sizeof...(T)>;
2014#endif
2015
2016 //*************************************************************************
2018 //*************************************************************************
2019#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
2020 template <typename TKey, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey>, typename... T>
2021 constexpr auto make_unordered_set(T&&... keys) -> etl::unordered_set<TKey, sizeof...(T), sizeof...(T), THash, TKeyEqual>
2022 {
2023 return {etl::forward<T>(keys)...};
2024 }
2025#endif
2026} // namespace etl
2027
2028#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_set.h:323
Definition unordered_set.h:183
A templated unordered_set implementation that uses a fixed size buffer.
Definition unordered_set.h:1899
unordered_set(TIterator first_, TIterator last_, const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Definition unordered_set.h:1952
~unordered_set()
Destructor.
Definition unordered_set.h:1972
unordered_set(const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Default constructor.
Definition unordered_set.h:1912
unordered_set(const unordered_set &other)
Copy constructor.
Definition unordered_set.h:1920
unordered_set & operator=(const unordered_set &rhs)
Assignment operator.
Definition unordered_set.h:1980
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
T * allocate()
Definition ipool.h:334
Definition ipool.h:110
Definition pool.h:54
size_t count(key_parameter_t key) const
Definition unordered_set.h:1242
const_local_iterator begin(size_t i) const
Definition unordered_set.h:512
key_equal key_eq() const
Definition unordered_set.h:1567
iterator erase(const_iterator first_, const_iterator last_)
Definition unordered_set.h:1178
local_iterator end(size_t i)
Definition unordered_set.h:557
size_type bucket_count() const
Definition unordered_set.h:639
size_type max_size() const
Gets the maximum possible size of the unordered_set.
Definition unordered_set.h:1507
size_type size() const
Gets the size of the unordered_set.
Definition unordered_set.h:1499
iunordered_set(pool_t &node_pool_, bucket_t *pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
Constructor.
Definition unordered_set.h:1631
iunordered_set & operator=(const iunordered_set &rhs)
Assignment operator.
Definition unordered_set.h:1575
local_iterator begin(size_t i)
Definition unordered_set.h:503
void insert(TIterator first_, TIterator last_)
Definition unordered_set.h:974
float load_factor() const
Definition unordered_set.h:1549
const_iterator begin() const
Definition unordered_set.h:485
bool contains(key_parameter_t key) const
Check if the unordered_set contains the key.
Definition unordered_set.h:1610
const_local_iterator cbegin(size_t i) const
Definition unordered_set.h:521
bool full() const
Checks to see if the unordered_set is full.
Definition unordered_set.h:1531
size_type bucket_size(key_parameter_t key) const
Definition unordered_set.h:605
~iunordered_set()
Destructor.
Definition unordered_set.h:1830
size_type get_bucket_index(key_parameter_t key) const
Definition unordered_set.h:584
const_iterator end() const
Definition unordered_set.h:539
void clear()
Clears the unordered_set.
Definition unordered_set.h:1232
size_t available() const
Definition unordered_set.h:1540
ETL_OR_STD::pair< iterator, bool > insert(const_reference key)
Definition unordered_set.h:676
iterator insert(const_iterator, const_reference key)
Definition unordered_set.h:946
void assign(TIterator first_, TIterator last_)
Definition unordered_set.h:653
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(key_parameter_t key) const
Definition unordered_set.h:1433
iterator find(key_parameter_t key)
Definition unordered_set.h:1265
ETL_OR_STD::pair< iterator, iterator > equal_range(key_parameter_t key)
Definition unordered_set.h:1411
iterator end()
Definition unordered_set.h:530
size_t erase(key_parameter_t key)
Definition unordered_set.h:1084
const_iterator find(key_parameter_t key) const
Definition unordered_set.h:1299
hasher hash_function() const
Definition unordered_set.h:1558
bool empty() const
Checks to see if the unordered_set is empty.
Definition unordered_set.h:1523
size_type max_bucket_count() const
Definition unordered_set.h:630
iterator begin()
Definition unordered_set.h:476
const_local_iterator cend(size_t i) const
Definition unordered_set.h:575
const_iterator cend() const
Definition unordered_set.h:548
const_local_iterator end(size_t i) const
Definition unordered_set.h:566
void initialise()
Initialise the unordered_set.
Definition unordered_set.h:1645
size_type capacity() const
Gets the maximum possible size of the unordered_set.
Definition unordered_set.h:1515
const_iterator cbegin() const
Definition unordered_set.h:494
iterator erase(const_iterator ielement)
Definition unordered_set.h:1150
Definition unordered_set.h:128
Definition unordered_set.h:69
Definition unordered_set.h:83
Definition unordered_set.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
iterator
Definition iterator.h:482
Definition unordered_set.h:151
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