Path: blob/main/contrib/llvm-project/libcxx/include/__flat_set/flat_multiset.h
213766 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___FLAT_MAP_FLAT_MULTISET_H10#define _LIBCPP___FLAT_MAP_FLAT_MULTISET_H1112#include <__algorithm/equal_range.h>13#include <__algorithm/lexicographical_compare_three_way.h>14#include <__algorithm/lower_bound.h>15#include <__algorithm/min.h>16#include <__algorithm/ranges_equal.h>17#include <__algorithm/ranges_inplace_merge.h>18#include <__algorithm/ranges_is_sorted.h>19#include <__algorithm/ranges_sort.h>20#include <__algorithm/ranges_unique.h>21#include <__algorithm/remove_if.h>22#include <__algorithm/upper_bound.h>23#include <__assert>24#include <__compare/synth_three_way.h>25#include <__concepts/convertible_to.h>26#include <__concepts/swappable.h>27#include <__config>28#include <__cstddef/byte.h>29#include <__cstddef/ptrdiff_t.h>30#include <__flat_map/key_value_iterator.h>31#include <__flat_map/sorted_equivalent.h>32#include <__flat_set/ra_iterator.h>33#include <__flat_set/utils.h>34#include <__functional/invoke.h>35#include <__functional/is_transparent.h>36#include <__functional/operations.h>37#include <__fwd/vector.h>38#include <__iterator/concepts.h>39#include <__iterator/distance.h>40#include <__iterator/iterator_traits.h>41#include <__iterator/prev.h>42#include <__iterator/ranges_iterator_traits.h>43#include <__iterator/reverse_iterator.h>44#include <__memory/allocator_traits.h>45#include <__memory/uses_allocator.h>46#include <__memory/uses_allocator_construction.h>47#include <__ranges/access.h>48#include <__ranges/concepts.h>49#include <__ranges/container_compatible_range.h>50#include <__ranges/drop_view.h>51#include <__ranges/from_range.h>52#include <__ranges/ref_view.h>53#include <__ranges/size.h>54#include <__ranges/subrange.h>55#include <__ranges/zip_view.h>56#include <__type_traits/conjunction.h>57#include <__type_traits/container_traits.h>58#include <__type_traits/invoke.h>59#include <__type_traits/is_allocator.h>60#include <__type_traits/is_nothrow_constructible.h>61#include <__type_traits/is_same.h>62#include <__type_traits/maybe_const.h>63#include <__utility/as_const.h>64#include <__utility/exception_guard.h>65#include <__utility/move.h>66#include <__utility/pair.h>67#include <__utility/scope_guard.h>68#include <__vector/vector.h>69#include <initializer_list>7071#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)72# pragma GCC system_header73#endif7475_LIBCPP_PUSH_MACROS76#include <__undef_macros>7778#if _LIBCPP_STD_VER >= 237980_LIBCPP_BEGIN_NAMESPACE_STD8182template <class _Key, class _Compare = less<_Key>, class _KeyContainer = vector<_Key>>83class flat_multiset {84template <class, class, class>85friend class flat_multiset;8687friend __flat_set_utils;8889static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);90static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");9192public:93// types94using key_type = _Key;95using value_type = _Key;96using key_compare = __type_identity_t<_Compare>;97using value_compare = _Compare;98using reference = value_type&;99using const_reference = const value_type&;100using size_type = typename _KeyContainer::size_type;101using difference_type = typename _KeyContainer::difference_type;102using iterator = __ra_iterator<flat_multiset, typename _KeyContainer::const_iterator>;103using const_iterator = iterator;104using reverse_iterator = std::reverse_iterator<iterator>;105using const_reverse_iterator = std::reverse_iterator<const_iterator>;106using container_type = _KeyContainer;107108public:109// [flat.multiset.cons], constructors110_LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> &&111is_nothrow_default_constructible_v<_Compare>)112: __keys_(), __compare_() {}113114_LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default;115116// The copy/move constructors are not specified in the spec, which means they should be defaulted.117// However, the move constructor can potentially leave a moved-from object in an inconsistent118// state if an exception is thrown.119_LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept(120is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)121# if _LIBCPP_HAS_EXCEPTIONS122try123# endif // _LIBCPP_HAS_EXCEPTIONS124: __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) {125__other.clear();126# if _LIBCPP_HAS_EXCEPTIONS127} catch (...) {128__other.clear();129// gcc does not like the `throw` keyword in a conditionally noexcept function130if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) {131throw;132}133# endif // _LIBCPP_HAS_EXCEPTIONS134}135136_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {}137138_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare())139: __keys_(std::move(__keys)), __compare_(__comp) {140ranges::sort(__keys_, __compare_);141}142143_LIBCPP_HIDE_FROM_ABI144flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare())145: __keys_(std::move(__keys)), __compare_(__comp) {146_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");147}148149template <class _InputIterator>150requires __has_input_iterator_category<_InputIterator>::value151_LIBCPP_HIDE_FROM_ABI152flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())153: __keys_(), __compare_(__comp) {154insert(__first, __last);155}156157template <class _InputIterator>158requires __has_input_iterator_category<_InputIterator>::value159_LIBCPP_HIDE_FROM_ABI flat_multiset(160sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())161: __keys_(__first, __last), __compare_(__comp) {162_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");163}164165template <_ContainerCompatibleRange<value_type> _Range>166_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg)167: flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {}168169template <_ContainerCompatibleRange<value_type> _Range>170_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) {171insert_range(std::forward<_Range>(__rg));172}173174_LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare())175: flat_multiset(__il.begin(), __il.end(), __comp) {}176177_LIBCPP_HIDE_FROM_ABI178flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())179: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {}180181template <class _Allocator>182requires uses_allocator<container_type, _Allocator>::value183_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc)184: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {}185186template <class _Allocator>187requires uses_allocator<container_type, _Allocator>::value188_LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc)189: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {}190191template <class _Allocator>192requires uses_allocator<container_type, _Allocator>::value193_LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc)194: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {195ranges::sort(__keys_, __compare_);196}197198template <class _Allocator>199requires uses_allocator<container_type, _Allocator>::value200_LIBCPP_HIDE_FROM_ABI201flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)202: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {203ranges::sort(__keys_, __compare_);204}205206template <class _Allocator>207requires uses_allocator<container_type, _Allocator>::value208_LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc)209: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {210_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");211}212213template <class _Allocator>214requires uses_allocator<container_type, _Allocator>::value215_LIBCPP_HIDE_FROM_ABI216flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)217: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {218_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");219}220221template <class _Allocator>222requires uses_allocator<container_type, _Allocator>::value223_LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc)224: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)),225__compare_(__other.__compare_) {}226227template <class _Allocator>228requires uses_allocator<container_type, _Allocator>::value229_LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc)230# if _LIBCPP_HAS_EXCEPTIONS231try232# endif // _LIBCPP_HAS_EXCEPTIONS233: __keys_(std::make_obj_using_allocator<container_type>(__alloc, std::move(__other.__keys_))),234__compare_(std::move(__other.__compare_)) {235__other.clear();236# if _LIBCPP_HAS_EXCEPTIONS237} catch (...) {238__other.clear();239throw;240# endif // _LIBCPP_HAS_EXCEPTIONS241}242243template <class _InputIterator, class _Allocator>244requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)245_LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)246: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {247insert(__first, __last);248}249250template <class _InputIterator, class _Allocator>251requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)252_LIBCPP_HIDE_FROM_ABI253flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)254: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {255insert(__first, __last);256}257258template <class _InputIterator, class _Allocator>259requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)260_LIBCPP_HIDE_FROM_ABI261flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)262: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() {263_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");264}265266template <class _InputIterator, class _Allocator>267requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)268_LIBCPP_HIDE_FROM_ABI269flat_multiset(sorted_equivalent_t,270_InputIterator __first,271_InputIterator __last,272const key_compare& __comp,273const _Allocator& __alloc)274: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) {275_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");276}277278template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>279requires uses_allocator<container_type, _Allocator>::value280_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc)281: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {282insert_range(std::forward<_Range>(__rg));283}284285template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>286requires uses_allocator<container_type, _Allocator>::value287_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)288: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {289insert_range(std::forward<_Range>(__rg));290}291292template <class _Allocator>293requires uses_allocator<container_type, _Allocator>::value294_LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc)295: flat_multiset(__il.begin(), __il.end(), __alloc) {}296297template <class _Allocator>298requires uses_allocator<container_type, _Allocator>::value299_LIBCPP_HIDE_FROM_ABI300flat_multiset(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)301: flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {}302303template <class _Allocator>304requires uses_allocator<container_type, _Allocator>::value305_LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc)306: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {}307308template <class _Allocator>309requires uses_allocator<container_type, _Allocator>::value310_LIBCPP_HIDE_FROM_ABI flat_multiset(311sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)312: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {}313314_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list<value_type> __il) {315clear();316insert(__il);317return *this;318}319320// copy/move assignment are not specified in the spec (defaulted)321// but move assignment can potentially leave moved from object in an inconsistent322// state if an exception is thrown323_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default;324325_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept(326is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) {327auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });328auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });329__keys_ = std::move(__other.__keys_);330__compare_ = std::move(__other.__compare_);331__clear_self_guard.__complete();332return *this;333}334335// iterators336_LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); }337_LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); }338_LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); }339_LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); }340341_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }342_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }343_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }344_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }345346_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }347_LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }348_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }349_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }350351// capacity352[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); }353_LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); }354_LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); }355356// [flat.multiset.modifiers], modifiers357template <class... _Args>358requires is_constructible_v<value_type, _Args...>359_LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {360if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {361return __emplace(std::forward<_Args>(__args)...);362} else {363return __emplace(_Key(std::forward<_Args>(__args)...));364}365}366367template <class... _Args>368requires is_constructible_v<value_type, _Args...>369_LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {370if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {371return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...);372} else {373return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...));374}375}376377_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }378379_LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }380381_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {382return emplace_hint(__hint, __x);383}384385_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {386return emplace_hint(__hint, std::move(__x));387}388389template <class _InputIterator>390requires __has_input_iterator_category<_InputIterator>::value391_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {392if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {393__reserve(__last - __first);394}395__append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last));396}397398template <class _InputIterator>399requires __has_input_iterator_category<_InputIterator>::value400_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) {401if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {402__reserve(__last - __first);403}404405__append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last));406}407408template <_ContainerCompatibleRange<value_type> _Range>409_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {410if constexpr (ranges::sized_range<_Range>) {411__reserve(ranges::size(__range));412}413414__append_sort_merge</*WasSorted = */ false>(std::forward<_Range>(__range));415}416417_LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }418419_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) {420insert(sorted_equivalent, __il.begin(), __il.end());421}422423_LIBCPP_HIDE_FROM_ABI container_type extract() && {424auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });425auto __ret = std::move(__keys_);426return __ret;427}428429_LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) {430_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted");431auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });432__keys_ = std::move(__keys);433__guard.__complete();434}435436_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {437auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });438auto __key_iter = __keys_.erase(__position.__base());439__on_failure.__complete();440return iterator(__key_iter);441}442443// The following overload is the same as the iterator overload444// iterator erase(const_iterator __position);445446_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {447auto [__first, __last] = equal_range(__x);448auto __res = __last - __first;449erase(__first, __last);450return __res;451}452453template <class _Kp>454requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&455!is_convertible_v<_Kp &&, const_iterator>)456_LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {457auto [__first, __last] = equal_range(__x);458auto __res = __last - __first;459erase(__first, __last);460return __res;461}462463_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {464auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });465auto __key_it = __keys_.erase(__first.__base(), __last.__base());466__on_failure.__complete();467return iterator(std::move(__key_it));468}469470_LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept {471// warning: The spec has unconditional noexcept, which means that472// if any of the following functions throw an exception,473// std::terminate will be called474// This is discussed in P3567, which hasn't been voted on yet.475ranges::swap(__compare_, __y.__compare_);476ranges::swap(__keys_, __y.__keys_);477}478479_LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); }480481// observers482_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }483_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; }484485// map operations486_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }487488_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }489490template <class _Kp>491requires __is_transparent_v<_Compare>492_LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {493return __find_impl(*this, __x);494}495496template <class _Kp>497requires __is_transparent_v<_Compare>498_LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {499return __find_impl(*this, __x);500}501502_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const {503auto [__first, __last] = equal_range(__x);504return __last - __first;505}506507template <class _Kp>508requires __is_transparent_v<_Compare>509_LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {510auto [__first, __last] = equal_range(__x);511return __last - __first;512}513514_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }515516template <class _Kp>517requires __is_transparent_v<_Compare>518_LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {519return find(__x) != end();520}521522_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) {523const auto& __keys = __keys_;524return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));525}526527_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {528return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));529}530531template <class _Kp>532requires __is_transparent_v<_Compare>533_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {534const auto& __keys = __keys_;535return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));536}537538template <class _Kp>539requires __is_transparent_v<_Compare>540_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {541return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));542}543544_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) {545const auto& __keys = __keys_;546return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));547}548549_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {550return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));551}552553template <class _Kp>554requires __is_transparent_v<_Compare>555_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {556const auto& __keys = __keys_;557return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));558}559560template <class _Kp>561requires __is_transparent_v<_Compare>562_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {563return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));564}565566_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {567return __equal_range_impl(*this, __x);568}569570_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {571return __equal_range_impl(*this, __x);572}573574template <class _Kp>575requires __is_transparent_v<_Compare>576_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {577return __equal_range_impl(*this, __x);578}579template <class _Kp>580requires __is_transparent_v<_Compare>581_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {582return __equal_range_impl(*this, __x);583}584585friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) {586return ranges::equal(__x, __y);587}588589friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) {590return std::lexicographical_compare_three_way(591__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);592}593594friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); }595596private:597template <bool _WasSorted, class... _Args>598_LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) {599auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });600size_type __old_size = size();601__flat_set_utils::__append(*this, std::forward<_Args>(__args)...);602if constexpr (!_WasSorted) {603ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_);604} else {605_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(606ranges::is_sorted(__keys_ | ranges::views::drop(__old_size)), "Key container is not sorted");607}608ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_);609__on_failure.__complete();610}611612template <class _Kp>613_LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) {614auto __it = upper_bound(__key);615return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key));616}617618template <class _Kp>619_LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) {620auto __prev_larger = __hint != cbegin() && __compare_(__key, *std::prev(__hint));621auto __next_smaller = __hint != cend() && __compare_(*__hint, __key);622623if (!__prev_larger && !__next_smaller) [[likely]] {624// hint correct, just use exact hint iterator625} else if (__prev_larger && !__next_smaller) {626// the hint position is more to the right than the key should have been.627// we want to emplace the element to a position as right as possible628// e.g. Insert new element "2" in the following range629// 1, 1, 2, 2, 2, 3, 4, 6630// ^631// |632// hint633// We want to insert "2" after the last existing "2"634__hint = std::upper_bound(begin(), __hint, __key, __compare_);635} else {636_LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multiset is not sorted");637638// the hint position is more to the left than the key should have been.639// we want to emplace the element to a position as left as possible640// 1, 1, 2, 2, 2, 3, 4, 6641// ^642// |643// hint644// We want to insert "2" before the first existing "2"645__hint = std::lower_bound(__hint, end(), __key, __compare_);646}647return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key));648}649650template <class _Self, class _Kp>651_LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {652auto __it = __self.lower_bound(__key);653auto __last = __self.end();654if (__it == __last || __self.__compare_(__key, *__it)) {655return __last;656}657return __it;658}659660template <class _Self, class _Kp>661_LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {662using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>;663auto [__key_first, __key_last] =664std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_);665return std::make_pair(__iter(__key_first), __iter(__key_last));666}667668_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {669if constexpr (__container_traits<_KeyContainer>::__reservable) {670__keys_.reserve(__size);671}672}673674template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate>675friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type676erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate);677678_KeyContainer __keys_;679_LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;680681struct __key_equiv {682_LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}683_LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {684return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));685}686key_compare __comp_;687};688};689690template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>691requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&692is_invocable_v<const _Compare&,693const typename _KeyContainer::value_type&,694const typename _KeyContainer::value_type&>)695flat_multiset(_KeyContainer, _Compare = _Compare())696-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;697698template <class _KeyContainer, class _Allocator>699requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)700flat_multiset(_KeyContainer, _Allocator)701-> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;702703template <class _KeyContainer, class _Compare, class _Allocator>704requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&705uses_allocator_v<_KeyContainer, _Allocator> &&706is_invocable_v<const _Compare&,707const typename _KeyContainer::value_type&,708const typename _KeyContainer::value_type&>)709flat_multiset(_KeyContainer, _Compare, _Allocator)710-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;711712template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>713requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&714is_invocable_v<const _Compare&,715const typename _KeyContainer::value_type&,716const typename _KeyContainer::value_type&>)717flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare())718-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;719720template <class _KeyContainer, class _Allocator>721requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)722flat_multiset(sorted_equivalent_t, _KeyContainer, _Allocator)723-> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;724725template <class _KeyContainer, class _Compare, class _Allocator>726requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&727uses_allocator_v<_KeyContainer, _Allocator> &&728is_invocable_v<const _Compare&,729const typename _KeyContainer::value_type&,730const typename _KeyContainer::value_type&>)731flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Allocator)732-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;733734template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>735requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)736flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare())737-> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;738739template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>740requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)741flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())742-> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;743744template <ranges::input_range _Range,745class _Compare = less<ranges::range_value_t<_Range>>,746class _Allocator = allocator<ranges::range_value_t<_Range>>,747class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>748flat_multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multiset<749ranges::range_value_t<_Range>,750_Compare,751vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;752753template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>754flat_multiset(from_range_t, _Range&&, _Allocator) -> flat_multiset<755ranges::range_value_t<_Range>,756less<ranges::range_value_t<_Range>>,757vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;758759template <class _Key, class _Compare = less<_Key>>760requires(!__is_allocator<_Compare>::value)761flat_multiset(initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;762763template <class _Key, class _Compare = less<_Key>>764requires(!__is_allocator<_Compare>::value)765flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;766767template <class _Key, class _Compare, class _KeyContainer, class _Allocator>768struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Allocator>769: bool_constant<uses_allocator_v<_KeyContainer, _Allocator> > {};770771template <class _Key, class _Compare, class _KeyContainer, class _Predicate>772_LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type773erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) {774auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); });775auto __it =776std::remove_if(__flat_multiset.__keys_.begin(), __flat_multiset.__keys_.end(), [&](const auto& __e) -> bool {777return static_cast<bool>(__pred(__e));778});779auto __res = __flat_multiset.__keys_.end() - __it;780__flat_multiset.__keys_.erase(__it, __flat_multiset.__keys_.end());781__guard.__complete();782return __res;783}784785_LIBCPP_END_NAMESPACE_STD786787#endif // _LIBCPP_STD_VER >= 23788789_LIBCPP_POP_MACROS790791#endif // _LIBCPP___FLAT_MAP_FLAT_MULTISET_H792793794