source: mainline/uspace/lib/cpp/include/impl/set.hpp@ 55d6223

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

cpp: added missing include guards, fixed formatting

  • Property mode set to 100644
File size: 29.1 KB
RevLine 
[89bc6460]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
[55d6223]29#ifndef LIBCPP_SET
30#define LIBCPP_SET
31
[89bc6460]32#include <functional>
33#include <internal/rbtree.hpp>
34#include <iterator>
35#include <memory>
36#include <utility>
37
38namespace std
39{
40 /**
41 * 23.4.6, class template set:
42 */
43
44 template<
45 class Key,
46 class Compare = less<Key>,
47 class Alloc = allocator<Key>
48 >
49 class set
50 {
51 public:
52 using key_type = Key;
53 using value_type = Key;
54 using key_compare = Compare;
55 using value_compare = Compare;
56 using allocator_type = Alloc;
57 using pointer = typename allocator_traits<allocator_type>::pointer;
58 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
59 using reference = value_type&;
60 using const_reference = const value_type&;
61 using size_type = size_t;
62 using difference_type = ptrdiff_t;
63
64 /**
65 * Note: Both the iterator and const_iterator (and their local variants)
66 * types are constant iterators, the standard does not require them
67 * to be the same type, but why not? :)
68 */
69 using iterator = aux::rbtree_const_iterator<
70 value_type, const_reference, const_pointer, size_type
71 >;
72 using const_iterator = iterator;
73
74 using reverse_iterator = std::reverse_iterator<iterator>;
75 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
76
77 set()
78 : set{key_compare{}}
79 { /* DUMMY BODY */ }
80
81 explicit set(const key_compare& comp,
82 const allocator_type& alloc = allocator_type{})
83 : tree_{comp}, allocator_{alloc}
84 { /* DUMMY BODY */ }
85
86 template<class InputIterator>
87 set(InputIterator first, InputIterator last,
88 const key_compare& comp = key_compare{},
89 const allocator_type& alloc = allocator_type{})
90 : set{comp, alloc}
91 {
92 insert(first, last);
93 }
94
95 set(const set& other)
96 : set{other, other.allocator_}
97 { /* DUMMY BODY */ }
98
99 set(set&& other)
100 : tree_{move(other.tree_)}, allocator_{move(other.allocator_)}
101 { /* DUMMY BODY */ }
102
103 explicit set(const allocator_type& alloc)
104 : tree_{}, allocator_{alloc}
105 { /* DUMMY BODY */ }
106
107 set(const set& other, const allocator_type& alloc)
108 : tree_{other.tree_}, allocator_{alloc}
109 { /* DUMMY BODY */ }
110
111 set(set&& other, const allocator_type& alloc)
112 : tree_{move(other.tree_)}, allocator_{alloc}
113 { /* DUMMY BODY */ }
114
115 set(initializer_list<value_type> init,
116 const key_compare& comp = key_compare{},
117 const allocator_type& alloc = allocator_type{})
118 : set{comp, alloc}
119 {
120 insert(init.begin(), init.end());
121 }
122
123 template<class InputIterator>
124 set(InputIterator first, InputIterator last,
125 const allocator_type& alloc)
126 : set{first, last, key_compare{}, alloc}
127 { /* DUMMY BODY */ }
128
129 set(initializer_list<value_type> init,
130 const allocator_type& alloc)
131 : set{init, key_compare{}, alloc}
132 { /* DUMMY BODY */ }
133
134 ~set()
135 { /* DUMMY BODY */ }
136
137 set& operator=(const set& other)
138 {
139 tree_ = other.tree_;
140 allocator_ = other.allocator_;
141
142 return *this;
143 }
144
145 set& operator=(set&& other)
146 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
147 is_nothrow_move_assignable<key_compare>::value)
148 {
149 tree_ = move(other.tree_);
150 allocator_ = move(other.allocator_);
151
152 return *this;
153 }
154
155 set& operator=(initializer_list<value_type>& init)
156 {
157 tree_.clear();
158
159 insert(init.begin(), init.end());
160
161 return *this;
162 }
163
164 allocator_type get_allocator() const noexcept
165 {
166 return allocator_;
167 }
168
169 iterator begin() noexcept
170 {
171 return tree_.begin();
172 }
173
174 const_iterator begin() const noexcept
175 {
176 return tree_.begin();
177 }
178
179 iterator end() noexcept
180 {
181 return tree_.end();
182 }
183
184 const_iterator end() const noexcept
185 {
186 return tree_.end();
187 }
188
189 reverse_iterator rbegin() noexcept
190 {
191 return tree_.rbegin();
192 }
193
194 const_reverse_iterator rbegin() const noexcept
195 {
196 return tree_.rbegin();
197 }
198
199 reverse_iterator rend() noexcept
200 {
201 return tree_.rend();
202 }
203
204 const_reverse_iterator rend() const noexcept
205 {
206 return tree_.rend();
207 }
208
209 const_iterator cbegin() const noexcept
210 {
211 return tree_.cbegin();
212 }
213
214 const_iterator cend() const noexcept
215 {
216 return tree_.cend();
217 }
218
219 const_reverse_iterator crbegin() const noexcept
220 {
221 return tree_.crbegin();
222 }
223
224 const_reverse_iterator crend() const noexcept
225 {
226 return tree_.crend();
227 }
228
229 bool empty() const noexcept
230 {
231 return tree_.empty();
232 }
233
234 size_type size() const noexcept
235 {
236 return tree_.size();
237 }
238
239 size_type max_size() const noexcept
240 {
241 return tree_.max_size(allocator_);
242 }
243
244 template<class... Args>
245 pair<iterator, bool> emplace(Args&&... args)
246 {
247 return tree_.emplace(forward<Args>(args)...);
248 }
249
250 template<class... Args>
251 iterator emplace_hint(const_iterator, Args&&... args)
252 {
253 return emplace(forward<Args>(args)...).first;
254 }
255
256 pair<iterator, bool> insert(const value_type& val)
257 {
258 return tree_.insert(val);
259 }
260
261 pair<iterator, bool> insert(value_type&& val)
262 {
263 return tree_.insert(forward<value_type>(val));
264 }
265
266 iterator insert(const_iterator, const value_type& val)
267 {
268 return insert(val).first;
269 }
270
271 iterator insert(const_iterator, value_type&& val)
272 {
273 return insert(forward<value_type>(val)).first;
274 }
275
276 template<class InputIterator>
277 void insert(InputIterator first, InputIterator last)
278 {
279 while (first != last)
280 insert(*first++);
281 }
282
283 void insert(initializer_list<value_type> init)
284 {
285 insert(init.begin(), init.end());
286 }
287
288 iterator erase(const_iterator position)
289 {
290 return tree_.erase(position);
291 }
292
293 size_type erase(const key_type& key)
294 {
295 return tree_.erase(key);
296 }
297
298 iterator erase(const_iterator first, const_iterator last)
299 {
300 while (first != last)
301 first = erase(first);
302
303 return iterator{
304 first.node(), first.end()
305 };
306 }
307
308 void swap(set& other)
309 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
310 noexcept(std::swap(declval<key_compare>(), declval<key_compare>())))
311 {
312 tree_.swap(other.tree_);
313 std::swap(allocator_, other.allocator_);
314 }
315
316 void clear() noexcept
317 {
318 tree_.clear();
319 }
320
321 key_compare key_comp() const
322 {
323 return tree_.key_comp();
324 }
325
326 value_compare value_comp() const
327 {
328 return tree_.value_comp();
329 }
330
331 iterator find(const key_type& key)
332 {
333 return tree_.find(key);
334 }
335
336 const_iterator find(const key_type& key) const
337 {
338 return tree_.find(key);
339 }
340
[55d6223]341 template<class K>
[89bc6460]342 iterator find(
343 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
344 )
345 {
346 return tree_.find(key);
347 }
348
[55d6223]349 template<class K>
[89bc6460]350 const_iterator find(
351 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
352 ) const
353 {
354 return tree_.find(key);
355 }
356
357 size_type count(const key_type& key) const
358 {
359 return tree_.count(key);
360 }
361
[55d6223]362 template<class K>
[89bc6460]363 size_type count(
364 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
365 ) const
366 {
367 return tree_.count(key);
368 }
369
370 iterator lower_bound(const key_type& key)
371 {
372 return tree_.lower_bound(key);
373 }
374
375 const_iterator lower_bound(const key_type& key) const
376 {
377 return tree_.lower_bound(key);
378 }
379
[55d6223]380 template<class K>
[89bc6460]381 iterator lower_bound(
382 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
383 )
384 {
385 return tree_.lower_bound(key);
386 }
387
[55d6223]388 template<class K>
[89bc6460]389 const_iterator lower_bound(
390 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
391 ) const
392 {
393 return tree_.lower_bound(key);
394 }
395
396 iterator upper_bound(const key_type& key)
397 {
398 return tree_.upper_bound(key);
399 }
400
401 const_iterator upper_bound(const key_type& key) const
402 {
403 return tree_.upper_bound(key);
404 }
405
[55d6223]406 template<class K>
[89bc6460]407 iterator upper_bound(
408 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
409 )
410 {
411 return tree_.upper_bound(key);
412 }
413
[55d6223]414 template<class K>
[89bc6460]415 const_iterator upper_bound(
416 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
417 ) const
418 {
419 return tree_.upper_bound(key);
420 }
421
422 pair<iterator, iterator> equal_range(const key_type& key)
423 {
424 return tree_.equal_range(key);
425 }
426
427 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
428 {
429 return tree_.equal_range(key);
430 }
431
[55d6223]432 template<class K>
[89bc6460]433 pair<iterator, iterator> equal_range(
434 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
435 )
436 {
437 return tree_.equal_range(key);
438 }
439
[55d6223]440 template<class K>
[89bc6460]441 pair<const_iterator, const_iterator> equal_range(
442 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
443 ) const
444 {
445 return tree_.equal_range(key);
446 }
447
448 private:
449 using tree_type = aux::rbtree<
450 key_type, key_type, aux::key_no_value_key_extractor<key_type>,
451 key_compare, allocator_type, size_type,
452 iterator, const_iterator,
453 aux::rbtree_single_policy
454 >;
455
456 tree_type tree_;
457 allocator_type allocator_;
458
459 template<class K, class C, class A>
460 friend bool operator==(const set<K, C, A>&,
461 const set<K, C, A>&);
462 };
463
464 template<class Key, class Compare, class Allocator>
465 bool operator==(const set<Key, Compare, Allocator>& lhs,
466 const set<Key, Compare, Allocator>& rhs)
467 {
468 return lhs.tree_.is_eq_to(rhs.tree_);
469 }
470
471 template<class Key, class Compare, class Allocator>
472 bool operator<(const set<Key, Compare, Allocator>& lhs,
473 const set<Key, Compare, Allocator>& rhs)
474 {
475 // TODO: need lexicographical_compare
476 return false;
477 }
478
479 template<class Key, class Compare, class Allocator>
480 bool operator!=(const set<Key, Compare, Allocator>& lhs,
481 const set<Key, Compare, Allocator>& rhs)
482 {
483 return !(lhs == rhs);
484 }
485
486 template<class Key, class Compare, class Allocator>
487 bool operator>(const set<Key, Compare, Allocator>& lhs,
488 const set<Key, Compare, Allocator>& rhs)
489 {
490 // TODO: need lexicographical_compare
491 return false;
492 }
493
494 template<class Key, class Compare, class Allocator>
495 bool operator>=(const set<Key, Compare, Allocator>& lhs,
496 const set<Key, Compare, Allocator>& rhs)
497 {
498 // TODO: need lexicographical_compare
499 return false;
500 }
501
502 template<class Key, class Compare, class Allocator>
503 bool operator<=(const set<Key, Compare, Allocator>& lhs,
504 const set<Key, Compare, Allocator>& rhs)
505 {
506 // TODO: need lexicographical_compare
507 return false;
508 }
[af0fbaac]509 /**
510 * 23.4.7, class template multiset:
511 */
512
513 template<
514 class Key,
515 class Compare = less<Key>,
516 class Alloc = allocator<Key>
517 >
518 class multiset
519 {
520 public:
521 using key_type = Key;
522 using value_type = Key;
523 using key_compare = Compare;
524 using value_compare = Compare;
525 using allocator_type = Alloc;
526 using pointer = typename allocator_traits<allocator_type>::pointer;
527 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
528 using reference = value_type&;
529 using const_reference = const value_type&;
530 using size_type = size_t;
531 using difference_type = ptrdiff_t;
532
533 /**
534 * Note: Both the iterator and const_iterator (and their local variants)
535 * types are constant iterators, the standard does not require them
536 * to be the same type, but why not? :)
537 */
538 using iterator = aux::rbtree_const_iterator<
539 value_type, const_reference, const_pointer, size_type
540 >;
541 using const_iterator = iterator;
542
543 using reverse_iterator = std::reverse_iterator<iterator>;
544 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
545
546 multiset()
547 : multiset{key_compare{}}
548 { /* DUMMY BODY */ }
549
550 explicit multiset(const key_compare& comp,
551 const allocator_type& alloc = allocator_type{})
552 : tree_{comp}, allocator_{alloc}
553 { /* DUMMY BODY */ }
554
555 template<class InputIterator>
556 multiset(InputIterator first, InputIterator last,
557 const key_compare& comp = key_compare{},
558 const allocator_type& alloc = allocator_type{})
559 : multiset{comp, alloc}
560 {
561 insert(first, last);
562 }
563
564 multiset(const multiset& other)
565 : multiset{other, other.allocator_}
566 { /* DUMMY BODY */ }
567
568 multiset(multiset&& other)
569 : tree_{move(other.tree_)}, allocator_{move(other.allocator_)}
570 { /* DUMMY BODY */ }
571
572 explicit multiset(const allocator_type& alloc)
573 : tree_{}, allocator_{alloc}
574 { /* DUMMY BODY */ }
575
576 multiset(const multiset& other, const allocator_type& alloc)
577 : tree_{other.tree_}, allocator_{alloc}
578 { /* DUMMY BODY */ }
579
580 multiset(multiset&& other, const allocator_type& alloc)
581 : tree_{move(other.tree_)}, allocator_{alloc}
582 { /* DUMMY BODY */ }
583
584 multiset(initializer_list<value_type> init,
585 const key_compare& comp = key_compare{},
586 const allocator_type& alloc = allocator_type{})
587 : multiset{comp, alloc}
588 {
589 insert(init.begin(), init.end());
590 }
591
592 template<class InputIterator>
593 multiset(InputIterator first, InputIterator last,
594 const allocator_type& alloc)
595 : multiset{first, last, key_compare{}, alloc}
596 { /* DUMMY BODY */ }
597
598 multiset(initializer_list<value_type> init,
599 const allocator_type& alloc)
600 : multiset{init, key_compare{}, alloc}
601 { /* DUMMY BODY */ }
602
603 ~multiset()
604 { /* DUMMY BODY */ }
605
606 multiset& operator=(const multiset& other)
607 {
608 tree_ = other.tree_;
609 allocator_ = other.allocator_;
610
611 return *this;
612 }
613
614 multiset& operator=(multiset&& other)
615 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
616 is_nothrow_move_assignable<key_compare>::value)
617 {
618 tree_ = move(other.tree_);
619 allocator_ = move(other.allocator_);
620
621 return *this;
622 }
623
624 multiset& operator=(initializer_list<value_type>& init)
625 {
626 tree_.clear();
627
628 insert(init.begin(), init.end());
629
630 return *this;
631 }
632
633 allocator_type get_allocator() const noexcept
634 {
635 return allocator_;
636 }
637
638 iterator begin() noexcept
639 {
640 return tree_.begin();
641 }
642
643 const_iterator begin() const noexcept
644 {
645 return tree_.begin();
646 }
647
648 iterator end() noexcept
649 {
650 return tree_.end();
651 }
652
653 const_iterator end() const noexcept
654 {
655 return tree_.end();
656 }
657
658 reverse_iterator rbegin() noexcept
659 {
660 return tree_.rbegin();
661 }
662
663 const_reverse_iterator rbegin() const noexcept
664 {
665 return tree_.rbegin();
666 }
667
668 reverse_iterator rend() noexcept
669 {
670 return tree_.rend();
671 }
672
673 const_reverse_iterator rend() const noexcept
674 {
675 return tree_.rend();
676 }
677
678 const_iterator cbegin() const noexcept
679 {
680 return tree_.cbegin();
681 }
682
683 const_iterator cend() const noexcept
684 {
685 return tree_.cend();
686 }
687
688 const_reverse_iterator crbegin() const noexcept
689 {
690 return tree_.crbegin();
691 }
692
693 const_reverse_iterator crend() const noexcept
694 {
695 return tree_.crend();
696 }
697
698 bool empty() const noexcept
699 {
700 return tree_.empty();
701 }
702
703 size_type size() const noexcept
704 {
705 return tree_.size();
706 }
707
708 size_type max_size() const noexcept
709 {
710 return tree_.max_size(allocator_);
711 }
712
713 template<class... Args>
714 iterator emplace(Args&&... args)
715 {
716 return tree_.emplace(forward<Args>(args)...);
717 }
718
719 template<class... Args>
720 iterator emplace_hint(const_iterator, Args&&... args)
721 {
722 return emplace(forward<Args>(args)...);
723 }
724
725 iterator insert(const value_type& val)
726 {
727 return tree_.insert(val);
728 }
729
730 iterator insert(value_type&& val)
731 {
732 return tree_.insert(forward<value_type>(val));
733 }
734
735 iterator insert(const_iterator, const value_type& val)
736 {
737 return insert(val);
738 }
739
740 iterator insert(const_iterator, value_type&& val)
741 {
742 return insert(forward<value_type>(val));
743 }
744
745 template<class InputIterator>
746 void insert(InputIterator first, InputIterator last)
747 {
748 while (first != last)
749 insert(*first++);
750 }
751
752 void insert(initializer_list<value_type> init)
753 {
754 insert(init.begin(), init.end());
755 }
756
757 iterator erase(const_iterator position)
758 {
759 return tree_.erase(position);
760 }
761
762 size_type erase(const key_type& key)
763 {
764 return tree_.erase(key);
765 }
766
767 iterator erase(const_iterator first, const_iterator last)
768 {
769 while (first != last)
770 first = erase(first);
771
772 return iterator{
773 first.node(), first.end()
774 };
775 }
776
777 void swap(multiset& other)
778 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
779 noexcept(std::swap(declval<key_compare>(), declval<key_compare>())))
780 {
781 tree_.swap(other.tree_);
782 std::swap(allocator_, other.allocator_);
783 }
784
785 void clear() noexcept
786 {
787 tree_.clear();
788 }
789
790 key_compare key_comp() const
791 {
792 return tree_.key_comp();
793 }
794
795 value_compare value_comp() const
796 {
797 return tree_.value_comp();
798 }
799
800 iterator find(const key_type& key)
801 {
802 return tree_.find(key);
803 }
804
805 const_iterator find(const key_type& key) const
806 {
807 return tree_.find(key);
808 }
809
810 template<class K>
811 iterator find(
812 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
813 )
814 {
815 return tree_.find(key);
816 }
817
818 template<class K>
819 const_iterator find(
820 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
821 ) const
822 {
823 return tree_.find(key);
824 }
825
826 size_type count(const key_type& key) const
827 {
828 return tree_.count(key);
829 }
830
831 template<class K>
832 size_type count(
833 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
834 ) const
835 {
836 return tree_.count(key);
837 }
838
839 iterator lower_bound(const key_type& key)
840 {
841 return tree_.lower_bound(key);
842 }
843
844 const_iterator lower_bound(const key_type& key) const
845 {
846 return tree_.lower_bound(key);
847 }
848
849 template<class K>
850 iterator lower_bound(
851 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
852 )
853 {
854 return tree_.lower_bound(key);
855 }
856
857 template<class K>
858 const_iterator lower_bound(
859 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
860 ) const
861 {
862 return tree_.lower_bound(key);
863 }
864
865 iterator upper_bound(const key_type& key)
866 {
867 return tree_.upper_bound(key);
868 }
869
870 const_iterator upper_bound(const key_type& key) const
871 {
872 return tree_.upper_bound(key);
873 }
874
875 template<class K>
876 iterator upper_bound(
877 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
878 )
879 {
880 return tree_.upper_bound(key);
881 }
882
883 template<class K>
884 const_iterator upper_bound(
885 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
886 ) const
887 {
888 return tree_.upper_bound(key);
889 }
890
891 pair<iterator, iterator> equal_range(const key_type& key)
892 {
893 return tree_.equal_range(key);
894 }
895
896 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
897 {
898 return tree_.equal_range(key);
899 }
900
901 template<class K>
902 pair<iterator, iterator> equal_range(
903 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
904 )
905 {
906 return tree_.equal_range(key);
907 }
908
909 template<class K>
910 pair<const_iterator, const_iterator> equal_range(
911 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
912 ) const
913 {
914 return tree_.equal_range(key);
915 }
916
917 private:
918 using tree_type = aux::rbtree<
919 key_type, key_type, aux::key_no_value_key_extractor<key_type>,
920 key_compare, allocator_type, size_type,
921 iterator, const_iterator,
922 aux::rbtree_multi_policy
923 >;
924
925 tree_type tree_;
926 allocator_type allocator_;
927
928 template<class K, class C, class A>
929 friend bool operator==(const multiset<K, C, A>&,
930 const multiset<K, C, A>&);
931 };
932
933 template<class Key, class Compare, class Allocator>
934 bool operator==(const multiset<Key, Compare, Allocator>& lhs,
935 const multiset<Key, Compare, Allocator>& rhs)
936 {
937 return lhs.tree_.is_eq_to(rhs.tree_);
938 }
939
940 template<class Key, class Compare, class Allocator>
941 bool operator<(const multiset<Key, Compare, Allocator>& lhs,
942 const multiset<Key, Compare, Allocator>& rhs)
943 {
944 // TODO: need lexicographical_compare
945 return false;
946 }
947
948 template<class Key, class Compare, class Allocator>
949 bool operator!=(const multiset<Key, Compare, Allocator>& lhs,
950 const multiset<Key, Compare, Allocator>& rhs)
951 {
952 return !(lhs == rhs);
953 }
954
955 template<class Key, class Compare, class Allocator>
956 bool operator>(const multiset<Key, Compare, Allocator>& lhs,
957 const multiset<Key, Compare, Allocator>& rhs)
958 {
959 // TODO: need lexicographical_compare
960 return false;
961 }
962
963 template<class Key, class Compare, class Allocator>
964 bool operator>=(const multiset<Key, Compare, Allocator>& lhs,
965 const multiset<Key, Compare, Allocator>& rhs)
966 {
967 // TODO: need lexicographical_compare
968 return false;
969 }
970
971 template<class Key, class Compare, class Allocator>
972 bool operator<=(const multiset<Key, Compare, Allocator>& lhs,
973 const multiset<Key, Compare, Allocator>& rhs)
974 {
975 // TODO: need lexicographical_compare
976 return false;
977 }
[89bc6460]978}
[55d6223]979
980#endif
Note: See TracBrowser for help on using the repository browser.