1*700637cbSDimitry Andric // -*- C++ -*- 2*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 3*700637cbSDimitry Andric // 4*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*700637cbSDimitry Andric // 8*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 9*700637cbSDimitry Andric 10*700637cbSDimitry Andric #ifndef _LIBCPP___FLAT_MAP_FLAT_MULTISET_H 11*700637cbSDimitry Andric #define _LIBCPP___FLAT_MAP_FLAT_MULTISET_H 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric #include <__algorithm/equal_range.h> 14*700637cbSDimitry Andric #include <__algorithm/lexicographical_compare_three_way.h> 15*700637cbSDimitry Andric #include <__algorithm/lower_bound.h> 16*700637cbSDimitry Andric #include <__algorithm/min.h> 17*700637cbSDimitry Andric #include <__algorithm/ranges_equal.h> 18*700637cbSDimitry Andric #include <__algorithm/ranges_inplace_merge.h> 19*700637cbSDimitry Andric #include <__algorithm/ranges_is_sorted.h> 20*700637cbSDimitry Andric #include <__algorithm/ranges_sort.h> 21*700637cbSDimitry Andric #include <__algorithm/ranges_unique.h> 22*700637cbSDimitry Andric #include <__algorithm/remove_if.h> 23*700637cbSDimitry Andric #include <__algorithm/upper_bound.h> 24*700637cbSDimitry Andric #include <__assert> 25*700637cbSDimitry Andric #include <__compare/synth_three_way.h> 26*700637cbSDimitry Andric #include <__concepts/convertible_to.h> 27*700637cbSDimitry Andric #include <__concepts/swappable.h> 28*700637cbSDimitry Andric #include <__config> 29*700637cbSDimitry Andric #include <__cstddef/byte.h> 30*700637cbSDimitry Andric #include <__cstddef/ptrdiff_t.h> 31*700637cbSDimitry Andric #include <__flat_map/key_value_iterator.h> 32*700637cbSDimitry Andric #include <__flat_map/sorted_equivalent.h> 33*700637cbSDimitry Andric #include <__flat_set/ra_iterator.h> 34*700637cbSDimitry Andric #include <__flat_set/utils.h> 35*700637cbSDimitry Andric #include <__functional/invoke.h> 36*700637cbSDimitry Andric #include <__functional/is_transparent.h> 37*700637cbSDimitry Andric #include <__functional/operations.h> 38*700637cbSDimitry Andric #include <__fwd/vector.h> 39*700637cbSDimitry Andric #include <__iterator/concepts.h> 40*700637cbSDimitry Andric #include <__iterator/distance.h> 41*700637cbSDimitry Andric #include <__iterator/iterator_traits.h> 42*700637cbSDimitry Andric #include <__iterator/prev.h> 43*700637cbSDimitry Andric #include <__iterator/ranges_iterator_traits.h> 44*700637cbSDimitry Andric #include <__iterator/reverse_iterator.h> 45*700637cbSDimitry Andric #include <__memory/allocator_traits.h> 46*700637cbSDimitry Andric #include <__memory/uses_allocator.h> 47*700637cbSDimitry Andric #include <__memory/uses_allocator_construction.h> 48*700637cbSDimitry Andric #include <__ranges/access.h> 49*700637cbSDimitry Andric #include <__ranges/concepts.h> 50*700637cbSDimitry Andric #include <__ranges/container_compatible_range.h> 51*700637cbSDimitry Andric #include <__ranges/drop_view.h> 52*700637cbSDimitry Andric #include <__ranges/from_range.h> 53*700637cbSDimitry Andric #include <__ranges/ref_view.h> 54*700637cbSDimitry Andric #include <__ranges/size.h> 55*700637cbSDimitry Andric #include <__ranges/subrange.h> 56*700637cbSDimitry Andric #include <__ranges/zip_view.h> 57*700637cbSDimitry Andric #include <__type_traits/conjunction.h> 58*700637cbSDimitry Andric #include <__type_traits/container_traits.h> 59*700637cbSDimitry Andric #include <__type_traits/invoke.h> 60*700637cbSDimitry Andric #include <__type_traits/is_allocator.h> 61*700637cbSDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 62*700637cbSDimitry Andric #include <__type_traits/is_same.h> 63*700637cbSDimitry Andric #include <__type_traits/maybe_const.h> 64*700637cbSDimitry Andric #include <__utility/as_const.h> 65*700637cbSDimitry Andric #include <__utility/exception_guard.h> 66*700637cbSDimitry Andric #include <__utility/move.h> 67*700637cbSDimitry Andric #include <__utility/pair.h> 68*700637cbSDimitry Andric #include <__utility/scope_guard.h> 69*700637cbSDimitry Andric #include <__vector/vector.h> 70*700637cbSDimitry Andric #include <initializer_list> 71*700637cbSDimitry Andric 72*700637cbSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 73*700637cbSDimitry Andric # pragma GCC system_header 74*700637cbSDimitry Andric #endif 75*700637cbSDimitry Andric 76*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS 77*700637cbSDimitry Andric #include <__undef_macros> 78*700637cbSDimitry Andric 79*700637cbSDimitry Andric #if _LIBCPP_STD_VER >= 23 80*700637cbSDimitry Andric 81*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 82*700637cbSDimitry Andric 83*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>, class _KeyContainer = vector<_Key>> 84*700637cbSDimitry Andric class flat_multiset { 85*700637cbSDimitry Andric template <class, class, class> 86*700637cbSDimitry Andric friend class flat_multiset; 87*700637cbSDimitry Andric 88*700637cbSDimitry Andric friend __flat_set_utils; 89*700637cbSDimitry Andric 90*700637cbSDimitry Andric static_assert(is_same_v<_Key, typename _KeyContainer::value_type>); 91*700637cbSDimitry Andric static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container"); 92*700637cbSDimitry Andric 93*700637cbSDimitry Andric public: 94*700637cbSDimitry Andric // types 95*700637cbSDimitry Andric using key_type = _Key; 96*700637cbSDimitry Andric using value_type = _Key; 97*700637cbSDimitry Andric using key_compare = __type_identity_t<_Compare>; 98*700637cbSDimitry Andric using value_compare = _Compare; 99*700637cbSDimitry Andric using reference = value_type&; 100*700637cbSDimitry Andric using const_reference = const value_type&; 101*700637cbSDimitry Andric using size_type = typename _KeyContainer::size_type; 102*700637cbSDimitry Andric using difference_type = typename _KeyContainer::difference_type; 103*700637cbSDimitry Andric using iterator = __ra_iterator<flat_multiset, typename _KeyContainer::const_iterator>; 104*700637cbSDimitry Andric using const_iterator = iterator; 105*700637cbSDimitry Andric using reverse_iterator = std::reverse_iterator<iterator>; 106*700637cbSDimitry Andric using const_reverse_iterator = std::reverse_iterator<const_iterator>; 107*700637cbSDimitry Andric using container_type = _KeyContainer; 108*700637cbSDimitry Andric 109*700637cbSDimitry Andric public: 110*700637cbSDimitry Andric // [flat.multiset.cons], constructors flat_multiset()111*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && 112*700637cbSDimitry Andric is_nothrow_default_constructible_v<_Compare>) 113*700637cbSDimitry Andric : __keys_(), __compare_() {} 114*700637cbSDimitry Andric 115*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default; 116*700637cbSDimitry Andric 117*700637cbSDimitry Andric // The copy/move constructors are not specified in the spec, which means they should be defaulted. 118*700637cbSDimitry Andric // However, the move constructor can potentially leave a moved-from object in an inconsistent 119*700637cbSDimitry Andric // state if an exception is thrown. flat_multiset(flat_multiset && __other)120*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept( 121*700637cbSDimitry Andric is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>) 122*700637cbSDimitry Andric # if _LIBCPP_HAS_EXCEPTIONS 123*700637cbSDimitry Andric try 124*700637cbSDimitry Andric # endif // _LIBCPP_HAS_EXCEPTIONS 125*700637cbSDimitry Andric : __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) { 126*700637cbSDimitry Andric __other.clear(); 127*700637cbSDimitry Andric # if _LIBCPP_HAS_EXCEPTIONS 128*700637cbSDimitry Andric } catch (...) { 129*700637cbSDimitry Andric __other.clear(); 130*700637cbSDimitry Andric // gcc does not like the `throw` keyword in a conditionally noexcept function 131*700637cbSDimitry Andric if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) { 132*700637cbSDimitry Andric throw; 133*700637cbSDimitry Andric } 134*700637cbSDimitry Andric # endif // _LIBCPP_HAS_EXCEPTIONS 135*700637cbSDimitry Andric } 136*700637cbSDimitry Andric flat_multiset(const key_compare & __comp)137*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {} 138*700637cbSDimitry Andric 139*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare()) __keys_(std::move (__keys))140*700637cbSDimitry Andric : __keys_(std::move(__keys)), __compare_(__comp) { 141*700637cbSDimitry Andric ranges::sort(__keys_, __compare_); 142*700637cbSDimitry Andric } 143*700637cbSDimitry Andric 144*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 145*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare()) __keys_(std::move (__keys))146*700637cbSDimitry Andric : __keys_(std::move(__keys)), __compare_(__comp) { 147*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 148*700637cbSDimitry Andric } 149*700637cbSDimitry Andric 150*700637cbSDimitry Andric template <class _InputIterator> 151*700637cbSDimitry Andric requires __has_input_iterator_category<_InputIterator>::value 152*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 153*700637cbSDimitry Andric flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) __keys_()154*700637cbSDimitry Andric : __keys_(), __compare_(__comp) { 155*700637cbSDimitry Andric insert(__first, __last); 156*700637cbSDimitry Andric } 157*700637cbSDimitry Andric 158*700637cbSDimitry Andric template <class _InputIterator> 159*700637cbSDimitry Andric requires __has_input_iterator_category<_InputIterator>::value 160*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset( 161*700637cbSDimitry Andric sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) __keys_(__first,__last)162*700637cbSDimitry Andric : __keys_(__first, __last), __compare_(__comp) { 163*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 164*700637cbSDimitry Andric } 165*700637cbSDimitry Andric 166*700637cbSDimitry Andric template <_ContainerCompatibleRange<value_type> _Range> flat_multiset(from_range_t __fr,_Range && __rg)167*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg) 168*700637cbSDimitry Andric : flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {} 169*700637cbSDimitry Andric 170*700637cbSDimitry Andric template <_ContainerCompatibleRange<value_type> _Range> flat_multiset(from_range_t,_Range && __rg,const key_compare & __comp)171*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) { 172*700637cbSDimitry Andric insert_range(std::forward<_Range>(__rg)); 173*700637cbSDimitry Andric } 174*700637cbSDimitry Andric 175*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare()) 176*700637cbSDimitry Andric : flat_multiset(__il.begin(), __il.end(), __comp) {} 177*700637cbSDimitry Andric 178*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 179*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare()) 180*700637cbSDimitry Andric : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {} 181*700637cbSDimitry Andric 182*700637cbSDimitry Andric template <class _Allocator> 183*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(const _Allocator & __alloc)184*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc) 185*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {} 186*700637cbSDimitry Andric 187*700637cbSDimitry Andric template <class _Allocator> 188*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(const key_compare & __comp,const _Allocator & __alloc)189*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc) 190*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {} 191*700637cbSDimitry Andric 192*700637cbSDimitry Andric template <class _Allocator> 193*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(const container_type & __keys,const _Allocator & __alloc)194*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc) 195*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() { 196*700637cbSDimitry Andric ranges::sort(__keys_, __compare_); 197*700637cbSDimitry Andric } 198*700637cbSDimitry Andric 199*700637cbSDimitry Andric template <class _Allocator> 200*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value 201*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type & __keys,const key_compare & __comp,const _Allocator & __alloc)202*700637cbSDimitry Andric flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) 203*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) { 204*700637cbSDimitry Andric ranges::sort(__keys_, __compare_); 205*700637cbSDimitry Andric } 206*700637cbSDimitry Andric 207*700637cbSDimitry Andric template <class _Allocator> 208*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(sorted_equivalent_t,const container_type & __keys,const _Allocator & __alloc)209*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc) 210*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() { 211*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 212*700637cbSDimitry Andric } 213*700637cbSDimitry Andric 214*700637cbSDimitry Andric template <class _Allocator> 215*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value 216*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t,const container_type & __keys,const key_compare & __comp,const _Allocator & __alloc)217*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) 218*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) { 219*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 220*700637cbSDimitry Andric } 221*700637cbSDimitry Andric 222*700637cbSDimitry Andric template <class _Allocator> 223*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(const flat_multiset & __other,const _Allocator & __alloc)224*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc) 225*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)), 226*700637cbSDimitry Andric __compare_(__other.__compare_) {} 227*700637cbSDimitry Andric 228*700637cbSDimitry Andric template <class _Allocator> 229*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(flat_multiset && __other,const _Allocator & __alloc)230*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc) 231*700637cbSDimitry Andric # if _LIBCPP_HAS_EXCEPTIONS 232*700637cbSDimitry Andric try 233*700637cbSDimitry Andric # endif // _LIBCPP_HAS_EXCEPTIONS 234*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, std::move(__other.__keys_))), 235*700637cbSDimitry Andric __compare_(std::move(__other.__compare_)) { 236*700637cbSDimitry Andric __other.clear(); 237*700637cbSDimitry Andric # if _LIBCPP_HAS_EXCEPTIONS 238*700637cbSDimitry Andric } catch (...) { 239*700637cbSDimitry Andric __other.clear(); 240*700637cbSDimitry Andric throw; 241*700637cbSDimitry Andric # endif // _LIBCPP_HAS_EXCEPTIONS 242*700637cbSDimitry Andric } 243*700637cbSDimitry Andric 244*700637cbSDimitry Andric template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)245*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) 246*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) 247*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() { 248*700637cbSDimitry Andric insert(__first, __last); 249*700637cbSDimitry Andric } 250*700637cbSDimitry Andric 251*700637cbSDimitry Andric template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)252*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) 253*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 254*700637cbSDimitry Andric flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) 255*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) { 256*700637cbSDimitry Andric insert(__first, __last); 257*700637cbSDimitry Andric } 258*700637cbSDimitry Andric 259*700637cbSDimitry Andric template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)260*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) 261*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 262*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) 263*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() { 264*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 265*700637cbSDimitry Andric } 266*700637cbSDimitry Andric 267*700637cbSDimitry Andric template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)268*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) 269*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI 270*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, 271*700637cbSDimitry Andric _InputIterator __first, 272*700637cbSDimitry Andric _InputIterator __last, 273*700637cbSDimitry Andric const key_compare& __comp, 274*700637cbSDimitry Andric const _Allocator& __alloc) 275*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) { 276*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); 277*700637cbSDimitry Andric } 278*700637cbSDimitry Andric 279*700637cbSDimitry Andric template <_ContainerCompatibleRange<value_type> _Range, class _Allocator> 280*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(from_range_t,_Range && __rg,const _Allocator & __alloc)281*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc) 282*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() { 283*700637cbSDimitry Andric insert_range(std::forward<_Range>(__rg)); 284*700637cbSDimitry Andric } 285*700637cbSDimitry Andric 286*700637cbSDimitry Andric template <_ContainerCompatibleRange<value_type> _Range, class _Allocator> 287*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(from_range_t,_Range && __rg,const key_compare & __comp,const _Allocator & __alloc)288*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) 289*700637cbSDimitry Andric : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) { 290*700637cbSDimitry Andric insert_range(std::forward<_Range>(__rg)); 291*700637cbSDimitry Andric } 292*700637cbSDimitry Andric 293*700637cbSDimitry Andric template <class _Allocator> 294*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(initializer_list<value_type> __il,const _Allocator & __alloc)295*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc) 296*700637cbSDimitry Andric : flat_multiset(__il.begin(), __il.end(), __alloc) {} 297*700637cbSDimitry Andric 298*700637cbSDimitry Andric template <class _Allocator> 299*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value 300*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)301*700637cbSDimitry Andric flat_multiset(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc) 302*700637cbSDimitry Andric : flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {} 303*700637cbSDimitry Andric 304*700637cbSDimitry Andric template <class _Allocator> 305*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(sorted_equivalent_t,initializer_list<value_type> __il,const _Allocator & __alloc)306*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc) 307*700637cbSDimitry Andric : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {} 308*700637cbSDimitry Andric 309*700637cbSDimitry Andric template <class _Allocator> 310*700637cbSDimitry Andric requires uses_allocator<container_type, _Allocator>::value flat_multiset(sorted_equivalent_t,initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)311*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset( 312*700637cbSDimitry Andric sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc) 313*700637cbSDimitry Andric : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {} 314*700637cbSDimitry Andric 315*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list<value_type> __il) { 316*700637cbSDimitry Andric clear(); 317*700637cbSDimitry Andric insert(__il); 318*700637cbSDimitry Andric return *this; 319*700637cbSDimitry Andric } 320*700637cbSDimitry Andric 321*700637cbSDimitry Andric // copy/move assignment are not specified in the spec (defaulted) 322*700637cbSDimitry Andric // but move assignment can potentially leave moved from object in an inconsistent 323*700637cbSDimitry Andric // state if an exception is thrown 324*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default; 325*700637cbSDimitry Andric noexcept(is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>)326*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept( 327*700637cbSDimitry Andric is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) { 328*700637cbSDimitry Andric auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); 329*700637cbSDimitry Andric auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); 330*700637cbSDimitry Andric __keys_ = std::move(__other.__keys_); 331*700637cbSDimitry Andric __compare_ = std::move(__other.__compare_); 332*700637cbSDimitry Andric __clear_self_guard.__complete(); 333*700637cbSDimitry Andric return *this; 334*700637cbSDimitry Andric } 335*700637cbSDimitry Andric 336*700637cbSDimitry Andric // iterators begin()337*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); } begin()338*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); } end()339*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); } end()340*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); } 341*700637cbSDimitry Andric rbegin()342*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } rbegin()343*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } rend()344*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } rend()345*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } 346*700637cbSDimitry Andric cbegin()347*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } cend()348*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } crbegin()349*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } crend()350*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } 351*700637cbSDimitry Andric 352*700637cbSDimitry Andric // capacity empty()353*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); } size()354*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); } max_size()355*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); } 356*700637cbSDimitry Andric 357*700637cbSDimitry Andric // [flat.multiset.modifiers], modifiers 358*700637cbSDimitry Andric template <class... _Args> 359*700637cbSDimitry Andric requires is_constructible_v<value_type, _Args...> emplace(_Args &&...__args)360*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { 361*700637cbSDimitry Andric if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) { 362*700637cbSDimitry Andric return __emplace(std::forward<_Args>(__args)...); 363*700637cbSDimitry Andric } else { 364*700637cbSDimitry Andric return __emplace(_Key(std::forward<_Args>(__args)...)); 365*700637cbSDimitry Andric } 366*700637cbSDimitry Andric } 367*700637cbSDimitry Andric 368*700637cbSDimitry Andric template <class... _Args> 369*700637cbSDimitry Andric requires is_constructible_v<value_type, _Args...> emplace_hint(const_iterator __hint,_Args &&...__args)370*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { 371*700637cbSDimitry Andric if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) { 372*700637cbSDimitry Andric return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...); 373*700637cbSDimitry Andric } else { 374*700637cbSDimitry Andric return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...)); 375*700637cbSDimitry Andric } 376*700637cbSDimitry Andric } 377*700637cbSDimitry Andric insert(const value_type & __x)378*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); } 379*700637cbSDimitry Andric insert(value_type && __x)380*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); } 381*700637cbSDimitry Andric insert(const_iterator __hint,const value_type & __x)382*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { 383*700637cbSDimitry Andric return emplace_hint(__hint, __x); 384*700637cbSDimitry Andric } 385*700637cbSDimitry Andric insert(const_iterator __hint,value_type && __x)386*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { 387*700637cbSDimitry Andric return emplace_hint(__hint, std::move(__x)); 388*700637cbSDimitry Andric } 389*700637cbSDimitry Andric 390*700637cbSDimitry Andric template <class _InputIterator> 391*700637cbSDimitry Andric requires __has_input_iterator_category<_InputIterator>::value insert(_InputIterator __first,_InputIterator __last)392*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { 393*700637cbSDimitry Andric if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { 394*700637cbSDimitry Andric __reserve(__last - __first); 395*700637cbSDimitry Andric } 396*700637cbSDimitry Andric __append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last)); 397*700637cbSDimitry Andric } 398*700637cbSDimitry Andric 399*700637cbSDimitry Andric template <class _InputIterator> 400*700637cbSDimitry Andric requires __has_input_iterator_category<_InputIterator>::value insert(sorted_equivalent_t,_InputIterator __first,_InputIterator __last)401*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { 402*700637cbSDimitry Andric if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { 403*700637cbSDimitry Andric __reserve(__last - __first); 404*700637cbSDimitry Andric } 405*700637cbSDimitry Andric 406*700637cbSDimitry Andric __append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last)); 407*700637cbSDimitry Andric } 408*700637cbSDimitry Andric 409*700637cbSDimitry Andric template <_ContainerCompatibleRange<value_type> _Range> insert_range(_Range && __range)410*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { 411*700637cbSDimitry Andric if constexpr (ranges::sized_range<_Range>) { 412*700637cbSDimitry Andric __reserve(ranges::size(__range)); 413*700637cbSDimitry Andric } 414*700637cbSDimitry Andric 415*700637cbSDimitry Andric __append_sort_merge</*WasSorted = */ false>(std::forward<_Range>(__range)); 416*700637cbSDimitry Andric } 417*700637cbSDimitry Andric insert(initializer_list<value_type> __il)418*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); } 419*700637cbSDimitry Andric insert(sorted_equivalent_t,initializer_list<value_type> __il)420*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) { 421*700637cbSDimitry Andric insert(sorted_equivalent, __il.begin(), __il.end()); 422*700637cbSDimitry Andric } 423*700637cbSDimitry Andric extract()424*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI container_type extract() && { 425*700637cbSDimitry Andric auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); 426*700637cbSDimitry Andric auto __ret = std::move(__keys_); 427*700637cbSDimitry Andric return __ret; 428*700637cbSDimitry Andric } 429*700637cbSDimitry Andric replace(container_type && __keys)430*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) { 431*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted"); 432*700637cbSDimitry Andric auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); 433*700637cbSDimitry Andric __keys_ = std::move(__keys); 434*700637cbSDimitry Andric __guard.__complete(); 435*700637cbSDimitry Andric } 436*700637cbSDimitry Andric erase(iterator __position)437*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { 438*700637cbSDimitry Andric auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); 439*700637cbSDimitry Andric auto __key_iter = __keys_.erase(__position.__base()); 440*700637cbSDimitry Andric __on_failure.__complete(); 441*700637cbSDimitry Andric return iterator(__key_iter); 442*700637cbSDimitry Andric } 443*700637cbSDimitry Andric 444*700637cbSDimitry Andric // The following overload is the same as the iterator overload 445*700637cbSDimitry Andric // iterator erase(const_iterator __position); 446*700637cbSDimitry Andric erase(const key_type & __x)447*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { 448*700637cbSDimitry Andric auto [__first, __last] = equal_range(__x); 449*700637cbSDimitry Andric auto __res = __last - __first; 450*700637cbSDimitry Andric erase(__first, __last); 451*700637cbSDimitry Andric return __res; 452*700637cbSDimitry Andric } 453*700637cbSDimitry Andric 454*700637cbSDimitry Andric template <class _Kp> 455*700637cbSDimitry Andric requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> && 456*700637cbSDimitry Andric !is_convertible_v<_Kp &&, const_iterator>) erase(_Kp && __x)457*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { 458*700637cbSDimitry Andric auto [__first, __last] = equal_range(__x); 459*700637cbSDimitry Andric auto __res = __last - __first; 460*700637cbSDimitry Andric erase(__first, __last); 461*700637cbSDimitry Andric return __res; 462*700637cbSDimitry Andric } 463*700637cbSDimitry Andric erase(const_iterator __first,const_iterator __last)464*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { 465*700637cbSDimitry Andric auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); 466*700637cbSDimitry Andric auto __key_it = __keys_.erase(__first.__base(), __last.__base()); 467*700637cbSDimitry Andric __on_failure.__complete(); 468*700637cbSDimitry Andric return iterator(std::move(__key_it)); 469*700637cbSDimitry Andric } 470*700637cbSDimitry Andric swap(flat_multiset & __y)471*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept { 472*700637cbSDimitry Andric // warning: The spec has unconditional noexcept, which means that 473*700637cbSDimitry Andric // if any of the following functions throw an exception, 474*700637cbSDimitry Andric // std::terminate will be called 475*700637cbSDimitry Andric // This is discussed in P3567, which hasn't been voted on yet. 476*700637cbSDimitry Andric ranges::swap(__compare_, __y.__compare_); 477*700637cbSDimitry Andric ranges::swap(__keys_, __y.__keys_); 478*700637cbSDimitry Andric } 479*700637cbSDimitry Andric clear()480*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); } 481*700637cbSDimitry Andric 482*700637cbSDimitry Andric // observers key_comp()483*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } value_comp()484*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; } 485*700637cbSDimitry Andric 486*700637cbSDimitry Andric // map operations find(const key_type & __x)487*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } 488*700637cbSDimitry Andric find(const key_type & __x)489*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } 490*700637cbSDimitry Andric 491*700637cbSDimitry Andric template <class _Kp> 492*700637cbSDimitry Andric requires __is_transparent_v<_Compare> find(const _Kp & __x)493*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { 494*700637cbSDimitry Andric return __find_impl(*this, __x); 495*700637cbSDimitry Andric } 496*700637cbSDimitry Andric 497*700637cbSDimitry Andric template <class _Kp> 498*700637cbSDimitry Andric requires __is_transparent_v<_Compare> find(const _Kp & __x)499*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { 500*700637cbSDimitry Andric return __find_impl(*this, __x); 501*700637cbSDimitry Andric } 502*700637cbSDimitry Andric count(const key_type & __x)503*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { 504*700637cbSDimitry Andric auto [__first, __last] = equal_range(__x); 505*700637cbSDimitry Andric return __last - __first; 506*700637cbSDimitry Andric } 507*700637cbSDimitry Andric 508*700637cbSDimitry Andric template <class _Kp> 509*700637cbSDimitry Andric requires __is_transparent_v<_Compare> count(const _Kp & __x)510*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { 511*700637cbSDimitry Andric auto [__first, __last] = equal_range(__x); 512*700637cbSDimitry Andric return __last - __first; 513*700637cbSDimitry Andric } 514*700637cbSDimitry Andric contains(const key_type & __x)515*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } 516*700637cbSDimitry Andric 517*700637cbSDimitry Andric template <class _Kp> 518*700637cbSDimitry Andric requires __is_transparent_v<_Compare> contains(const _Kp & __x)519*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { 520*700637cbSDimitry Andric return find(__x) != end(); 521*700637cbSDimitry Andric } 522*700637cbSDimitry Andric lower_bound(const key_type & __x)523*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { 524*700637cbSDimitry Andric const auto& __keys = __keys_; 525*700637cbSDimitry Andric return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); 526*700637cbSDimitry Andric } 527*700637cbSDimitry Andric lower_bound(const key_type & __x)528*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { 529*700637cbSDimitry Andric return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); 530*700637cbSDimitry Andric } 531*700637cbSDimitry Andric 532*700637cbSDimitry Andric template <class _Kp> 533*700637cbSDimitry Andric requires __is_transparent_v<_Compare> lower_bound(const _Kp & __x)534*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { 535*700637cbSDimitry Andric const auto& __keys = __keys_; 536*700637cbSDimitry Andric return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); 537*700637cbSDimitry Andric } 538*700637cbSDimitry Andric 539*700637cbSDimitry Andric template <class _Kp> 540*700637cbSDimitry Andric requires __is_transparent_v<_Compare> lower_bound(const _Kp & __x)541*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { 542*700637cbSDimitry Andric return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); 543*700637cbSDimitry Andric } 544*700637cbSDimitry Andric upper_bound(const key_type & __x)545*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { 546*700637cbSDimitry Andric const auto& __keys = __keys_; 547*700637cbSDimitry Andric return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); 548*700637cbSDimitry Andric } 549*700637cbSDimitry Andric upper_bound(const key_type & __x)550*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { 551*700637cbSDimitry Andric return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); 552*700637cbSDimitry Andric } 553*700637cbSDimitry Andric 554*700637cbSDimitry Andric template <class _Kp> 555*700637cbSDimitry Andric requires __is_transparent_v<_Compare> upper_bound(const _Kp & __x)556*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { 557*700637cbSDimitry Andric const auto& __keys = __keys_; 558*700637cbSDimitry Andric return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); 559*700637cbSDimitry Andric } 560*700637cbSDimitry Andric 561*700637cbSDimitry Andric template <class _Kp> 562*700637cbSDimitry Andric requires __is_transparent_v<_Compare> upper_bound(const _Kp & __x)563*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { 564*700637cbSDimitry Andric return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); 565*700637cbSDimitry Andric } 566*700637cbSDimitry Andric equal_range(const key_type & __x)567*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) { 568*700637cbSDimitry Andric return __equal_range_impl(*this, __x); 569*700637cbSDimitry Andric } 570*700637cbSDimitry Andric equal_range(const key_type & __x)571*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const { 572*700637cbSDimitry Andric return __equal_range_impl(*this, __x); 573*700637cbSDimitry Andric } 574*700637cbSDimitry Andric 575*700637cbSDimitry Andric template <class _Kp> 576*700637cbSDimitry Andric requires __is_transparent_v<_Compare> equal_range(const _Kp & __x)577*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) { 578*700637cbSDimitry Andric return __equal_range_impl(*this, __x); 579*700637cbSDimitry Andric } 580*700637cbSDimitry Andric template <class _Kp> 581*700637cbSDimitry Andric requires __is_transparent_v<_Compare> equal_range(const _Kp & __x)582*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const { 583*700637cbSDimitry Andric return __equal_range_impl(*this, __x); 584*700637cbSDimitry Andric } 585*700637cbSDimitry Andric 586*700637cbSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) { 587*700637cbSDimitry Andric return ranges::equal(__x, __y); 588*700637cbSDimitry Andric } 589*700637cbSDimitry Andric 590*700637cbSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) { 591*700637cbSDimitry Andric return std::lexicographical_compare_three_way( 592*700637cbSDimitry Andric __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); 593*700637cbSDimitry Andric } 594*700637cbSDimitry Andric swap(flat_multiset & __x,flat_multiset & __y)595*700637cbSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); } 596*700637cbSDimitry Andric 597*700637cbSDimitry Andric private: 598*700637cbSDimitry Andric template <bool _WasSorted, class... _Args> __append_sort_merge(_Args &&...__args)599*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) { 600*700637cbSDimitry Andric auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); 601*700637cbSDimitry Andric size_type __old_size = size(); 602*700637cbSDimitry Andric __flat_set_utils::__append(*this, std::forward<_Args>(__args)...); 603*700637cbSDimitry Andric if constexpr (!_WasSorted) { 604*700637cbSDimitry Andric ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_); 605*700637cbSDimitry Andric } else { 606*700637cbSDimitry Andric _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT( 607*700637cbSDimitry Andric ranges::is_sorted(__keys_ | ranges::views::drop(__old_size)), "Key container is not sorted"); 608*700637cbSDimitry Andric } 609*700637cbSDimitry Andric ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_); 610*700637cbSDimitry Andric __on_failure.__complete(); 611*700637cbSDimitry Andric } 612*700637cbSDimitry Andric 613*700637cbSDimitry Andric template <class _Kp> __emplace(_Kp && __key)614*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) { 615*700637cbSDimitry Andric auto __it = upper_bound(__key); 616*700637cbSDimitry Andric return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)); 617*700637cbSDimitry Andric } 618*700637cbSDimitry Andric 619*700637cbSDimitry Andric template <class _Kp> __emplace_hint(const_iterator __hint,_Kp && __key)620*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { 621*700637cbSDimitry Andric auto __prev_larger = __hint != cbegin() && __compare_(__key, *std::prev(__hint)); 622*700637cbSDimitry Andric auto __next_smaller = __hint != cend() && __compare_(*__hint, __key); 623*700637cbSDimitry Andric 624*700637cbSDimitry Andric if (!__prev_larger && !__next_smaller) [[likely]] { 625*700637cbSDimitry Andric // hint correct, just use exact hint iterator 626*700637cbSDimitry Andric } else if (__prev_larger && !__next_smaller) { 627*700637cbSDimitry Andric // the hint position is more to the right than the key should have been. 628*700637cbSDimitry Andric // we want to emplace the element to a position as right as possible 629*700637cbSDimitry Andric // e.g. Insert new element "2" in the following range 630*700637cbSDimitry Andric // 1, 1, 2, 2, 2, 3, 4, 6 631*700637cbSDimitry Andric // ^ 632*700637cbSDimitry Andric // | 633*700637cbSDimitry Andric // hint 634*700637cbSDimitry Andric // We want to insert "2" after the last existing "2" 635*700637cbSDimitry Andric __hint = std::upper_bound(begin(), __hint, __key, __compare_); 636*700637cbSDimitry Andric } else { 637*700637cbSDimitry Andric _LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multiset is not sorted"); 638*700637cbSDimitry Andric 639*700637cbSDimitry Andric // the hint position is more to the left than the key should have been. 640*700637cbSDimitry Andric // we want to emplace the element to a position as left as possible 641*700637cbSDimitry Andric // 1, 1, 2, 2, 2, 3, 4, 6 642*700637cbSDimitry Andric // ^ 643*700637cbSDimitry Andric // | 644*700637cbSDimitry Andric // hint 645*700637cbSDimitry Andric // We want to insert "2" before the first existing "2" 646*700637cbSDimitry Andric __hint = std::lower_bound(__hint, end(), __key, __compare_); 647*700637cbSDimitry Andric } 648*700637cbSDimitry Andric return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key)); 649*700637cbSDimitry Andric } 650*700637cbSDimitry Andric 651*700637cbSDimitry Andric template <class _Self, class _Kp> __find_impl(_Self && __self,const _Kp & __key)652*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { 653*700637cbSDimitry Andric auto __it = __self.lower_bound(__key); 654*700637cbSDimitry Andric auto __last = __self.end(); 655*700637cbSDimitry Andric if (__it == __last || __self.__compare_(__key, *__it)) { 656*700637cbSDimitry Andric return __last; 657*700637cbSDimitry Andric } 658*700637cbSDimitry Andric return __it; 659*700637cbSDimitry Andric } 660*700637cbSDimitry Andric 661*700637cbSDimitry Andric template <class _Self, class _Kp> __equal_range_impl(_Self && __self,const _Kp & __key)662*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { 663*700637cbSDimitry Andric using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>; 664*700637cbSDimitry Andric auto [__key_first, __key_last] = 665*700637cbSDimitry Andric std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_); 666*700637cbSDimitry Andric return std::make_pair(__iter(__key_first), __iter(__key_last)); 667*700637cbSDimitry Andric } 668*700637cbSDimitry Andric __reserve(size_t __size)669*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { 670*700637cbSDimitry Andric if constexpr (__container_traits<_KeyContainer>::__reservable) { 671*700637cbSDimitry Andric __keys_.reserve(__size); 672*700637cbSDimitry Andric } 673*700637cbSDimitry Andric } 674*700637cbSDimitry Andric 675*700637cbSDimitry Andric template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate> 676*700637cbSDimitry Andric friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type 677*700637cbSDimitry Andric erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate); 678*700637cbSDimitry Andric 679*700637cbSDimitry Andric _KeyContainer __keys_; 680*700637cbSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; 681*700637cbSDimitry Andric 682*700637cbSDimitry Andric struct __key_equiv { __key_equiv__key_equiv683*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} operator__key_equiv684*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { 685*700637cbSDimitry Andric return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); 686*700637cbSDimitry Andric } 687*700637cbSDimitry Andric key_compare __comp_; 688*700637cbSDimitry Andric }; 689*700637cbSDimitry Andric }; 690*700637cbSDimitry Andric 691*700637cbSDimitry Andric template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>> 692*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && 693*700637cbSDimitry Andric is_invocable_v<const _Compare&, 694*700637cbSDimitry Andric const typename _KeyContainer::value_type&, 695*700637cbSDimitry Andric const typename _KeyContainer::value_type&>) 696*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Compare = _Compare()) 697*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; 698*700637cbSDimitry Andric 699*700637cbSDimitry Andric template <class _KeyContainer, class _Allocator> 700*700637cbSDimitry Andric requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) 701*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Allocator) 702*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>; 703*700637cbSDimitry Andric 704*700637cbSDimitry Andric template <class _KeyContainer, class _Compare, class _Allocator> 705*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && 706*700637cbSDimitry Andric uses_allocator_v<_KeyContainer, _Allocator> && 707*700637cbSDimitry Andric is_invocable_v<const _Compare&, 708*700637cbSDimitry Andric const typename _KeyContainer::value_type&, 709*700637cbSDimitry Andric const typename _KeyContainer::value_type&>) 710*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Compare, _Allocator) 711*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; 712*700637cbSDimitry Andric 713*700637cbSDimitry Andric template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>> 714*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && 715*700637cbSDimitry Andric is_invocable_v<const _Compare&, 716*700637cbSDimitry Andric const typename _KeyContainer::value_type&, 717*700637cbSDimitry Andric const typename _KeyContainer::value_type&>) 718*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare()) 719*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; 720*700637cbSDimitry Andric 721*700637cbSDimitry Andric template <class _KeyContainer, class _Allocator> 722*700637cbSDimitry Andric requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value) 723*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Allocator) 724*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>; 725*700637cbSDimitry Andric 726*700637cbSDimitry Andric template <class _KeyContainer, class _Compare, class _Allocator> 727*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value && 728*700637cbSDimitry Andric uses_allocator_v<_KeyContainer, _Allocator> && 729*700637cbSDimitry Andric is_invocable_v<const _Compare&, 730*700637cbSDimitry Andric const typename _KeyContainer::value_type&, 731*700637cbSDimitry Andric const typename _KeyContainer::value_type&>) 732*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Allocator) 733*700637cbSDimitry Andric -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; 734*700637cbSDimitry Andric 735*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>> 736*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) 737*700637cbSDimitry Andric flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare()) 738*700637cbSDimitry Andric -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>; 739*700637cbSDimitry Andric 740*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>> 741*700637cbSDimitry Andric requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value) 742*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare()) 743*700637cbSDimitry Andric -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>; 744*700637cbSDimitry Andric 745*700637cbSDimitry Andric template <ranges::input_range _Range, 746*700637cbSDimitry Andric class _Compare = less<ranges::range_value_t<_Range>>, 747*700637cbSDimitry Andric class _Allocator = allocator<ranges::range_value_t<_Range>>, 748*700637cbSDimitry Andric class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>> 749*700637cbSDimitry Andric flat_multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multiset< 750*700637cbSDimitry Andric ranges::range_value_t<_Range>, 751*700637cbSDimitry Andric _Compare, 752*700637cbSDimitry Andric vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; 753*700637cbSDimitry Andric 754*700637cbSDimitry Andric template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>> 755*700637cbSDimitry Andric flat_multiset(from_range_t, _Range&&, _Allocator) -> flat_multiset< 756*700637cbSDimitry Andric ranges::range_value_t<_Range>, 757*700637cbSDimitry Andric less<ranges::range_value_t<_Range>>, 758*700637cbSDimitry Andric vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>; 759*700637cbSDimitry Andric 760*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>> 761*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value) 762*700637cbSDimitry Andric flat_multiset(initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>; 763*700637cbSDimitry Andric 764*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>> 765*700637cbSDimitry Andric requires(!__is_allocator<_Compare>::value) 766*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>; 767*700637cbSDimitry Andric 768*700637cbSDimitry Andric template <class _Key, class _Compare, class _KeyContainer, class _Allocator> 769*700637cbSDimitry Andric struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Allocator> 770*700637cbSDimitry Andric : bool_constant<uses_allocator_v<_KeyContainer, _Allocator> > {}; 771*700637cbSDimitry Andric 772*700637cbSDimitry Andric template <class _Key, class _Compare, class _KeyContainer, class _Predicate> 773*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type 774*700637cbSDimitry Andric erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) { 775*700637cbSDimitry Andric auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); }); 776*700637cbSDimitry Andric auto __it = 777*700637cbSDimitry Andric std::remove_if(__flat_multiset.__keys_.begin(), __flat_multiset.__keys_.end(), [&](const auto& __e) -> bool { 778*700637cbSDimitry Andric return static_cast<bool>(__pred(__e)); 779*700637cbSDimitry Andric }); 780*700637cbSDimitry Andric auto __res = __flat_multiset.__keys_.end() - __it; 781*700637cbSDimitry Andric __flat_multiset.__keys_.erase(__it, __flat_multiset.__keys_.end()); 782*700637cbSDimitry Andric __guard.__complete(); 783*700637cbSDimitry Andric return __res; 784*700637cbSDimitry Andric } 785*700637cbSDimitry Andric 786*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD 787*700637cbSDimitry Andric 788*700637cbSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 789*700637cbSDimitry Andric 790*700637cbSDimitry Andric _LIBCPP_POP_MACROS 791*700637cbSDimitry Andric 792*700637cbSDimitry Andric #endif // _LIBCPP___FLAT_MAP_FLAT_MULTISET_H 793