source: mainline/uspace/lib/cpp/include/impl/unordered_set.hpp@ 04fa158

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

cpp: removed no unneeded type alias

  • Property mode set to 100644
File size: 30.1 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_UNORDERED_SET
30#define LIBCPP_UNORDERED_SET
31
32#include <initializer_list>
33#include <internal/hash_table.hpp>
34#include <functional>
35#include <memory>
36#include <utility>
37
38namespace std
39{
40 /**
41 * 23.5.6, class template unordered_set:
42 */
43
44 template<
45 class Key,
46 class Hash = hash<Key>,
47 class Pred = equal_to<Key>,
48 class Alloc = allocator<Key>
49 >
50 class unordered_set
51 {
52 public:
53 using key_type = Key;
54 using value_type = Key;
55 using hasher = Hash;
56 using key_equal = Pred;
57 using allocator_type = Alloc;
58 using pointer = typename allocator_traits<allocator_type>::pointer;
59 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
60 using reference = value_type&;
61 using const_reference = const value_type&;
62 using size_type = size_t;
63 using difference_type = ptrdiff_t;
64
65 /**
66 * Note: Both the iterator and const_iterator (and their local variants)
67 * types are constant iterators, the standard does not require them
68 * to be the same type, but why not? :)
69 */
70 using iterator = aux::hash_table_const_iterator<
71 value_type, const_reference, const_pointer, size_type
72 >;
73 using const_iterator = iterator;
74 using local_iterator = aux::hash_table_const_local_iterator<
75 value_type, const_reference, const_pointer
76 >;
77 using const_local_iterator = local_iterator;
78
79 /**
80 * Note: We need () to delegate the constructor,
81 * otherwise it could be deduced as the initializer
82 * list constructor when size_type is convertible
83 * to value_type.
84 */
85 unordered_set()
86 : unordered_set(default_bucket_count_)
87 { /* DUMMY BODY */ }
88
89 explicit unordered_set(size_type bucket_count,
90 const hasher& hf = hasher{},
91 const key_equal& eql = key_equal{},
92 const allocator_type& alloc = allocator_type{})
93 : table_{bucket_count, hf, eql}, allocator_{alloc}
94 { /* DUMMY BODY */ }
95
96 template<class InputIterator>
97 unordered_set(InputIterator first, InputIterator last,
98 size_type bucket_count = default_bucket_count_,
99 const hasher& hf = hasher{},
100 const key_equal& eql = key_equal{},
101 const allocator_type& alloc = allocator_type{})
102 : unordered_set{bucket_count, hf, eql, alloc}
103 {
104 insert(first, last);
105 }
106
107 unordered_set(const unordered_set& other)
108 : unordered_set{other, other.allocator_}
109 { /* DUMMY BODY */ }
110
111 unordered_set(unordered_set&& other)
112 : table_{move(other.table_)}, allocator_{move(other.allocator_)}
113 { /* DUMMY BODY */ }
114
115 explicit unordered_set(const allocator_type& alloc)
116 : table_{default_bucket_count_}, allocator_{alloc}
117 { /* DUMMY BODY */ }
118
119 unordered_set(const unordered_set& other, const allocator_type& alloc)
120 : table_{other.table_}, allocator_{alloc}
121 { /* DUMMY BODY */ }
122
123 unordered_set(unordered_set&& other, const allocator_type& alloc)
124 : table_{move(other.table_)}, allocator_{alloc}
125 { /* DUMMY BODY */ }
126
127 unordered_set(initializer_list<value_type> init,
128 size_type bucket_count = default_bucket_count_,
129 const hasher& hf = hasher{},
130 const key_equal& eql = key_equal{},
131 const allocator_type& alloc = allocator_type{})
132 : unordered_set{bucket_count, hf, eql, alloc}
133 {
134 insert(init.begin(), init.end());
135 }
136
137 unordered_set(size_type bucket_count, const allocator_type& alloc)
138 : unordered_set{bucket_count, hasher{}, key_equal{}, alloc}
139 { /* DUMMY BODY */ }
140
141 unordered_set(size_type bucket_count, const hasher& hf, const allocator_type& alloc)
142 : unordered_set{bucket_count, hf, key_equal{}, alloc}
143 { /* DUMMY BODY */ }
144
145 template<class InputIterator>
146 unordered_set(InputIterator first, InputIterator last,
147 size_type bucket_count, const allocator_type& alloc)
148 : unordered_set{first, last, bucket_count, hasher{}, key_equal{}, alloc}
149 { /* DUMMY BODY */ }
150
151 template<class InputIterator>
152 unordered_set(InputIterator first, InputIterator last,
153 size_type bucket_count, const hasher& hf, const allocator_type& alloc)
154 : unordered_set{first, last, bucket_count, hf, key_equal{}, alloc}
155 { /* DUMMY BODY */ }
156
157 unordered_set(initializer_list<value_type> init, size_type bucket_count,
158 const allocator_type& alloc)
159 : unordered_set{init, bucket_count, hasher{}, key_equal{}, alloc}
160 { /* DUMMY BODY */ }
161
162 unordered_set(initializer_list<value_type> init, size_type bucket_count,
163 const hasher& hf, const allocator_type& alloc)
164 : unordered_set{init, bucket_count, hf, key_equal{}, alloc}
165 { /* DUMMY BODY */ }
166
167 ~unordered_set()
168 { /* DUMMY BODY */ }
169
170 unordered_set& operator=(const unordered_set& other)
171 {
172 table_ = other.table_;
173 allocator_ = other.allocator_;
174
175 return *this;
176 }
177
178 unordered_set& operator=(unordered_set&& other)
179 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
180 is_nothrow_move_assignable<hasher>::value &&
181 is_nothrow_move_assignable<key_equal>::value)
182 {
183 table_ = move(other.table_);
184 allocator_ = move(other.allocator_);
185
186 return *this;
187 }
188
189 unordered_set& operator=(initializer_list<value_type>& init)
190 {
191 table_.clear();
192 table_.reserve(init.size());
193
194 insert(init.begin(), init.end());
195
196 return *this;
197 }
198
199 allocator_type get_allocator() const noexcept
200 {
201 return allocator_;
202 }
203
204 bool empty() const noexcept
205 {
206 return table_.empty();
207 }
208
209 size_type size() const noexcept
210 {
211 return table_.size();
212 }
213
214 size_type max_size() const noexcept
215 {
216 return table_.max_size(allocator_);
217 }
218
219 iterator begin() noexcept
220 {
221 return table_.begin();
222 }
223
224 const_iterator begin() const noexcept
225 {
226 return table_.begin();
227 }
228
229 iterator end() noexcept
230 {
231 return table_.end();
232 }
233
234 const_iterator end() const noexcept
235 {
236 return table_.end();
237 }
238
239 const_iterator cbegin() const noexcept
240 {
241 return table_.cbegin();
242 }
243
244 const_iterator cend() const noexcept
245 {
246 return table_.cend();
247 }
248
249 template<class... Args>
250 pair<iterator, bool> emplace(Args&&... args)
251 {
252 return table_.emplace(forward<Args>(args)...);
253 }
254
255 template<class... Args>
256 iterator emplace_hint(const_iterator, Args&&... args)
257 {
258 return emplace(forward<Args>(args)...).first;
259 }
260
261 pair<iterator, bool> insert(const value_type& val)
262 {
263 return table_.insert(val);
264 }
265
266 pair<iterator, bool> insert(value_type&& val)
267 {
268 return table_.insert(forward<value_type>(val));
269 }
270
271 iterator insert(const_iterator, const value_type& val)
272 {
273 return insert(val).first;
274 }
275
276 iterator insert(const_iterator, value_type&& val)
277 {
278 return insert(forward<value_type>(val)).first;
279 }
280
281 template<class InputIterator>
282 void insert(InputIterator first, InputIterator last)
283 {
284 while (first != last)
285 insert(*first++);
286 }
287
288 void insert(initializer_list<value_type> init)
289 {
290 insert(init.begin(), init.end());
291 }
292
293 iterator erase(const_iterator position)
294 {
295 return table_.erase(position);
296 }
297
298 size_type erase(const key_type& key)
299 {
300 return table_.erase(key);
301 }
302
303 iterator erase(const_iterator first, const_iterator last)
304 {
305 while (first != last)
306 first = erase(first);
307
308 return iterator{
309 table_.table(), first.idx(),
310 table_.bucket_count(), table_.head(first.idx())
311 }; // TODO: why do we pass table_.head(first.idx()) here?
312 }
313
314 void clear() noexcept
315 {
316 table_.clear();
317 }
318
319 void swap(unordered_set& other)
320 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
321 noexcept(std::swap(declval<hasher>(), declval<hasher>())) &&
322 noexcept(std::swap(declval<key_equal>(), declval<key_equal>())))
323 {
324 table_.swap(other.table_);
325 std::swap(allocator_, other.allocator_);
326 }
327
328 hasher hash_function() const
329 {
330 return table_.hash_function();
331 }
332
333 key_equal key_eq() const
334 {
335 return table_.key_eq();
336 }
337
338 iterator find(const key_type& key)
339 {
340 return table_.find(key);
341 }
342
343 const_iterator find(const key_type& key) const
344 {
345 return table_.find(key);
346 }
347
348 size_type count(const key_type& key) const
349 {
350 return table_.count(key);
351 }
352
353 pair<iterator, iterator> equal_range(const key_type& key)
354 {
355 return table_.equal_range(key);
356 }
357
358 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
359 {
360 return table_.equal_range(key);
361 }
362
363 size_type bucket_count() const noexcept
364 {
365 return table_.bucket_count();
366 }
367
368 size_type max_bucket_count() const noexcept
369 {
370 return table_.max_bucket_count();
371 }
372
373 size_type bucket_size(size_type idx) const
374 {
375 return table_.bucket_size(idx);
376 }
377
378 size_type bucket(const key_type& key) const
379 {
380 return table_.bucket(key);
381 }
382
383 local_iterator begin(size_type idx)
384 {
385 return table_.begin(idx);
386 }
387
388 const_local_iterator begin(size_type idx) const
389 {
390 return table_.begin(idx);
391 }
392
393 local_iterator end(size_type idx)
394 {
395 return table_.end(idx);
396 }
397
398 const_local_iterator end(size_type idx) const
399 {
400 return table_.end(idx);
401 }
402
403 const_local_iterator cbegin(size_type idx) const
404 {
405 return table_.cbegin(idx);
406 }
407
408 const_local_iterator cend(size_type idx) const
409 {
410 return table_.cend(idx);
411 }
412
413 float load_factor() const noexcept
414 {
415 return table_.load_factor();
416 }
417
418 float max_load_factor() const noexcept
419 {
420 return table_.max_load_factor();
421 }
422
423 void max_load_factor(float factor)
424 {
425 table_.max_load_factor(factor);
426 }
427
428 void rehash(size_type bucket_count)
429 {
430 table_.rehash(bucket_count);
431 }
432
433 void reserve(size_type count)
434 {
435 table_.reserve(count);
436 }
437
438 private:
439 using table_type = aux::hash_table<
440 key_type, key_type, aux::key_no_value_key_extractor<key_type>,
441 hasher, key_equal, allocator_type, size_type,
442 iterator, const_iterator, local_iterator, const_local_iterator,
443 aux::hash_single_policy
444 >;
445
446 table_type table_;
447 allocator_type allocator_;
448
449 static constexpr size_type default_bucket_count_{16};
450
451 template<class K, class H, class P, class A>
452 friend bool operator==(unordered_set<K, H, P, A>&,
453 unordered_set<K, H, P, A>&);
454 };
455
456 /**
457 * 23.5.7, class template unordered_multiset:
458 */
459
460 template<
461 class Key,
462 class Hash = hash<Key>,
463 class Pred = equal_to<Key>,
464 class Alloc = allocator<Key>
465 >
466 class unordered_multiset
467 {
468 public:
469 using key_type = Key;
470 using value_type = Key;
471 using hasher = Hash;
472 using key_equal = Pred;
473 using allocator_type = Alloc;
474 using pointer = typename allocator_traits<allocator_type>::pointer;
475 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
476 using reference = value_type&;
477 using const_reference = const value_type&;
478 using size_type = size_t;
479 using difference_type = ptrdiff_t;
480
481 /**
482 * Note: Both the iterator and const_iterator (and their local variants)
483 * types are constant iterators, the standard does not require them
484 * to be the same type, but why not? :)
485 */
486 using iterator = aux::hash_table_const_iterator<
487 value_type, const_reference, const_pointer, size_type
488 >;
489 using const_iterator = iterator;
490 using local_iterator = aux::hash_table_const_local_iterator<
491 value_type, const_reference, const_pointer
492 >;
493 using const_local_iterator = local_iterator;
494
495 /**
496 * Note: We need () to delegate the constructor,
497 * otherwise it could be deduced as the initializer
498 * list constructor when size_type is convertible
499 * to value_type.
500 */
501 unordered_multiset()
502 : unordered_multiset(default_bucket_count_)
503 { /* DUMMY BODY */ }
504
505 explicit unordered_multiset(size_type bucket_count,
506 const hasher& hf = hasher{},
507 const key_equal& eql = key_equal{},
508 const allocator_type& alloc = allocator_type{})
509 : table_{bucket_count, hf, eql}, allocator_{alloc}
510 { /* DUMMY BODY */ }
511
512 template<class InputIterator>
513 unordered_multiset(InputIterator first, InputIterator last,
514 size_type bucket_count = default_bucket_count_,
515 const hasher& hf = hasher{},
516 const key_equal& eql = key_equal{},
517 const allocator_type& alloc = allocator_type{})
518 : unordered_multiset{bucket_count, hf, eql, alloc}
519 {
520 insert(first, last);
521 }
522
523 unordered_multiset(const unordered_multiset& other)
524 : unordered_multiset{other, other.allocator_}
525 { /* DUMMY BODY */ }
526
527 unordered_multiset(unordered_multiset&& other)
528 : table_{move(other.table_)}, allocator_{move(other.allocator_)}
529 { /* DUMMY BODY */ }
530
531 explicit unordered_multiset(const allocator_type& alloc)
532 : table_{default_bucket_count_}, allocator_{alloc}
533 { /* DUMMY BODY */ }
534
535 unordered_multiset(const unordered_multiset& other, const allocator_type& alloc)
536 : table_{other.table_}, allocator_{alloc}
537 { /* DUMMY BODY */ }
538
539 unordered_multiset(unordered_multiset&& other, const allocator_type& alloc)
540 : table_{move(other.table_)}, allocator_{alloc}
541 { /* DUMMY BODY */ }
542
543 unordered_multiset(initializer_list<value_type> init,
544 size_type bucket_count = default_bucket_count_,
545 const hasher& hf = hasher{},
546 const key_equal& eql = key_equal{},
547 const allocator_type& alloc = allocator_type{})
548 : unordered_multiset{bucket_count, hf, eql, alloc}
549 {
550 insert(init.begin(), init.end());
551 }
552
553 unordered_multiset(size_type bucket_count, const allocator_type& alloc)
554 : unordered_multiset{bucket_count, hasher{}, key_equal{}, alloc}
555 { /* DUMMY BODY */ }
556
557 unordered_multiset(size_type bucket_count, const hasher& hf, const allocator_type& alloc)
558 : unordered_multiset{bucket_count, hf, key_equal{}, alloc}
559 { /* DUMMY BODY */ }
560
561 template<class InputIterator>
562 unordered_multiset(InputIterator first, InputIterator last,
563 size_type bucket_count, const allocator_type& alloc)
564 : unordered_multiset{first, last, bucket_count, hasher{}, key_equal{}, alloc}
565 { /* DUMMY BODY */ }
566
567 template<class InputIterator>
568 unordered_multiset(InputIterator first, InputIterator last,
569 size_type bucket_count, const hasher& hf, const allocator_type& alloc)
570 : unordered_multiset{first, last, bucket_count, hf, key_equal{}, alloc}
571 { /* DUMMY BODY */ }
572
573 unordered_multiset(initializer_list<value_type> init, size_type bucket_count,
574 const allocator_type& alloc)
575 : unordered_multiset{init, bucket_count, hasher{}, key_equal{}, alloc}
576 { /* DUMMY BODY */ }
577
578 unordered_multiset(initializer_list<value_type> init, size_type bucket_count,
579 const hasher& hf, const allocator_type& alloc)
580 : unordered_multiset{init, bucket_count, hf, key_equal{}, alloc}
581 { /* DUMMY BODY */ }
582
583 ~unordered_multiset()
584 { /* DUMMY BODY */ }
585
586 unordered_multiset& operator=(const unordered_multiset& other)
587 {
588 table_ = other.table_;
589 allocator_ = other.allocator_;
590
591 return *this;
592 }
593
594 unordered_multiset& operator=(unordered_multiset&& other)
595 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
596 is_nothrow_move_assignable<hasher>::value &&
597 is_nothrow_move_assignable<key_equal>::value)
598 {
599 table_ = move(other.table_);
600 allocator_ = move(other.allocator_);
601
602 return *this;
603 }
604
605 unordered_multiset& operator=(initializer_list<value_type>& init)
606 {
607 table_.clear();
608 table_.reserve(init.size());
609
610 insert(init.begin(), init.end());
611
612 return *this;
613 }
614
615 allocator_type get_allocator() const noexcept
616 {
617 return allocator_;
618 }
619
620 bool empty() const noexcept
621 {
622 return table_.empty();
623 }
624
625 size_type size() const noexcept
626 {
627 return table_.size();
628 }
629
630 size_type max_size() const noexcept
631 {
632 return table_.max_size(allocator_);
633 }
634
635 iterator begin() noexcept
636 {
637 return table_.begin();
638 }
639
640 const_iterator begin() const noexcept
641 {
642 return table_.begin();
643 }
644
645 iterator end() noexcept
646 {
647 return table_.end();
648 }
649
650 const_iterator end() const noexcept
651 {
652 return table_.end();
653 }
654
655 const_iterator cbegin() const noexcept
656 {
657 return table_.cbegin();
658 }
659
660 const_iterator cend() const noexcept
661 {
662 return table_.cend();
663 }
664
665 template<class... Args>
666 pair<iterator, bool> emplace(Args&&... args)
667 {
668 return table_.emplace(forward<Args>(args)...);
669 }
670
671 template<class... Args>
672 iterator emplace_hint(const_iterator, Args&&... args)
673 {
674 return emplace(forward<Args>(args)...).first;
675 }
676
677 pair<iterator, bool> insert(const value_type& val)
678 {
679 return table_.insert(val);
680 }
681
682 pair<iterator, bool> insert(value_type&& val)
683 {
684 return table_.insert(forward<value_type>(val));
685 }
686
687 iterator insert(const_iterator, const value_type& val)
688 {
689 return insert(val).first;
690 }
691
692 iterator insert(const_iterator, value_type&& val)
693 {
694 return insert(forward<value_type>(val)).first;
695 }
696
697 template<class InputIterator>
698 void insert(InputIterator first, InputIterator last)
699 {
700 while (first != last)
701 insert(*first++);
702 }
703
704 void insert(initializer_list<value_type> init)
705 {
706 insert(init.begin(), init.end());
707 }
708
709 iterator erase(const_iterator position)
710 {
711 return table_.erase(position);
712 }
713
714 size_type erase(const key_type& key)
715 {
716 return table_.erase(key);
717 }
718
719 iterator erase(const_iterator first, const_iterator last)
720 {
721 while (first != last)
722 first = erase(first);
723
724 return iterator{
725 table_.table(), first.idx(),
726 table_.bucket_count(), table_.head(first.idx())
727 };
728 }
729
730 void clear() noexcept
731 {
732 table_.clear();
733 }
734
735 void swap(unordered_multiset& other)
736 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
737 noexcept(std::swap(declval<hasher>(), declval<hasher>())) &&
738 noexcept(std::swap(declval<key_equal>(), declval<key_equal>())))
739 {
740 table_.swap(other.table_);
741 std::swap(allocator_, other.allocator_);
742 }
743
744 hasher hash_function() const
745 {
746 return table_.hash_function();
747 }
748
749 key_equal key_eq() const
750 {
751 return table_.key_eq();
752 }
753
754 iterator find(const key_type& key)
755 {
756 return table_.find(key);
757 }
758
759 const_iterator find(const key_type& key) const
760 {
761 return table_.find(key);
762 }
763
764 size_type count(const key_type& key) const
765 {
766 return table_.count(key);
767 }
768
769 pair<iterator, iterator> equal_range(const key_type& key)
770 {
771 return table_.equal_range(key);
772 }
773
774 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
775 {
776 return table_.equal_range(key);
777 }
778
779 size_type bucket_count() const noexcept
780 {
781 return table_.bucket_count();
782 }
783
784 size_type max_bucket_count() const noexcept
785 {
786 return table_.max_bucket_count();
787 }
788
789 size_type bucket_size(size_type idx) const
790 {
791 return table_.bucket_size(idx);
792 }
793
794 size_type bucket(const key_type& key) const
795 {
796 return table_.bucket(key);
797 }
798
799 local_iterator begin(size_type idx)
800 {
801 return table_.begin(idx);
802 }
803
804 const_local_iterator begin(size_type idx) const
805 {
806 return table_.begin(idx);
807 }
808
809 local_iterator end(size_type idx)
810 {
811 return table_.end(idx);
812 }
813
814 const_local_iterator end(size_type idx) const
815 {
816 return table_.end(idx);
817 }
818
819 const_local_iterator cbegin(size_type idx) const
820 {
821 return table_.cbegin(idx);
822 }
823
824 const_local_iterator cend(size_type idx) const
825 {
826 return table_.cend(idx);
827 }
828
829 float load_factor() const noexcept
830 {
831 return table_.load_factor();
832 }
833
834 float max_load_factor() const noexcept
835 {
836 return table_.max_load_factor();
837 }
838
839 void max_load_factor(float factor)
840 {
841 table_.max_load_factor(factor);
842 }
843
844 void rehash(size_type bucket_count)
845 {
846 table_.rehash(bucket_count);
847 }
848
849 void reserve(size_type count)
850 {
851 table_.reserve(count);
852 }
853
854 private:
855 using table_type = aux::hash_table<
856 key_type, key_type, aux::key_no_value_key_extractor<key_type>,
857 hasher, key_equal, allocator_type, size_type,
858 iterator, const_iterator, local_iterator, const_local_iterator,
859 aux::hash_multi_policy
860 >;
861
862 table_type table_;
863 allocator_type allocator_;
864
865 static constexpr size_type default_bucket_count_{16};
866
867 template<class K, class H, class P, class A>
868 friend bool operator==(unordered_multiset<K, H, P, A>&,
869 unordered_multiset<K, H, P, A>&);
870 };
871
872 template<class Key, class Hash, class Pred, class Alloc>
873 void swap(unordered_set<Key, Hash, Pred, Alloc>& lhs,
874 unordered_set<Key, Hash, Pred, Alloc>& rhs)
875 noexcept(noexcept(lhs.swap(rhs)))
876 {
877 lhs.swap(rhs);
878 }
879
880 template<class Key, class Hash, class Pred, class Alloc>
881 void swap(unordered_multiset<Key, Hash, Pred, Alloc>& lhs,
882 unordered_multiset<Key, Hash, Pred, Alloc>& rhs)
883 noexcept(noexcept(lhs.swap(rhs)))
884 {
885 lhs.swap(rhs);
886 }
887
888 template<class Key, class Hash, class Pred, class Alloc>
889 bool operator==(unordered_set<Key, Hash, Pred, Alloc>& lhs,
890 unordered_set<Key, Hash, Pred, Alloc>& rhs)
891 {
892 return lhs.table_.is_eq_to(rhs.table_);
893 }
894
895 template<class Key, class Hash, class Pred, class Alloc>
896 bool operator!=(unordered_set<Key, Hash, Pred, Alloc>& lhs,
897 unordered_set<Key, Hash, Pred, Alloc>& rhs)
898 {
899 return !(lhs == rhs);
900 }
901
902 template<class Key, class Hash, class Pred, class Alloc>
903 bool operator==(unordered_multiset<Key, Hash, Pred, Alloc>& lhs,
904 unordered_multiset<Key, Hash, Pred, Alloc>& rhs)
905 {
906 return lhs.table_.is_eq_to(rhs.table_);
907 }
908
909 template<class Key, class Value, class Hash, class Pred, class Alloc>
910 bool operator!=(unordered_multiset<Key, Hash, Pred, Alloc>& lhs,
911 unordered_multiset<Key, Hash, Pred, Alloc>& rhs)
912 {
913 return !(lhs == rhs);
914 }
915}
916
917#endif
Note: See TracBrowser for help on using the repository browser.