56 #ifndef _STL_MULTIMAP_H
57 #define _STL_MULTIMAP_H 1
60 #if __cplusplus >= 201103L
63 #if __glibcxx_containers_ranges // C++ >= 23
68 namespace std _GLIBCXX_VISIBILITY(default)
70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
71 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
73 template <
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
102 template <
typename _Key,
typename _Tp,
108 typedef _Key key_type;
109 typedef _Tp mapped_type;
111 typedef _Compare key_compare;
112 typedef _Alloc allocator_type;
115 #ifdef _GLIBCXX_CONCEPT_CHECKS
117 typedef typename _Alloc::value_type _Alloc_value_type;
118 # if __cplusplus < 201103L
119 __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
121 __glibcxx_class_requires4(_Compare,
bool, _Key, _Key,
122 _BinaryFunctionConcept)
123 __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept)
126 #if __cplusplus >= 201103L
127 #if __cplusplus > 201703L || defined __STRICT_ANSI__
128 static_assert(is_same<typename _Alloc::value_type, value_type>::value,
129 "std::multimap must have the same value_type as its allocator");
134 #pragma GCC diagnostic push
135 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
139 friend class multimap<_Key, _Tp, _Compare, _Alloc>;
143 value_compare(_Compare __c)
147 bool operator()(
const value_type& __x,
const value_type& __y)
const
148 {
return comp(__x.first, __y.first); }
150 #pragma GCC diagnostic pop
155 rebind<value_type>::other _Pair_alloc_type;
157 typedef _Rb_tree<key_type, value_type, _Select1st<value_type>,
158 key_compare, _Pair_alloc_type> _Rep_type;
167 typedef typename _Alloc_traits::pointer pointer;
168 typedef typename _Alloc_traits::const_pointer const_pointer;
169 typedef typename _Alloc_traits::reference reference;
170 typedef typename _Alloc_traits::const_reference const_reference;
171 typedef typename _Rep_type::iterator iterator;
172 typedef typename _Rep_type::const_iterator const_iterator;
173 typedef typename _Rep_type::size_type size_type;
174 typedef typename _Rep_type::difference_type difference_type;
175 typedef typename _Rep_type::reverse_iterator reverse_iterator;
176 typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
178 #ifdef __glibcxx_node_extract // >= C++17
179 using node_type =
typename _Rep_type::node_type;
188 #if __cplusplus < 201103L
201 const allocator_type& __a = allocator_type())
202 : _M_t(__comp, _Pair_alloc_type(__a)) { }
209 #if __cplusplus < 201103L
235 const _Compare& __comp = _Compare(),
236 const allocator_type& __a = allocator_type())
237 : _M_t(__comp, _Pair_alloc_type(__a))
238 { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
243 : _M_t(_Pair_alloc_type(__a)) { }
247 const __type_identity_t<allocator_type>& __a)
248 : _M_t(__m._M_t, _Pair_alloc_type(__a)) { }
253 && _Alloc_traits::_S_always_equal())
254 : _M_t(
std::
move(__m._M_t), _Pair_alloc_type(__a)) { }
258 : _M_t(_Pair_alloc_type(__a))
259 { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
262 template<
typename _InputIterator>
263 multimap(_InputIterator __first, _InputIterator __last,
264 const allocator_type& __a)
265 : _M_t(_Pair_alloc_type(__a))
266 { _M_t._M_insert_range_equal(__first, __last); }
278 template<
typename _InputIterator>
279 multimap(_InputIterator __first, _InputIterator __last)
281 { _M_t._M_insert_range_equal(__first, __last); }
294 template<
typename _InputIterator>
295 multimap(_InputIterator __first, _InputIterator __last,
296 const _Compare& __comp,
297 const allocator_type& __a = allocator_type())
298 : _M_t(__comp, _Pair_alloc_type(__a))
299 { _M_t._M_insert_range_equal(__first, __last); }
301 #if __glibcxx_containers_ranges // C++ >= 23
306 template<__detail::__container_compatible_range<value_type> _Rg>
308 const _Compare& __comp,
309 const _Alloc& __a = _Alloc())
310 : _M_t(__comp, _Pair_alloc_type(__a))
311 { insert_range(std::forward<_Rg>(__rg)); }
314 template<__detail::__container_compatible_range<value_type> _Rg>
315 multimap(from_range_t, _Rg&& __rg,
const _Alloc& __a = _Alloc())
316 : _M_t(_Pair_alloc_type(__a))
317 { insert_range(std::forward<_Rg>(__rg)); }
321 #if __cplusplus >= 201103L
335 #if __cplusplus < 201103L
364 _M_t._M_assign_equal(__l.begin(), __l.end());
372 {
return allocator_type(_M_t.get_allocator()); }
382 {
return _M_t.begin(); }
391 {
return _M_t.begin(); }
400 {
return _M_t.end(); }
408 end() const _GLIBCXX_NOEXCEPT
409 {
return _M_t.end(); }
418 {
return _M_t.rbegin(); }
425 const_reverse_iterator
427 {
return _M_t.rbegin(); }
436 {
return _M_t.rend(); }
443 const_reverse_iterator
445 {
return _M_t.rend(); }
447 #if __cplusplus >= 201103L
455 {
return _M_t.begin(); }
464 {
return _M_t.end(); }
471 const_reverse_iterator
473 {
return _M_t.rbegin(); }
480 const_reverse_iterator
482 {
return _M_t.rend(); }
487 _GLIBCXX_NODISCARD
bool
489 {
return _M_t.empty(); }
494 {
return _M_t.size(); }
499 {
return _M_t.max_size(); }
502 #if __cplusplus >= 201103L
519 template<
typename... _Args>
522 {
return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); }
546 template<
typename... _Args>
550 return _M_t._M_emplace_hint_equal(__pos,
551 std::forward<_Args>(__args)...);
570 {
return _M_t._M_insert_equal(__x); }
572 #if __cplusplus >= 201103L
577 {
return _M_t._M_insert_equal(
std::move(__x)); }
579 template<
typename _Pair>
580 __enable_if_t<is_constructible<value_type, _Pair>::value,
iterator>
582 {
return _M_t._M_emplace_equal(std::forward<_Pair>(__x)); }
608 #if __cplusplus >= 201103L
613 {
return _M_t._M_insert_equal_(__position, __x); }
615 #if __cplusplus >= 201103L
620 {
return _M_t._M_insert_equal_(__position,
std::move(__x)); }
622 template<
typename _Pair>
623 __enable_if_t<is_constructible<value_type, _Pair&&>::value,
iterator>
624 insert(const_iterator __position, _Pair&& __x)
626 return _M_t._M_emplace_hint_equal(__position,
627 std::forward<_Pair>(__x));
641 template<
typename _InputIterator>
643 insert(_InputIterator __first, _InputIterator __last)
644 { _M_t._M_insert_range_equal(__first, __last); }
646 #if __cplusplus >= 201103L
656 { this->
insert(__l.begin(), __l.end()); }
659 #if __glibcxx_containers_ranges // C++ >= 23
666 template<__detail::__container_compatible_range<value_type> _Rg>
668 insert_range(_Rg&& __rg)
670 auto __first = ranges::begin(__rg);
671 const auto __last = ranges::end(__rg);
672 for (; __first != __last; ++__first)
673 _M_t._M_emplace_equal(*__first);
678 #ifdef __glibcxx_node_extract // >= C++17
681 extract(const_iterator __pos)
683 __glibcxx_assert(__pos !=
end());
684 return _M_t.extract(__pos);
689 extract(
const key_type& __x)
690 {
return _M_t.extract(__x); }
692 #ifdef __glibcxx_associative_heterogeneous_erasure // C++23
693 template <__heterogeneous_tree_key<multimap> _Kt>
696 {
return _M_t._M_extract_tr(__key); }
702 {
return _M_t._M_reinsert_node_equal(
std::move(__nh)); }
706 insert(const_iterator __hint, node_type&& __nh)
707 {
return _M_t._M_reinsert_node_hint_equal(__hint,
std::move(__nh)); }
709 template<
typename,
typename>
710 friend struct std::_Rb_tree_merge_helper;
712 template<
typename _Cmp2>
714 merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source)
716 using _Merge_helper = _Rb_tree_merge_helper<multimap, _Cmp2>;
717 _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
720 template<
typename _Cmp2>
722 merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source)
725 template<
typename _Cmp2>
727 merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source)
729 using _Merge_helper = _Rb_tree_merge_helper<multimap, _Cmp2>;
730 _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
733 template<
typename _Cmp2>
735 merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source)
739 #if __cplusplus >= 201103L
759 {
return _M_t.erase(__position); }
762 _GLIBCXX_ABI_TAG_CXX11
765 {
return _M_t.erase(__position); }
780 { _M_t.erase(__position); }
796 {
return _M_t.erase(__x); }
798 #ifdef __glibcxx_associative_heterogeneous_erasure // C++23
799 template <__heterogeneous_tree_key<multimap> _Kt>
802 {
return _M_t._M_erase_tr(__key); }
805 #if __cplusplus >= 201103L
823 erase(const_iterator __first, const_iterator __last)
824 {
return _M_t.erase(__first, __last); }
843 { _M_t.erase(__first, __last); }
861 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value)
862 { _M_t.swap(__x._M_t); }
881 {
return _M_t.key_comp(); }
889 {
return value_compare(_M_t.key_comp()); }
907 {
return _M_t.find(__x); }
909 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
910 template<
typename _Kt>
912 find(
const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
913 {
return _M_t._M_find_tr(__x); }
930 find(
const key_type& __x)
const
931 {
return _M_t.find(__x); }
933 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
934 template<
typename _Kt>
936 find(
const _Kt& __x)
const -> decltype(_M_t._M_find_tr(__x))
937 {
return _M_t._M_find_tr(__x); }
949 {
return _M_t.count(__x); }
951 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
952 template<
typename _Kt>
954 count(
const _Kt& __x)
const -> decltype(_M_t._M_count_tr(__x))
955 {
return _M_t._M_count_tr(__x); }
959 #if __cplusplus > 201703L
968 {
return _M_t.find(__x) != _M_t.end(); }
970 template<
typename _Kt>
973 -> decltype(_M_t._M_find_tr(__x),
void(),
true)
974 {
return _M_t._M_find_tr(__x) != _M_t.end(); }
992 {
return _M_t.lower_bound(__x); }
994 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
995 template<
typename _Kt>
998 -> decltype(
iterator(_M_t._M_lower_bound_tr(__x)))
999 {
return iterator(_M_t._M_lower_bound_tr(__x)); }
1017 {
return _M_t.lower_bound(__x); }
1019 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1020 template<
typename _Kt>
1023 -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x)))
1024 {
return const_iterator(_M_t._M_lower_bound_tr(__x)); }
1037 {
return _M_t.upper_bound(__x); }
1039 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1040 template<
typename _Kt>
1043 -> decltype(
iterator(_M_t._M_upper_bound_tr(__x)))
1044 {
return iterator(_M_t._M_upper_bound_tr(__x)); }
1057 {
return _M_t.upper_bound(__x); }
1059 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1060 template<
typename _Kt>
1063 -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x)))
1064 {
return const_iterator(_M_t._M_upper_bound_tr(__x)); }
1084 {
return _M_t.equal_range(__x); }
1086 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1087 template<
typename _Kt>
1111 {
return _M_t.equal_range(__x); }
1113 #ifdef __glibcxx_generic_associative_lookup // C++ >= 14
1114 template<
typename _Kt>
1118 _M_t._M_equal_range_tr(__x)))
1121 _M_t._M_equal_range_tr(__x));
1126 template<
typename _K1,
typename _T1,
typename _C1,
typename _A1>
1128 operator==(
const multimap<_K1, _T1, _C1, _A1>&,
1129 const multimap<_K1, _T1, _C1, _A1>&);
1131 #if __cpp_lib_three_way_comparison
1132 template<
typename _K1,
typename _T1,
typename _C1,
typename _A1>
1133 friend __detail::__synth3way_t<pair<const _K1, _T1>>
1134 operator<=>(
const multimap<_K1, _T1, _C1, _A1>&,
1135 const multimap<_K1, _T1, _C1, _A1>&);
1137 template<
typename _K1,
typename _T1,
typename _C1,
typename _A1>
1139 operator<(
const multimap<_K1, _T1, _C1, _A1>&,
1140 const multimap<_K1, _T1, _C1, _A1>&);
1144 #if __cpp_deduction_guides >= 201606
1146 template<
typename _InputIterator,
1147 typename _Compare = less<__iter_key_t<_InputIterator>>,
1148 typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
1149 typename = _RequireInputIter<_InputIterator>,
1150 typename = _RequireNotAllocator<_Compare>,
1151 typename = _RequireAllocator<_Allocator>>
1152 multimap(_InputIterator, _InputIterator,
1153 _Compare = _Compare(), _Allocator = _Allocator())
1154 -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
1155 _Compare, _Allocator>;
1157 template<
typename _Key,
typename _Tp,
typename _Compare = less<_Key>,
1158 typename _Allocator = allocator<pair<const _Key, _Tp>>,
1159 typename = _RequireNotAllocator<_Compare>,
1160 typename = _RequireAllocator<_Allocator>>
1161 multimap(initializer_list<pair<_Key, _Tp>>,
1162 _Compare = _Compare(), _Allocator = _Allocator())
1163 -> multimap<_Key, _Tp, _Compare, _Allocator>;
1165 template<
typename _InputIterator,
typename _Allocator,
1166 typename = _RequireInputIter<_InputIterator>,
1167 typename = _RequireAllocator<_Allocator>>
1168 multimap(_InputIterator, _InputIterator, _Allocator)
1169 -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
1170 less<__iter_key_t<_InputIterator>>, _Allocator>;
1172 template<
typename _Key,
typename _Tp,
typename _Allocator,
1173 typename = _RequireAllocator<_Allocator>>
1174 multimap(initializer_list<pair<_Key, _Tp>>, _Allocator)
1175 -> multimap<_Key, _Tp, less<_Key>, _Allocator>;
1177 #if __glibcxx_containers_ranges // C++ >= 23
1178 template<ranges::input_range _Rg,
1179 __not_allocator_like _Compare = less<__detail::__range_key_type<_Rg>>,
1180 __allocator_like _Alloc =
1182 multimap(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())
1183 -> multimap<__detail::__range_key_type<_Rg>,
1184 __detail::__range_mapped_type<_Rg>,
1187 template<ranges::input_range _Rg, __allocator_like _Alloc>
1188 multimap(from_range_t, _Rg&&, _Alloc)
1189 -> multimap<__detail::__range_key_type<_Rg>,
1190 __detail::__range_mapped_type<_Rg>,
1191 less<__detail::__range_key_type<_Rg>>,
1195 #endif // deduction guides
1207 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1211 {
return __x._M_t == __y._M_t; }
1213 #if __cpp_lib_three_way_comparison
1228 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1229 inline __detail::__synth3way_t<pair<const _Key, _Tp>>
1230 operator<=>(
const multimap<_Key, _Tp, _Compare, _Alloc>& __x,
1231 const multimap<_Key, _Tp, _Compare, _Alloc>& __y)
1232 {
return __x._M_t <=> __y._M_t; }
1245 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1249 {
return __x._M_t < __y._M_t; }
1252 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1256 {
return !(__x == __y); }
1259 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1263 {
return __y < __x; }
1266 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1270 {
return !(__y < __x); }
1273 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1277 {
return !(__x < __y); }
1278 #endif // three-way comparison
1281 template<
typename _Key,
typename _Tp,
typename _Compare,
typename _Alloc>
1285 _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
1288 _GLIBCXX_END_NAMESPACE_CONTAINER
1290 #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
1292 template<
typename _Key,
typename _Val,
typename _Cmp1,
typename _Alloc,
1295 _Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>,
1299 friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>;
1302 _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map)
1303 {
return __map._M_t; }
1306 _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map)
1307 {
return __map._M_t; }
1311 _GLIBCXX_END_NAMESPACE_VERSION