source: mainline/uspace/lib/cpp/include/impl/map.hpp@ 7bbf91e

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

cpp: changed internal to bits to avoid include space pollusion, fixed old std::hel:: bugs in files that weren't touched since

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