Path: blob/main/contrib/llvm-project/libcxx/include/__flat_map/flat_multimap.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_MULTIMAP_H10#define _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_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/remove_if.h>21#include <__algorithm/upper_bound.h>22#include <__assert>23#include <__compare/synth_three_way.h>24#include <__concepts/convertible_to.h>25#include <__concepts/swappable.h>26#include <__config>27#include <__cstddef/byte.h>28#include <__cstddef/ptrdiff_t.h>29#include <__flat_map/key_value_iterator.h>30#include <__flat_map/sorted_equivalent.h>31#include <__flat_map/utils.h>32#include <__functional/invoke.h>33#include <__functional/is_transparent.h>34#include <__functional/operations.h>35#include <__fwd/vector.h>36#include <__iterator/concepts.h>37#include <__iterator/distance.h>38#include <__iterator/iterator_traits.h>39#include <__iterator/ranges_iterator_traits.h>40#include <__iterator/reverse_iterator.h>41#include <__memory/allocator_traits.h>42#include <__memory/uses_allocator.h>43#include <__memory/uses_allocator_construction.h>44#include <__ranges/access.h>45#include <__ranges/concepts.h>46#include <__ranges/container_compatible_range.h>47#include <__ranges/drop_view.h>48#include <__ranges/from_range.h>49#include <__ranges/ref_view.h>50#include <__ranges/size.h>51#include <__ranges/subrange.h>52#include <__ranges/zip_view.h>53#include <__type_traits/conjunction.h>54#include <__type_traits/container_traits.h>55#include <__type_traits/invoke.h>56#include <__type_traits/is_allocator.h>57#include <__type_traits/is_nothrow_constructible.h>58#include <__type_traits/is_same.h>59#include <__type_traits/maybe_const.h>60#include <__utility/exception_guard.h>61#include <__utility/move.h>62#include <__utility/pair.h>63#include <__utility/scope_guard.h>64#include <__vector/vector.h>65#include <initializer_list>66#include <stdexcept>6768#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)69# pragma GCC system_header70#endif7172_LIBCPP_PUSH_MACROS73#include <__undef_macros>7475#if _LIBCPP_STD_VER >= 237677_LIBCPP_BEGIN_NAMESPACE_STD7879template <class _Key,80class _Tp,81class _Compare = less<_Key>,82class _KeyContainer = vector<_Key>,83class _MappedContainer = vector<_Tp>>84class flat_multimap {85template <class, class, class, class, class>86friend class flat_multimap;8788static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);89static_assert(is_same_v<_Tp, typename _MappedContainer::value_type>);90static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");91static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");9293template <bool _Const>94using __iterator _LIBCPP_NODEBUG = __key_value_iterator<flat_multimap, _KeyContainer, _MappedContainer, _Const>;9596public:97// types98using key_type = _Key;99using mapped_type = _Tp;100using value_type = pair<key_type, mapped_type>;101using key_compare = __type_identity_t<_Compare>;102using reference = pair<const key_type&, mapped_type&>;103using const_reference = pair<const key_type&, const mapped_type&>;104using size_type = size_t;105using difference_type = ptrdiff_t;106using iterator = __iterator<false>; // see [container.requirements]107using const_iterator = __iterator<true>; // see [container.requirements]108using reverse_iterator = std::reverse_iterator<iterator>;109using const_reverse_iterator = std::reverse_iterator<const_iterator>;110using key_container_type = _KeyContainer;111using mapped_container_type = _MappedContainer;112113class value_compare {114private:115_LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_;116_LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {}117friend flat_multimap;118119public:120_LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {121return __comp_(__x.first, __y.first);122}123};124125struct containers {126key_container_type keys;127mapped_container_type values;128};129130private:131template <class _Allocator>132_LIBCPP_HIDE_FROM_ABI static constexpr bool __allocator_ctor_constraint =133_And<uses_allocator<key_container_type, _Allocator>, uses_allocator<mapped_container_type, _Allocator>>::value;134135_LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare>;136137public:138// [flat.map.cons], construct/copy/destroy139_LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept(140is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> &&141is_nothrow_default_constructible_v<_Compare>)142: __containers_(), __compare_() {}143144_LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap&) = default;145146// The copy/move constructors are not specified in the spec, which means they should be defaulted.147// However, the move constructor can potentially leave a moved-from object in an inconsistent148// state if an exception is thrown.149_LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other) noexcept(150is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> &&151is_nothrow_move_constructible_v<_Compare>)152# if _LIBCPP_HAS_EXCEPTIONS153try154# endif // _LIBCPP_HAS_EXCEPTIONS155: __containers_(std::move(__other.__containers_)), __compare_(std::move(__other.__compare_)) {156__other.clear();157# if _LIBCPP_HAS_EXCEPTIONS158} catch (...) {159__other.clear();160// gcc does not like the `throw` keyword in a conditionally noexcept function161if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> &&162is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>)) {163throw;164}165# endif // _LIBCPP_HAS_EXCEPTIONS166}167168template <class _Allocator>169requires __allocator_ctor_constraint<_Allocator>170_LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap& __other, const _Allocator& __alloc)171: flat_multimap(__ctor_uses_allocator_tag{},172__alloc,173__other.__containers_.keys,174__other.__containers_.values,175__other.__compare_) {}176177template <class _Allocator>178requires __allocator_ctor_constraint<_Allocator>179_LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other, const _Allocator& __alloc)180# if _LIBCPP_HAS_EXCEPTIONS181try182# endif // _LIBCPP_HAS_EXCEPTIONS183: flat_multimap(__ctor_uses_allocator_tag{},184__alloc,185std::move(__other.__containers_.keys),186std::move(__other.__containers_.values),187std::move(__other.__compare_)) {188__other.clear();189# if _LIBCPP_HAS_EXCEPTIONS190} catch (...) {191__other.clear();192throw;193# endif // _LIBCPP_HAS_EXCEPTIONS194}195196_LIBCPP_HIDE_FROM_ABI flat_multimap(197key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare())198: __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {199_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),200"flat_multimap keys and mapped containers have different size");201__sort();202}203204template <class _Allocator>205requires __allocator_ctor_constraint<_Allocator>206_LIBCPP_HIDE_FROM_ABI flat_multimap(207const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc)208: flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {209_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),210"flat_multimap keys and mapped containers have different size");211__sort();212}213214template <class _Allocator>215requires __allocator_ctor_constraint<_Allocator>216_LIBCPP_HIDE_FROM_ABI217flat_multimap(const key_container_type& __key_cont,218const mapped_container_type& __mapped_cont,219const key_compare& __comp,220const _Allocator& __alloc)221: flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {222_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),223"flat_multimap keys and mapped containers have different size");224__sort();225}226227_LIBCPP_HIDE_FROM_ABI228flat_multimap(sorted_equivalent_t,229key_container_type __key_cont,230mapped_container_type __mapped_cont,231const key_compare& __comp = key_compare())232: __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {233_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),234"flat_multimap keys and mapped containers have different size");235_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");236}237238template <class _Allocator>239requires __allocator_ctor_constraint<_Allocator>240_LIBCPP_HIDE_FROM_ABI241flat_multimap(sorted_equivalent_t,242const key_container_type& __key_cont,243const mapped_container_type& __mapped_cont,244const _Allocator& __alloc)245: flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {246_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),247"flat_multimap keys and mapped containers have different size");248_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");249}250251template <class _Allocator>252requires __allocator_ctor_constraint<_Allocator>253_LIBCPP_HIDE_FROM_ABI254flat_multimap(sorted_equivalent_t,255const key_container_type& __key_cont,256const mapped_container_type& __mapped_cont,257const key_compare& __comp,258const _Allocator& __alloc)259: flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {260_LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),261"flat_multimap keys and mapped containers have different size");262_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");263}264265_LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const key_compare& __comp) : __containers_(), __compare_(__comp) {}266267template <class _Allocator>268requires __allocator_ctor_constraint<_Allocator>269_LIBCPP_HIDE_FROM_ABI flat_multimap(const key_compare& __comp, const _Allocator& __alloc)270: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {}271272template <class _Allocator>273requires __allocator_ctor_constraint<_Allocator>274_LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const _Allocator& __alloc)275: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {}276277template <class _InputIterator>278requires __has_input_iterator_category<_InputIterator>::value279_LIBCPP_HIDE_FROM_ABI280flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())281: __containers_(), __compare_(__comp) {282insert(__first, __last);283}284285template <class _InputIterator, class _Allocator>286requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)287_LIBCPP_HIDE_FROM_ABI288flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)289: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {290insert(__first, __last);291}292293template <class _InputIterator, class _Allocator>294requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)295_LIBCPP_HIDE_FROM_ABI flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)296: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {297insert(__first, __last);298}299300template <_ContainerCompatibleRange<value_type> _Range>301_LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t __fr, _Range&& __rg)302: flat_multimap(__fr, std::forward<_Range>(__rg), key_compare()) {}303304template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>305requires __allocator_ctor_constraint<_Allocator>306_LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc)307: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {308insert_range(std::forward<_Range>(__rg));309}310311template <_ContainerCompatibleRange<value_type> _Range>312_LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multimap(__comp) {313insert_range(std::forward<_Range>(__rg));314}315316template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>317requires __allocator_ctor_constraint<_Allocator>318_LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)319: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {320insert_range(std::forward<_Range>(__rg));321}322323template <class _InputIterator>324requires __has_input_iterator_category<_InputIterator>::value325_LIBCPP_HIDE_FROM_ABI flat_multimap(326sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())327: __containers_(), __compare_(__comp) {328insert(sorted_equivalent, __first, __last);329}330template <class _InputIterator, class _Allocator>331requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)332_LIBCPP_HIDE_FROM_ABI333flat_multimap(sorted_equivalent_t,334_InputIterator __first,335_InputIterator __last,336const key_compare& __comp,337const _Allocator& __alloc)338: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {339insert(sorted_equivalent, __first, __last);340}341342template <class _InputIterator, class _Allocator>343requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)344_LIBCPP_HIDE_FROM_ABI345flat_multimap(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)346: flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {347insert(sorted_equivalent, __first, __last);348}349350_LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list<value_type> __il, const key_compare& __comp = key_compare())351: flat_multimap(__il.begin(), __il.end(), __comp) {}352353template <class _Allocator>354requires __allocator_ctor_constraint<_Allocator>355_LIBCPP_HIDE_FROM_ABI356flat_multimap(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)357: flat_multimap(__il.begin(), __il.end(), __comp, __alloc) {}358359template <class _Allocator>360requires __allocator_ctor_constraint<_Allocator>361_LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list<value_type> __il, const _Allocator& __alloc)362: flat_multimap(__il.begin(), __il.end(), __alloc) {}363364_LIBCPP_HIDE_FROM_ABI365flat_multimap(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())366: flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp) {}367368template <class _Allocator>369requires __allocator_ctor_constraint<_Allocator>370_LIBCPP_HIDE_FROM_ABI flat_multimap(371sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)372: flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {}373374template <class _Allocator>375requires __allocator_ctor_constraint<_Allocator>376_LIBCPP_HIDE_FROM_ABI flat_multimap(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc)377: flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __alloc) {}378379_LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(initializer_list<value_type> __il) {380clear();381insert(__il);382return *this;383}384385// copy/move assignment are not specified in the spec (defaulted)386// but move assignment can potentially leave moved from object in an inconsistent387// state if an exception is thrown388_LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(const flat_multimap&) = default;389390_LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(flat_multimap&& __other) noexcept(391is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> &&392is_nothrow_move_assignable_v<_Compare>) {393auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });394auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });395__containers_ = std::move(__other.__containers_);396__compare_ = std::move(__other.__compare_);397__clear_self_guard.__complete();398return *this;399}400401// iterators402_LIBCPP_HIDE_FROM_ABI iterator begin() noexcept {403return iterator(__containers_.keys.begin(), __containers_.values.begin());404}405406_LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept {407return const_iterator(__containers_.keys.begin(), __containers_.values.begin());408}409410_LIBCPP_HIDE_FROM_ABI iterator end() noexcept {411return iterator(__containers_.keys.end(), __containers_.values.end());412}413414_LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept {415return const_iterator(__containers_.keys.end(), __containers_.values.end());416}417418_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }419_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }420_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }421_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }422423_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }424_LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }425_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }426_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }427428// [flat.map.capacity], capacity429[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); }430431_LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); }432433_LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept {434return std::min<size_type>(__containers_.keys.max_size(), __containers_.values.max_size());435}436437// [flat.map.modifiers], modifiers438template <class... _Args>439requires is_constructible_v<pair<key_type, mapped_type>, _Args...> && is_move_constructible_v<key_type> &&440is_move_constructible_v<mapped_type>441_LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {442std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);443auto __key_it = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_);444auto __mapped_it = __corresponding_mapped_it(*this, __key_it);445446return __flat_map_utils::__emplace_exact_pos(447*this, std::move(__key_it), std::move(__mapped_it), std::move(__pair.first), std::move(__pair.second));448}449450template <class... _Args>451requires is_constructible_v<pair<key_type, mapped_type>, _Args...>452_LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {453std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);454455auto __prev_larger = __hint != cbegin() && __compare_(__pair.first, (__hint - 1)->first);456auto __next_smaller = __hint != cend() && __compare_(__hint->first, __pair.first);457458auto __hint_distance = __hint.__key_iter_ - __containers_.keys.cbegin();459auto __key_iter = __containers_.keys.begin() + __hint_distance;460auto __mapped_iter = __containers_.values.begin() + __hint_distance;461462if (!__prev_larger && !__next_smaller) [[likely]] {463// hint correct, just use exact hint iterators464} else if (__prev_larger && !__next_smaller) {465// the hint position is more to the right than the key should have been.466// we want to emplace the element to a position as right as possible467// e.g. Insert new element "2" in the following range468// 1, 1, 2, 2, 2, 3, 4, 6469// ^470// |471// hint472// We want to insert "2" after the last existing "2"473__key_iter = std::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_);474__mapped_iter = __corresponding_mapped_it(*this, __key_iter);475} else {476_LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multimap is not sorted");477478// the hint position is more to the left than the key should have been.479// we want to emplace the element to a position as left as possible480// 1, 1, 2, 2, 2, 3, 4, 6481// ^482// |483// hint484// We want to insert "2" before the first existing "2"485__key_iter = std::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_);486__mapped_iter = __corresponding_mapped_it(*this, __key_iter);487}488return __flat_map_utils::__emplace_exact_pos(489*this, __key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second));490}491492_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }493494_LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }495496_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {497return emplace_hint(__hint, __x);498}499500_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {501return emplace_hint(__hint, std::move(__x));502}503504template <class _PairLike>505requires is_constructible_v<pair<key_type, mapped_type>, _PairLike>506_LIBCPP_HIDE_FROM_ABI iterator insert(_PairLike&& __x) {507return emplace(std::forward<_PairLike>(__x));508}509510template <class _PairLike>511requires is_constructible_v<pair<key_type, mapped_type>, _PairLike>512_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) {513return emplace_hint(__hint, std::forward<_PairLike>(__x));514}515516template <class _InputIterator>517requires __has_input_iterator_category<_InputIterator>::value518_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {519if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {520__reserve(__last - __first);521}522__append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last));523}524525template <class _InputIterator>526requires __has_input_iterator_category<_InputIterator>::value527_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) {528if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {529__reserve(__last - __first);530}531532__append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last));533}534535template <_ContainerCompatibleRange<value_type> _Range>536_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {537if constexpr (ranges::sized_range<_Range>) {538__reserve(ranges::size(__range));539}540541__append_sort_merge</*WasSorted = */ false>(ranges::begin(__range), ranges::end(__range));542}543544_LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }545546_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) {547insert(sorted_equivalent, __il.begin(), __il.end());548}549550_LIBCPP_HIDE_FROM_ABI containers extract() && {551auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });552auto __ret = std::move(__containers_);553return __ret;554}555556_LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) {557_LIBCPP_ASSERT_VALID_INPUT_RANGE(558__key_cont.size() == __mapped_cont.size(), "flat_multimap keys and mapped containers have different size");559560_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__key_cont), "Key container is not sorted");561auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });562__containers_.keys = std::move(__key_cont);563__containers_.values = std::move(__mapped_cont);564__guard.__complete();565}566567_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {568return __erase(__position.__key_iter_, __position.__mapped_iter_);569}570571_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) {572return __erase(__position.__key_iter_, __position.__mapped_iter_);573}574575_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {576auto [__first, __last] = equal_range(__x);577auto __res = __last - __first;578erase(__first, __last);579return __res;580}581582template <class _Kp>583requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> &&584!is_convertible_v<_Kp &&, const_iterator>)585_LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {586auto [__first, __last] = equal_range(__x);587auto __res = __last - __first;588erase(__first, __last);589return __res;590}591592_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {593auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });594auto __key_it = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_);595auto __mapped_it = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_);596__on_failure.__complete();597return iterator(std::move(__key_it), std::move(__mapped_it));598}599600_LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __y) noexcept {601// warning: The spec has unconditional noexcept, which means that602// if any of the following functions throw an exception,603// std::terminate will be called604ranges::swap(__compare_, __y.__compare_);605ranges::swap(__containers_.keys, __y.__containers_.keys);606ranges::swap(__containers_.values, __y.__containers_.values);607}608609_LIBCPP_HIDE_FROM_ABI void clear() noexcept {610__containers_.keys.clear();611__containers_.values.clear();612}613614// observers615_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }616_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); }617618_LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; }619_LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; }620621// map operations622_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }623624_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }625626template <class _Kp>627requires __is_compare_transparent628_LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {629return __find_impl(*this, __x);630}631632template <class _Kp>633requires __is_compare_transparent634_LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {635return __find_impl(*this, __x);636}637638_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const {639auto [__first, __last] = equal_range(__x);640return __last - __first;641}642643template <class _Kp>644requires __is_compare_transparent645_LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {646auto [__first, __last] = equal_range(__x);647return __last - __first;648}649650_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }651652template <class _Kp>653requires __is_compare_transparent654_LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {655return find(__x) != end();656}657658_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound<iterator>(*this, __x); }659660_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {661return __lower_bound<const_iterator>(*this, __x);662}663664template <class _Kp>665requires __is_compare_transparent666_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {667return __lower_bound<iterator>(*this, __x);668}669670template <class _Kp>671requires __is_compare_transparent672_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {673return __lower_bound<const_iterator>(*this, __x);674}675676_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound<iterator>(*this, __x); }677678_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {679return __upper_bound<const_iterator>(*this, __x);680}681682template <class _Kp>683requires __is_compare_transparent684_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {685return __upper_bound<iterator>(*this, __x);686}687688template <class _Kp>689requires __is_compare_transparent690_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {691return __upper_bound<const_iterator>(*this, __x);692}693694_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {695return __equal_range_impl(*this, __x);696}697698_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {699return __equal_range_impl(*this, __x);700}701702template <class _Kp>703requires __is_compare_transparent704_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {705return __equal_range_impl(*this, __x);706}707template <class _Kp>708requires __is_compare_transparent709_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {710return __equal_range_impl(*this, __x);711}712713friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multimap& __x, const flat_multimap& __y) {714return ranges::equal(__x, __y);715}716717friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multimap& __x, const flat_multimap& __y) {718return std::lexicographical_compare_three_way(719__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);720}721722friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __x, flat_multimap& __y) noexcept { __x.swap(__y); }723724private:725struct __ctor_uses_allocator_tag {726explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default;727};728struct __ctor_uses_allocator_empty_tag {729explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default;730};731732template <class _Allocator, class _KeyCont, class _MappedCont, class... _CompArg>733requires __allocator_ctor_constraint<_Allocator>734_LIBCPP_HIDE_FROM_ABI735flat_multimap(__ctor_uses_allocator_tag,736const _Allocator& __alloc,737_KeyCont&& __key_cont,738_MappedCont&& __mapped_cont,739_CompArg&&... __comp)740: __containers_{.keys = std::make_obj_using_allocator<key_container_type>(741__alloc, std::forward<_KeyCont>(__key_cont)),742.values = std::make_obj_using_allocator<mapped_container_type>(743__alloc, std::forward<_MappedCont>(__mapped_cont))},744__compare_(std::forward<_CompArg>(__comp)...) {}745746template <class _Allocator, class... _CompArg>747requires __allocator_ctor_constraint<_Allocator>748_LIBCPP_HIDE_FROM_ABI flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp)749: __containers_{.keys = std::make_obj_using_allocator<key_container_type>(__alloc),750.values = std::make_obj_using_allocator<mapped_container_type>(__alloc)},751__compare_(std::forward<_CompArg>(__comp)...) {}752753_LIBCPP_HIDE_FROM_ABI bool __is_sorted(auto&& __key_container) const {754return ranges::is_sorted(__key_container, __compare_);755}756757_LIBCPP_HIDE_FROM_ABI void __sort() {758auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);759ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); });760}761762template <class _Self, class _KeyIter>763_LIBCPP_HIDE_FROM_ABI static auto __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) {764return __self.__containers_.values.begin() +765static_cast<ranges::range_difference_t<mapped_container_type>>(766ranges::distance(__self.__containers_.keys.begin(), __key_iter));767}768769template <bool _WasSorted, class _InputIterator, class _Sentinel>770_LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_InputIterator __first, _Sentinel __last) {771auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });772size_t __num_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last));773if (__num_appended != 0) {774auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);775auto __append_start_offset = __containers_.keys.size() - __num_appended;776auto __end = __zv.end();777auto __compare_key = [this](const auto& __p1, const auto& __p2) {778return __compare_(std::get<0>(__p1), std::get<0>(__p2));779};780if constexpr (!_WasSorted) {781ranges::sort(__zv.begin() + __append_start_offset, __end, __compare_key);782} else {783_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(784__is_sorted(__containers_.keys | ranges::views::drop(__append_start_offset)),785"Key container is not sorted");786}787ranges::inplace_merge(__zv.begin(), __zv.begin() + __append_start_offset, __end, __compare_key);788}789__on_failure.__complete();790}791792template <class _Self, class _Kp>793_LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {794auto __it = __self.lower_bound(__key);795auto __last = __self.end();796if (__it == __last || __self.__compare_(__key, __it->first)) {797return __last;798}799return __it;800}801802template <class _Self, class _Kp>803_LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {804auto [__key_first, __key_last] =805std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_);806807using __iterator_type = ranges::iterator_t<decltype(__self)>;808return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)),809__iterator_type(__key_last, __corresponding_mapped_it(__self, __key_last)));810}811812template <class _Res, class _Self, class _Kp>813_LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) {814auto __key_iter =815std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);816auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);817return _Res(std::move(__key_iter), std::move(__mapped_iter));818}819820template <class _Res, class _Self, class _Kp>821_LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) {822auto __key_iter =823std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);824auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);825return _Res(std::move(__key_iter), std::move(__mapped_iter));826}827828_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {829if constexpr (__container_traits<_KeyContainer>::__reservable) {830__containers_.keys.reserve(__size);831}832833if constexpr (__container_traits<_MappedContainer>::__reservable) {834__containers_.values.reserve(__size);835}836}837838template <class _KIter, class _MIter>839_LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) {840auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });841auto __key_iter = __containers_.keys.erase(__key_iter_to_remove);842auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove);843__on_failure.__complete();844return iterator(std::move(__key_iter), std::move(__mapped_iter));845}846847template <class _Key2, class _Tp2, class _Compare2, class _KeyContainer2, class _MappedContainer2, class _Predicate>848friend typename flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type849erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);850851friend __flat_map_utils;852853containers __containers_;854_LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;855856struct __key_equiv {857_LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}858_LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {859return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));860}861key_compare __comp_;862};863};864865template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>866requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&867!__is_allocator<_MappedContainer>::value &&868is_invocable_v<const _Compare&,869const typename _KeyContainer::value_type&,870const typename _KeyContainer::value_type&>)871flat_multimap(_KeyContainer, _MappedContainer, _Compare = _Compare())872-> flat_multimap<typename _KeyContainer::value_type,873typename _MappedContainer::value_type,874_Compare,875_KeyContainer,876_MappedContainer>;877878template <class _KeyContainer, class _MappedContainer, class _Allocator>879requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&880!__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)881flat_multimap(_KeyContainer, _MappedContainer, _Allocator)882-> flat_multimap<typename _KeyContainer::value_type,883typename _MappedContainer::value_type,884less<typename _KeyContainer::value_type>,885_KeyContainer,886_MappedContainer>;887888template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>889requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&890!__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&891uses_allocator_v<_MappedContainer, _Allocator> &&892is_invocable_v<const _Compare&,893const typename _KeyContainer::value_type&,894const typename _KeyContainer::value_type&>)895flat_multimap(_KeyContainer, _MappedContainer, _Compare, _Allocator)896-> flat_multimap<typename _KeyContainer::value_type,897typename _MappedContainer::value_type,898_Compare,899_KeyContainer,900_MappedContainer>;901902template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>903requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&904!__is_allocator<_MappedContainer>::value &&905is_invocable_v<const _Compare&,906const typename _KeyContainer::value_type&,907const typename _KeyContainer::value_type&>)908flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare = _Compare())909-> flat_multimap<typename _KeyContainer::value_type,910typename _MappedContainer::value_type,911_Compare,912_KeyContainer,913_MappedContainer>;914915template <class _KeyContainer, class _MappedContainer, class _Allocator>916requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&917!__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)918flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Allocator)919-> flat_multimap<typename _KeyContainer::value_type,920typename _MappedContainer::value_type,921less<typename _KeyContainer::value_type>,922_KeyContainer,923_MappedContainer>;924925template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>926requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&927!__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&928uses_allocator_v<_MappedContainer, _Allocator> &&929is_invocable_v<const _Compare&,930const typename _KeyContainer::value_type&,931const typename _KeyContainer::value_type&>)932flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare, _Allocator)933-> flat_multimap<typename _KeyContainer::value_type,934typename _MappedContainer::value_type,935_Compare,936_KeyContainer,937_MappedContainer>;938939template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>940requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)941flat_multimap(_InputIterator, _InputIterator, _Compare = _Compare())942-> flat_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;943944template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>945requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)946flat_multimap(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())947-> flat_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;948949template <ranges::input_range _Range,950class _Compare = less<__range_key_type<_Range>>,951class _Allocator = allocator<byte>,952class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>953flat_multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multimap<954__range_key_type<_Range>,955__range_mapped_type<_Range>,956_Compare,957vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,958vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;959960template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>961flat_multimap(from_range_t, _Range&&, _Allocator) -> flat_multimap<962__range_key_type<_Range>,963__range_mapped_type<_Range>,964less<__range_key_type<_Range>>,965vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,966vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;967968template <class _Key, class _Tp, class _Compare = less<_Key>>969requires(!__is_allocator<_Compare>::value)970flat_multimap(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare()) -> flat_multimap<_Key, _Tp, _Compare>;971972template <class _Key, class _Tp, class _Compare = less<_Key>>973requires(!__is_allocator<_Compare>::value)974flat_multimap(sorted_equivalent_t, initializer_list<pair<_Key, _Tp>>, _Compare = _Compare())975-> flat_multimap<_Key, _Tp, _Compare>;976977template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Allocator>978struct uses_allocator<flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>, _Allocator>979: bool_constant<uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator>> {};980981template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Predicate>982_LIBCPP_HIDE_FROM_ABI typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type983erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) {984auto __zv = ranges::views::zip(__flat_multimap.__containers_.keys, __flat_multimap.__containers_.values);985auto __first = __zv.begin();986auto __last = __zv.end();987auto __guard = std::__make_exception_guard([&] { __flat_multimap.clear(); });988auto __it = std::remove_if(__first, __last, [&](auto&& __zipped) -> bool {989using _Ref = typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::const_reference;990return __pred(_Ref(std::get<0>(__zipped), std::get<1>(__zipped)));991});992auto __res = __last - __it;993auto __offset = __it - __first;994995const auto __erase_container = [&](auto& __cont) { __cont.erase(__cont.begin() + __offset, __cont.end()); };996997__erase_container(__flat_multimap.__containers_.keys);998__erase_container(__flat_multimap.__containers_.values);9991000__guard.__complete();1001return __res;1002}10031004_LIBCPP_END_NAMESPACE_STD10051006#endif // _LIBCPP_STD_VER >= 2310071008_LIBCPP_POP_MACROS10091010#endif // _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H101110121013