source: mainline/uspace/lib/cpp/include/__bits/adt/map.hpp@ 34b2f54d

Last change on this file since 34b2f54d was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 35.7 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_ADT_MAP
8#define LIBCPP_BITS_ADT_MAP
9
10#include <__bits/adt/rbtree.hpp>
11#include <functional>
12#include <iterator>
13#include <memory>
14#include <utility>
15#include <type_traits>
16
17namespace std
18{
19 /**
20 * 23.4.4, class template map:
21 */
22
23 template<
24 class Key, class Value,
25 class Compare = less<Key>,
26 class Alloc = allocator<pair<const Key, Value>>
27 >
28 class map
29 {
30 public:
31 using key_type = Key;
32 using mapped_type = Value;
33 using value_type = pair<const key_type, mapped_type>;
34 using key_compare = Compare;
35 using allocator_type = Alloc;
36 using pointer = typename allocator_traits<allocator_type>::pointer;
37 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
38 using reference = value_type&;
39 using const_reference = const value_type&;
40 using size_type = size_t;
41 using difference_type = ptrdiff_t;
42
43 using node_type = aux::rbtree_single_node<value_type>;
44
45 using iterator = aux::rbtree_iterator<
46 value_type, reference, pointer, size_type, node_type
47 >;
48 using const_iterator = aux::rbtree_const_iterator<
49 value_type, const_reference, const_pointer, size_type, node_type
50 >;
51
52 using reverse_iterator = std::reverse_iterator<iterator>;
53 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54
55 class value_compare
56 {
57 friend class map;
58
59 protected:
60 key_compare comp;
61
62 value_compare(key_compare c)
63 : comp{c}
64 { /* DUMMY BODY */ }
65
66 public:
67 using result_type = bool;
68 using first_argument_type = value_type;
69 using second_argument_type = value_type;
70
71 bool operator()(const value_type& lhs, const value_type& rhs) const
72 {
73 return comp(lhs.first, rhs.first);
74 }
75 };
76
77 /**
78 * 24.4.4.2, construct/copy/destroy:
79 */
80
81 map()
82 : map{key_compare{}}
83 { /* DUMMY BODY */ }
84
85 explicit map(const key_compare& comp,
86 const allocator_type& alloc = allocator_type{})
87 : tree_{comp}, allocator_{alloc}
88 { /* DUMMY BODY */ }
89
90 template<class InputIterator>
91 map(InputIterator first, InputIterator last,
92 const key_compare& comp = key_compare{},
93 const allocator_type& alloc = allocator_type{})
94 : map{comp, alloc}
95 {
96 insert(first, last);
97 }
98
99 map(const map& other)
100 : map{other, other.allocator_}
101 { /* DUMMY BODY */ }
102
103 map(map&& other)
104 : tree_{move(other.tree_)}, allocator_{move(other.allocator_)}
105 { /* DUMMY BODY */ }
106
107 explicit map(const allocator_type& alloc)
108 : tree_{}, allocator_{alloc}
109 { /* DUMMY BODY */ }
110
111 map(const map& other, const allocator_type& alloc)
112 : tree_{other.tree_}, allocator_{alloc}
113 { /* DUMMY BODY */ }
114
115 map(map&& other, const allocator_type& alloc)
116 : tree_{move(other.tree_)}, allocator_{alloc}
117 { /* DUMMY BODY */ }
118
119 map(initializer_list<value_type> init,
120 const key_compare& comp = key_compare{},
121 const allocator_type& alloc = allocator_type{})
122 : map{comp, alloc}
123 {
124 insert(init.begin(), init.end());
125 }
126
127 template<class InputIterator>
128 map(InputIterator first, InputIterator last,
129 const allocator_type& alloc)
130 : map{first, last, key_compare{}, alloc}
131 { /* DUMMY BODY */ }
132
133 map(initializer_list<value_type> init,
134 const allocator_type& alloc)
135 : map{init, key_compare{}, alloc}
136 { /* DUMMY BODY */ }
137
138 ~map()
139 { /* DUMMY BODY */ }
140
141 map& operator=(const map& other)
142 {
143 tree_ = other.tree_;
144 allocator_ = other.allocator_;
145
146 return *this;
147 }
148
149 map& operator=(map&& other)
150 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
151 is_nothrow_move_assignable<key_compare>::value)
152 {
153 tree_ = move(other.tree_);
154 allocator_ = move(other.allocator_);
155
156 return *this;
157 }
158
159 map& operator=(initializer_list<value_type>& init)
160 {
161 tree_.clear();
162
163 insert(init.begin(), init.end());
164
165 return *this;
166 }
167
168 allocator_type get_allocator() const noexcept
169 {
170 return allocator_;
171 }
172
173 iterator begin() noexcept
174 {
175 return tree_.begin();
176 }
177
178 const_iterator begin() const noexcept
179 {
180 return tree_.begin();
181 }
182
183 iterator end() noexcept
184 {
185 return tree_.end();
186 }
187
188 const_iterator end() const noexcept
189 {
190 return tree_.end();
191 }
192
193 reverse_iterator rbegin() noexcept
194 {
195 return tree_.rbegin();
196 }
197
198 const_reverse_iterator rbegin() const noexcept
199 {
200 return tree_.rbegin();
201 }
202
203 reverse_iterator rend() noexcept
204 {
205 return tree_.rend();
206 }
207
208 const_reverse_iterator rend() const noexcept
209 {
210 return tree_.rend();
211 }
212
213 const_iterator cbegin() const noexcept
214 {
215 return tree_.cbegin();
216 }
217
218 const_iterator cend() const noexcept
219 {
220 return tree_.cend();
221 }
222
223 const_reverse_iterator crbegin() const noexcept
224 {
225 return tree_.crbegin();
226 }
227
228 const_reverse_iterator crend() const noexcept
229 {
230 return tree_.crend();
231 }
232
233 bool empty() const noexcept
234 {
235 return tree_.empty();
236 }
237
238 size_type size() const noexcept
239 {
240 return tree_.size();
241 }
242
243 size_type max_size() const noexcept
244 {
245 return tree_.max_size(allocator_);
246 }
247
248 /**
249 * 23.4.4.3, element access:
250 */
251
252 mapped_type& operator[](const key_type& key)
253 {
254 auto parent = tree_.find_parent_for_insertion(key);
255 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
256 return parent->value.second;
257
258 auto node = new node_type{value_type{key, mapped_type{}}};
259 tree_.insert_node(node, parent);
260
261 return node->value.second;
262 }
263
264 mapped_type& operator[](key_type&& key)
265 {
266 auto parent = tree_.find_parent_for_insertion(key);
267 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
268 return parent->value.second;
269
270 auto node = new node_type{value_type{move(key), mapped_type{}}};
271 tree_.insert_node(node, parent);
272
273 return node->value.second;
274 }
275
276 mapped_type& at(const key_type& key)
277 {
278 auto it = find(key);
279
280 // TODO: throw out_of_range if it == end()
281 return it->second;
282 }
283
284 const mapped_type& at(const key_type& key) const
285 {
286 auto it = find(key);
287
288 // TODO: throw out_of_range if it == end()
289 return it->second;
290 }
291
292 /**
293 * 23.4.4.4, modifiers:
294 */
295
296 template<class... Args>
297 pair<iterator, bool> emplace(Args&&... args)
298 {
299 return tree_.emplace(forward<Args>(args)...);
300 }
301
302 template<class... Args>
303 iterator emplace_hint(const_iterator, Args&&... args)
304 {
305 return emplace(forward<Args>(args)...).first;
306 }
307
308 pair<iterator, bool> insert(const value_type& val)
309 {
310 return tree_.insert(val);
311 }
312
313 pair<iterator, bool> insert(value_type&& val)
314 {
315 return tree_.insert(forward<value_type>(val));
316 }
317
318 template<class T>
319 pair<iterator, bool> insert(
320 T&& val,
321 enable_if_t<is_constructible_v<value_type, T&&>>* = nullptr
322 )
323 {
324 return emplace(forward<T>(val));
325 }
326
327 iterator insert(const_iterator, const value_type& val)
328 {
329 return insert(val).first;
330 }
331
332 iterator insert(const_iterator, value_type&& val)
333 {
334 return insert(forward<value_type>(val)).first;
335 }
336
337 template<class T>
338 iterator insert(
339 const_iterator hint,
340 T&& val,
341 enable_if_t<is_constructible_v<value_type, T&&>>* = nullptr
342 )
343 {
344 return emplace_hint(hint, forward<T>(val));
345 }
346
347 template<class InputIterator>
348 void insert(InputIterator first, InputIterator last)
349 {
350 while (first != last)
351 insert(*first++);
352 }
353
354 void insert(initializer_list<value_type> init)
355 {
356 insert(init.begin(), init.end());
357 }
358
359 template<class... Args>
360 pair<iterator, bool> try_emplace(const key_type& key, Args&&... args)
361 {
362 auto parent = tree_.find_parent_for_insertion(key);
363 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
364 return make_pair(iterator{parent, false}, false);
365 else
366 {
367 auto node = new node_type{value_type{key, forward<Args>(args)...}};
368 tree_.insert_node(node, parent);
369
370 return make_pair(iterator{node, false}, true);
371 }
372 }
373
374 template<class... Args>
375 pair<iterator, bool> try_emplace(key_type&& key, Args&&... args)
376 {
377 auto parent = tree_.find_parent_for_insertion(key);
378 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
379 return make_pair(iterator{parent, false}, false);
380 else
381 {
382 auto node = new node_type{value_type{move(key), forward<Args>(args)...}};
383 tree_.insert_node(node, parent);
384
385 return make_pair(iterator{node, false}, true);
386 }
387 }
388
389 template<class... Args>
390 iterator try_emplace(const_iterator, const key_type& key, Args&&... args)
391 {
392 return try_emplace(key, forward<Args>(args)...).first;
393 }
394
395 template<class... Args>
396 iterator try_emplace(const_iterator, key_type&& key, Args&&... args)
397 {
398 return try_emplace(move(key), forward<Args>(args)...).first;
399 }
400
401 template<class T>
402 pair<iterator, bool> insert_or_assign(const key_type& key, T&& val)
403 {
404 auto parent = tree_.find_parent_for_insertion(key);
405 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
406 {
407 parent->value.second = forward<T>(val);
408
409 return make_pair(iterator{parent, false}, false);
410 }
411 else
412 {
413 auto node = new node_type{value_type{key, forward<T>(val)}};
414 tree_.insert_node(node, parent);
415
416 return make_pair(iterator{node, false}, true);
417 }
418 }
419
420 template<class T>
421 pair<iterator, bool> insert_or_assign(key_type&& key, T&& val)
422 {
423 auto parent = tree_.find_parent_for_insertion(key);
424 if (parent && tree_.keys_equal(tree_.get_key(parent->value), key))
425 {
426 parent->value.second = forward<T>(val);
427
428 return make_pair(iterator{parent, false}, false);
429 }
430 else
431 {
432 auto node = new node_type{value_type{move(key), forward<T>(val)}};
433 tree_.insert_node(node, parent);
434
435 return make_pair(iterator{node, false}, true);
436 }
437 }
438
439 template<class T>
440 iterator insert_or_assign(const_iterator, const key_type& key, T&& val)
441 {
442 return insert_or_assign(key, forward<T>(val)).first;
443 }
444
445 template<class T>
446 iterator insert_or_assign(const_iterator, key_type&& key, T&& val)
447 {
448 return insert_or_assign(move(key), forward<T>(val)).first;
449 }
450
451 iterator erase(const_iterator position)
452 {
453 return tree_.erase(position);
454 }
455
456 size_type erase(const key_type& key)
457 {
458 return tree_.erase(key);
459 }
460
461 iterator erase(const_iterator first, const_iterator last)
462 {
463 while (first != last)
464 first = erase(first);
465
466 return iterator{
467 first.node(), first.end()
468 };
469 }
470
471 void swap(map& other)
472 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
473 noexcept(std::swap(declval<key_compare>(), declval<key_compare>())))
474 {
475 tree_.swap(other.tree_);
476 std::swap(allocator_, other.allocator_);
477 }
478
479 void clear() noexcept
480 {
481 tree_.clear();
482 }
483
484 key_compare key_comp() const
485 {
486 return tree_.key_comp();
487 }
488
489 value_compare value_comp() const
490 {
491 return value_compare{tree_.key_comp()};
492 }
493
494 iterator find(const key_type& key)
495 {
496 return tree_.find(key);
497 }
498
499 const_iterator find(const key_type& key) const
500 {
501 return tree_.find(key);
502 }
503
504 template<class K>
505 iterator find(
506 const K& key,
507 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
508 )
509 {
510 return tree_.find(key);
511 }
512
513 template<class K>
514 const_iterator find(
515 const K& key,
516 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
517 ) const
518 {
519 return tree_.find(key);
520 }
521
522 size_type count(const key_type& key) const
523 {
524 return tree_.count(key);
525 }
526
527 template<class K>
528 size_type count(
529 const K& key,
530 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
531 ) const
532 {
533 return tree_.count(key);
534 }
535
536 iterator lower_bound(const key_type& key)
537 {
538 return tree_.lower_bound(key);
539 }
540
541 const_iterator lower_bound(const key_type& key) const
542 {
543 return tree_.lower_bound(key);
544 }
545
546 template<class K>
547 iterator lower_bound(
548 const K& key,
549 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
550 )
551 {
552 return tree_.lower_bound(key);
553 }
554
555 template<class K>
556 const_iterator lower_bound(
557 const K& key,
558 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
559 ) const
560 {
561 return tree_.lower_bound(key);
562 }
563
564 iterator upper_bound(const key_type& key)
565 {
566 return tree_.upper_bound(key);
567 }
568
569 const_iterator upper_bound(const key_type& key) const
570 {
571 return tree_.upper_bound(key);
572 }
573
574 template<class K>
575 iterator upper_bound(
576 const K& key,
577 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
578 )
579 {
580 return tree_.upper_bound(key);
581 }
582
583 template<class K>
584 const_iterator upper_bound(
585 const K& key,
586 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
587 ) const
588 {
589 return tree_.upper_bound(key);
590 }
591
592 pair<iterator, iterator> equal_range(const key_type& key)
593 {
594 return tree_.equal_range(key);
595 }
596
597 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
598 {
599 return tree_.equal_range(key);
600 }
601
602 template<class K>
603 pair<iterator, iterator> equal_range(
604 const K& key,
605 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
606 )
607 {
608 return tree_.equal_range(key);
609 }
610
611 template<class K>
612 pair<const_iterator, const_iterator> equal_range(
613 const K& key,
614 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
615 ) const
616 {
617 return tree_.equal_range(key);
618 }
619
620 private:
621 using tree_type = aux::rbtree<
622 value_type, key_type, aux::key_value_key_extractor<key_type, mapped_type>,
623 key_compare, allocator_type, size_type,
624 iterator, const_iterator,
625 aux::rbtree_single_policy, node_type
626 >;
627
628 tree_type tree_;
629 allocator_type allocator_;
630
631 template<class K, class C, class A>
632 friend bool operator==(const map<K, C, A>&,
633 const map<K, C, A>&);
634 };
635
636 template<class Key, class Compare, class Allocator>
637 bool operator==(const map<Key, Compare, Allocator>& lhs,
638 const map<Key, Compare, Allocator>& rhs)
639 {
640 return lhs.tree_.is_eq_to(rhs.tree_);
641 }
642
643 template<class Key, class Compare, class Allocator>
644 bool operator<(const map<Key, Compare, Allocator>& lhs,
645 const map<Key, Compare, Allocator>& rhs)
646 {
647 return lexicographical_compare(
648 lhs.begin(), lhs.end(),
649 rhs.begin(), rhs.end(),
650 lhs.value_comp()
651 );
652 }
653
654 template<class Key, class Compare, class Allocator>
655 bool operator!=(const map<Key, Compare, Allocator>& lhs,
656 const map<Key, Compare, Allocator>& rhs)
657 {
658 return !(lhs == rhs);
659 }
660
661 template<class Key, class Compare, class Allocator>
662 bool operator>(const map<Key, Compare, Allocator>& lhs,
663 const map<Key, Compare, Allocator>& rhs)
664 {
665 return rhs < lhs;
666 }
667
668 template<class Key, class Compare, class Allocator>
669 bool operator>=(const map<Key, Compare, Allocator>& lhs,
670 const map<Key, Compare, Allocator>& rhs)
671 {
672 return !(lhs < rhs);
673 }
674
675 template<class Key, class Compare, class Allocator>
676 bool operator<=(const map<Key, Compare, Allocator>& lhs,
677 const map<Key, Compare, Allocator>& rhs)
678 {
679 return !(rhs < lhs);
680 }
681
682 /**
683 * 23.4.5, class template multimap:
684 */
685
686 template<
687 class Key, class Value,
688 class Compare = less<Key>,
689 class Alloc = allocator<pair<const Key, Value>>
690 >
691 class multimap
692 {
693 public:
694 using key_type = Key;
695 using mapped_type = Value;
696 using value_type = pair<const key_type, mapped_type>;
697 using key_compare = Compare;
698 using allocator_type = Alloc;
699 using pointer = typename allocator_traits<allocator_type>::pointer;
700 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
701 using reference = value_type&;
702 using const_reference = const value_type&;
703 using size_type = size_t;
704 using difference_type = ptrdiff_t;
705
706 using node_type = aux::rbtree_multi_node<value_type>;
707
708 class value_compare
709 {
710 friend class multimap;
711
712 protected:
713 key_compare comp;
714
715 value_compare(key_compare c)
716 : comp{c}
717 { /* DUMMY BODY */ }
718
719 public:
720 using result_type = bool;
721 using first_argument_type = value_type;
722 using second_argument_type = value_type;
723
724 bool operator()(const value_type& lhs, const value_type& rhs) const
725 {
726 return comp(lhs.first, rhs.first);
727 }
728 };
729
730 using iterator = aux::rbtree_iterator<
731 value_type, reference, pointer, size_type, node_type
732 >;
733 using const_iterator = aux::rbtree_const_iterator<
734 value_type, const_reference, const_pointer, size_type, node_type
735 >;
736
737 using reverse_iterator = std::reverse_iterator<iterator>;
738 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
739
740 multimap()
741 : multimap{key_compare{}}
742 { /* DUMMY BODY */ }
743
744 explicit multimap(const key_compare& comp,
745 const allocator_type& alloc = allocator_type{})
746 : tree_{comp}, allocator_{alloc}
747 { /* DUMMY BODY */ }
748
749 template<class InputIterator>
750 multimap(InputIterator first, InputIterator last,
751 const key_compare& comp = key_compare{},
752 const allocator_type& alloc = allocator_type{})
753 : multimap{comp, alloc}
754 {
755 insert(first, last);
756 }
757
758 multimap(const multimap& other)
759 : multimap{other, other.allocator_}
760 { /* DUMMY BODY */ }
761
762 multimap(multimap&& other)
763 : tree_{move(other.tree_)}, allocator_{move(other.allocator_)}
764 { /* DUMMY BODY */ }
765
766 explicit multimap(const allocator_type& alloc)
767 : tree_{}, allocator_{alloc}
768 { /* DUMMY BODY */ }
769
770 multimap(const multimap& other, const allocator_type& alloc)
771 : tree_{other.tree_}, allocator_{alloc}
772 { /* DUMMY BODY */ }
773
774 multimap(multimap&& other, const allocator_type& alloc)
775 : tree_{move(other.tree_)}, allocator_{alloc}
776 { /* DUMMY BODY */ }
777
778 multimap(initializer_list<value_type> init,
779 const key_compare& comp = key_compare{},
780 const allocator_type& alloc = allocator_type{})
781 : multimap{comp, alloc}
782 {
783 insert(init.begin(), init.end());
784 }
785
786 template<class InputIterator>
787 multimap(InputIterator first, InputIterator last,
788 const allocator_type& alloc)
789 : multimap{first, last, key_compare{}, alloc}
790 { /* DUMMY BODY */ }
791
792 multimap(initializer_list<value_type> init,
793 const allocator_type& alloc)
794 : multimap{init, key_compare{}, alloc}
795 { /* DUMMY BODY */ }
796
797 ~multimap()
798 { /* DUMMY BODY */ }
799
800 multimap& operator=(const multimap& other)
801 {
802 tree_ = other.tree_;
803 allocator_ = other.allocator_;
804
805 return *this;
806 }
807
808 multimap& operator=(multimap&& other)
809 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
810 is_nothrow_move_assignable<key_compare>::value)
811 {
812 tree_ = move(other.tree_);
813 allocator_ = move(other.allocator_);
814
815 return *this;
816 }
817
818 multimap& operator=(initializer_list<value_type>& init)
819 {
820 tree_.clear();
821
822 insert(init.begin(), init.end());
823
824 return *this;
825 }
826
827 allocator_type get_allocator() const noexcept
828 {
829 return allocator_;
830 }
831
832 iterator begin() noexcept
833 {
834 return tree_.begin();
835 }
836
837 const_iterator begin() const noexcept
838 {
839 return tree_.begin();
840 }
841
842 iterator end() noexcept
843 {
844 return tree_.end();
845 }
846
847 const_iterator end() const noexcept
848 {
849 return tree_.end();
850 }
851
852 reverse_iterator rbegin() noexcept
853 {
854 return tree_.rbegin();
855 }
856
857 const_reverse_iterator rbegin() const noexcept
858 {
859 return tree_.rbegin();
860 }
861
862 reverse_iterator rend() noexcept
863 {
864 return tree_.rend();
865 }
866
867 const_reverse_iterator rend() const noexcept
868 {
869 return tree_.rend();
870 }
871
872 const_iterator cbegin() const noexcept
873 {
874 return tree_.cbegin();
875 }
876
877 const_iterator cend() const noexcept
878 {
879 return tree_.cend();
880 }
881
882 const_reverse_iterator crbegin() const noexcept
883 {
884 return tree_.crbegin();
885 }
886
887 const_reverse_iterator crend() const noexcept
888 {
889 return tree_.crend();
890 }
891
892 bool empty() const noexcept
893 {
894 return tree_.empty();
895 }
896
897 size_type size() const noexcept
898 {
899 return tree_.size();
900 }
901
902 size_type max_size() const noexcept
903 {
904 return tree_.max_size(allocator_);
905 }
906
907 template<class... Args>
908 iterator emplace(Args&&... args)
909 {
910 return tree_.emplace(forward<Args>(args)...);
911 }
912
913 template<class... Args>
914 iterator emplace_hint(const_iterator, Args&&... args)
915 {
916 return emplace(forward<Args>(args)...);
917 }
918
919 iterator insert(const value_type& val)
920 {
921 return tree_.insert(val);
922 }
923
924 iterator insert(value_type&& val)
925 {
926 return tree_.insert(forward<value_type>(val));
927 }
928
929 template<class T>
930 iterator insert(
931 T&& val,
932 enable_if_t<is_constructible_v<value_type, T&&>>* = nullptr
933 )
934 {
935 return emplace(forward<T>(val));
936 }
937
938 iterator insert(const_iterator, const value_type& val)
939 {
940 return insert(val);
941 }
942
943 iterator insert(const_iterator, value_type&& val)
944 {
945 return insert(forward<value_type>(val));
946 }
947
948 template<class T>
949 iterator insert(
950 const_iterator hint,
951 T&& val,
952 enable_if_t<is_constructible_v<value_type, T&&>>* = nullptr
953 )
954 {
955 return emplace_hint(hint, forward<T>(val));
956 }
957
958 template<class InputIterator>
959 void insert(InputIterator first, InputIterator last)
960 {
961 while (first != last)
962 insert(*first++);
963 }
964
965 void insert(initializer_list<value_type> init)
966 {
967 insert(init.begin(), init.end());
968 }
969
970 iterator erase(const_iterator position)
971 {
972 return tree_.erase(position);
973 }
974
975 size_type erase(const key_type& key)
976 {
977 return tree_.erase(key);
978 }
979
980 iterator erase(const_iterator first, const_iterator last)
981 {
982 while (first != last)
983 first = erase(first);
984
985 return iterator{
986 first.node(), first.end()
987 };
988 }
989
990 void swap(multimap& other)
991 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
992 noexcept(std::swap(declval<key_compare>(), declval<key_compare>())))
993 {
994 tree_.swap(other.tree_);
995 std::swap(allocator_, other.allocator_);
996 }
997
998 void clear() noexcept
999 {
1000 tree_.clear();
1001 }
1002
1003 key_compare key_comp() const
1004 {
1005 return tree_.key_comp();
1006 }
1007
1008 value_compare value_comp() const
1009 {
1010 return value_compare{tree_.key_comp()};
1011 }
1012
1013 iterator find(const key_type& key)
1014 {
1015 return tree_.find(key);
1016 }
1017
1018 const_iterator find(const key_type& key) const
1019 {
1020 return tree_.find(key);
1021 }
1022
1023 template<class K>
1024 iterator find(
1025 const K& key,
1026 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1027 )
1028 {
1029 return tree_.find(key);
1030 }
1031
1032 template<class K>
1033 const_iterator find(
1034 const K& key,
1035 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1036 ) const
1037 {
1038 return tree_.find(key);
1039 }
1040
1041 size_type count(const key_type& key) const
1042 {
1043 return tree_.count(key);
1044 }
1045
1046 template<class K>
1047 size_type count(
1048 const K& key,
1049 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1050 ) const
1051 {
1052 return tree_.count(key);
1053 }
1054
1055 iterator lower_bound(const key_type& key)
1056 {
1057 return tree_.lower_bound(key);
1058 }
1059
1060 const_iterator lower_bound(const key_type& key) const
1061 {
1062 return tree_.lower_bound(key);
1063 }
1064
1065 template<class K>
1066 iterator lower_bound(
1067 const K& key,
1068 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1069 )
1070 {
1071 return tree_.lower_bound(key);
1072 }
1073
1074 template<class K>
1075 const_iterator lower_bound(
1076 const K& key,
1077 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1078 ) const
1079 {
1080 return tree_.lower_bound(key);
1081 }
1082
1083 iterator upper_bound(const key_type& key)
1084 {
1085 return tree_.upper_bound(key);
1086 }
1087
1088 const_iterator upper_bound(const key_type& key) const
1089 {
1090 return tree_.upper_bound(key);
1091 }
1092
1093 template<class K>
1094 iterator upper_bound(
1095 const K& key,
1096 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1097 )
1098 {
1099 return tree_.upper_bound(key);
1100 }
1101
1102 template<class K>
1103 const_iterator upper_bound(
1104 const K& key,
1105 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1106 ) const
1107 {
1108 return tree_.upper_bound(key);
1109 }
1110
1111 pair<iterator, iterator> equal_range(const key_type& key)
1112 {
1113 return tree_.equal_range(key);
1114 }
1115
1116 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
1117 {
1118 return tree_.equal_range(key);
1119 }
1120
1121 template<class K>
1122 pair<iterator, iterator> equal_range(
1123 const K& key,
1124 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1125 )
1126 {
1127 return tree_.equal_range(key);
1128 }
1129
1130 template<class K>
1131 pair<const_iterator, const_iterator> equal_range(
1132 const K& key,
1133 enable_if_t<aux::is_transparent_v<key_compare>, K>* = nullptr
1134 ) const
1135 {
1136 return tree_.equal_range(key);
1137 }
1138
1139 private:
1140 using tree_type = aux::rbtree<
1141 value_type, key_type, aux::key_value_key_extractor<key_type, mapped_type>,
1142 key_compare, allocator_type, size_type,
1143 iterator, const_iterator,
1144 aux::rbtree_multi_policy, node_type
1145 >;
1146
1147 tree_type tree_;
1148 allocator_type allocator_;
1149
1150 template<class K, class C, class A>
1151 friend bool operator==(const multimap<K, C, A>&,
1152 const multimap<K, C, A>&);
1153 };
1154
1155 template<class Key, class Compare, class Allocator>
1156 bool operator==(const multimap<Key, Compare, Allocator>& lhs,
1157 const multimap<Key, Compare, Allocator>& rhs)
1158 {
1159 return lhs.tree_.is_eq_to(rhs.tree_);
1160 }
1161
1162 template<class Key, class Compare, class Allocator>
1163 bool operator<(const multimap<Key, Compare, Allocator>& lhs,
1164 const multimap<Key, Compare, Allocator>& rhs)
1165 {
1166 return lexicographical_compare(
1167 lhs.begin(), lhs.end(),
1168 rhs.begin(), rhs.end(),
1169 lhs.value_comp()
1170 );
1171 }
1172
1173 template<class Key, class Compare, class Allocator>
1174 bool operator!=(const multimap<Key, Compare, Allocator>& lhs,
1175 const multimap<Key, Compare, Allocator>& rhs)
1176 {
1177 return !(lhs == rhs);
1178 }
1179
1180 template<class Key, class Compare, class Allocator>
1181 bool operator>(const multimap<Key, Compare, Allocator>& lhs,
1182 const multimap<Key, Compare, Allocator>& rhs)
1183 {
1184 return rhs < lhs;
1185 }
1186
1187 template<class Key, class Compare, class Allocator>
1188 bool operator>=(const multimap<Key, Compare, Allocator>& lhs,
1189 const multimap<Key, Compare, Allocator>& rhs)
1190 {
1191 return !(lhs < rhs);
1192 }
1193
1194 template<class Key, class Compare, class Allocator>
1195 bool operator<=(const multimap<Key, Compare, Allocator>& lhs,
1196 const multimap<Key, Compare, Allocator>& rhs)
1197 {
1198 return !(rhs < lhs);
1199 }
1200}
1201
1202#endif
Note: See TracBrowser for help on using the repository browser.