[associative] # 23 Containers library [[containers]](./#containers) ## 23.4 Associative containers [associative] ### [23.4.1](#general) General [[associative.general]](associative.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11363) The header [](#header:%3cmap%3e "23.4.2 Header synopsis [associative.map.syn]") defines the class templatesmap and multimap; the header [](#header:%3cset%3e "23.4.5 Header synopsis [associative.set.syn]") defines the class templatesset and multiset[.](#general-1.sentence-1) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11369) The following exposition-only alias templates may appear in deduction guides for associative containers:templateusing *iter-value-type* =typename iterator_traits::value_type; // *exposition only*templateusing *iter-key-type* = remove_const_t< tuple_element_t<0, *iter-value-type*>>; // *exposition only*templateusing *iter-mapped-type* = tuple_element_t<1, *iter-value-type*>; // *exposition only*templateusing *iter-to-alloc-type* = pair< add_const_t>>, tuple_element_t<1, *iter-value-type*>>; // *exposition only*templateusing *range-key-type* = remove_const_t::first_type>; // *exposition only*templateusing *range-mapped-type* = typename ranges::range_value_t::second_type; // *exposition only*templateusing *range-to-alloc-type* = pair::first_type>, typename ranges::range_value_t::second_type>; // *exposition only* ### [23.4.2](#map.syn) Header synopsis [[associative.map.syn]](associative.map.syn) [🔗](#header:%3cmap%3e) #include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")#include // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header synopsis")namespace std {// [[map]](#map "23.4.3 Class template map"), class template maptemplate, class Allocator = allocator>>class map; templateconstexpr bool operator==(const map& x, const map& y); templateconstexpr *synth-three-way-result*>operator<=>(const map& x, const map& y); templateconstexpr void swap(map& x, map& y)noexcept(noexcept(x.swap(y))); // [[map.erasure]](#map.erasure "23.4.3.5 Erasure"), erasure for maptemplateconstexpr typename map::size_type erase_if(map& c, Predicate pred); // [[multimap]](#multimap "23.4.4 Class template multimap"), class template multimaptemplate, class Allocator = allocator>>class multimap; templateconstexpr bool operator==(const multimap& x, const multimap& y); templateconstexpr *synth-three-way-result*>operator<=>(const multimap& x, const multimap& y); templateconstexpr void swap(multimap& x, multimap& y)noexcept(noexcept(x.swap(y))); // [[multimap.erasure]](#multimap.erasure "23.4.4.4 Erasure"), erasure for multimaptemplateconstexpr typename multimap::size_type erase_if(multimap& c, Predicate pred); namespace pmr {template>using map = std::map>>; template>using multimap = std::multimap>>; }} ### [23.4.3](#map) Class template map [[map]](map) #### [23.4.3.1](#map.overview) Overview [[map.overview]](map.overview) [1](#map.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11467) A map is an associative container that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of values of another type T based on the keys[.](#map.overview-1.sentence-1) The map class supports bidirectional iterators[.](#map.overview-1.sentence-2) [2](#map.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11473) A map meets all of the requirements of a container ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements")), of a reversible container ([[container.rev.reqmts]](container.rev.reqmts "23.2.2.3 Reversible container requirements")), of an allocator-aware container ([[container.alloc.reqmts]](container.alloc.reqmts "23.2.2.5 Allocator-aware containers")), and of an associative container ([[associative.reqmts]](associative.reqmts "23.2.7 Associative containers"))[.](#map.overview-2.sentence-1) Amap also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") for unique keys[.](#map.overview-2.sentence-2) This means that amap supports thea_uniq operations in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") but not thea_eq operations[.](#map.overview-2.sentence-3) For amap thekey_type isKey and thevalue_type ispair[.](#map.overview-2.sentence-4) Descriptions are provided here only for operations onmap that are not described in one of those tables or for operations where there is additional semantic information[.](#map.overview-2.sentence-5) [3](#map.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11506) The types iterator and const_iterator meet the constexpr iterator requirements ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General"))[.](#map.overview-3.sentence-1) [🔗](#lib:comp,map::value_compare) namespace std {template, class Allocator = allocator>>class map {public:// typesusing key_type = Key; using mapped_type = T; using value_type = pair; using key_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits::pointer; using const_pointer = typename allocator_traits::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using difference_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using node_type = *unspecified*; using insert_return_type = *insert-return-type*; class value_compare {protected: Compare comp; constexpr value_compare(Compare c) : comp(c) {}public:constexpr bool operator()(const value_type& x, const value_type& y) const {return comp(x.first, y.first); }}; // [[map.cons]](#map.cons "23.4.3.2 Constructors, copy, and assignment"), construct/copy/destroyconstexpr map() : map(Compare()) { }constexpr explicit map(const Compare& comp, const Allocator& = Allocator()); templateconstexpr map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); constexpr map(const map& x); constexpr map(map&& x); explicit map(const Allocator&); constexpr map(const map&, const type_identity_t&); constexpr map(map&&, const type_identity_t&); constexpr map(initializer_list, const Compare& = Compare(), const Allocator& = Allocator()); templateconstexpr map(InputIterator first, InputIterator last, const Allocator& a): map(first, last, Compare(), a) { }template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr map(from_range_t, R&& rg, const Allocator& a): map(from_range, std::forward(rg), Compare(), a) { }constexpr map(initializer_list il, const Allocator& a): map(il, Compare(), a) { }constexpr ~map(); constexpr map& operator=(const map& x); constexpr map& operator=(map&& x)noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v); constexpr map& operator=(initializer_list); constexpr allocator_type get_allocator() const noexcept; // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [[map.access]](#map.access "23.4.3.3 Element access"), element accessconstexpr mapped_type& operator[](const key_type& x); constexpr mapped_type& operator[](key_type&& x); template constexpr mapped_type& operator[](K&& x); constexpr mapped_type& at(const key_type& x); constexpr const mapped_type& at(const key_type& x) const; template constexpr mapped_type& at(const K& x); template constexpr const mapped_type& at(const K& x) const; // [[map.modifiers]](#map.modifiers "23.4.3.4 Modifiers"), modifierstemplate constexpr pair emplace(Args&&... args); templateconstexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr pair insert(const value_type& x); constexpr pair insert(value_type&& x); template constexpr pair insert(P&& x); constexpr iterator insert(const_iterator position, const value_type& x); constexpr iterator insert(const_iterator position, value_type&& x); templateconstexpr iterator insert(const_iterator position, P&&); templateconstexpr void insert(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list); constexpr node_type extract(const_iterator position); constexpr node_type extract(const key_type& x); template constexpr node_type extract(K&& x); constexpr insert_return_type insert(node_type&& nh); constexpr iterator insert(const_iterator hint, node_type&& nh); templateconstexpr pair try_emplace(const key_type& k, Args&&... args); templateconstexpr pair try_emplace(key_type&& k, Args&&... args); templateconstexpr pair try_emplace(K&& k, Args&&... args); templateconstexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); templateconstexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); templateconstexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); templateconstexpr pair insert_or_assign(const key_type& k, M&& obj); templateconstexpr pair insert_or_assign(key_type&& k, M&& obj); templateconstexpr pair insert_or_assign(K&& k, M&& obj); templateconstexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); templateconstexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); templateconstexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(map&)noexcept(allocator_traits::is_always_equal::value && is_nothrow_swappable_v); constexpr void clear() noexcept; templateconstexpr void merge(map& source); templateconstexpr void merge(map&& source); templateconstexpr void merge(multimap& source); templateconstexpr void merge(multimap&& source); // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // map operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair equal_range(const key_type& x); constexpr pair equal_range(const key_type& x) const; templateconstexpr pair equal_range(const K& x); templateconstexpr pair equal_range(const K& x) const; }; template>, class Allocator = allocator<*iter-to-alloc-type*>> map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())-> map<*iter-key-type*, *iter-mapped-type*, Compare, Allocator>; template, class Allocator = allocator<*range-to-alloc-type*>> map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> map<*range-key-type*, *range-mapped-type*, Compare, Allocator>; template, class Allocator = allocator>> map(initializer_list>, Compare = Compare(), Allocator = Allocator())-> map; template map(InputIterator, InputIterator, Allocator)-> map<*iter-key-type*, *iter-mapped-type*, less<*iter-key-type*>, Allocator>; template map(from_range_t, R&&, Allocator)-> map<*range-key-type*, *range-mapped-type*, less<*range-key-type*>, Allocator>; template map(initializer_list>, Allocator) -> map, Allocator>;} #### [23.4.3.2](#map.cons) Constructors, copy, and assignment [[map.cons]](map.cons) [🔗](#lib:map,constructor) `constexpr explicit map(const Compare& comp, const Allocator& = Allocator()); ` [1](#map.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11751) *Effects*: Constructs an emptymap using the specified comparison object and allocator[.](#map.cons-1.sentence-1) [2](#map.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11757) *Complexity*: Constant[.](#map.cons-2.sentence-1) [🔗](#lib:map,constructor_) `template constexpr map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [3](#map.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11770) *Effects*: Constructs an emptymap using the specified comparison object and allocator, and inserts elements from the range [first, last)[.](#map.cons-3.sentence-1) [4](#map.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11778) *Complexity*: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise NlogN, where N is last - first[.](#map.cons-4.sentence-1) [🔗](#lib:map,constructor__) `template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R> constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [5](#map.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11795) *Effects*: Constructs an empty map using the specified comparison object and allocator, and inserts elements from the range rg[.](#map.cons-5.sentence-1) [6](#map.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11801) *Complexity*: Linear in N if rg is already sorted with respect to comp and otherwise NlogN, where N is ranges​::​distance(rg)[.](#map.cons-6.sentence-1) #### [23.4.3.3](#map.access) Element access [[map.access]](map.access) [🔗](#lib:operator%5b%5d,map) `constexpr mapped_type& operator[](const key_type& x); ` [1](#map.access-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11815) *Effects*: Equivalent to: return try_emplace(x).first->second; [🔗](#lib:operator%5b%5d,map_) `constexpr mapped_type& operator[](key_type&& x); ` [2](#map.access-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11826) *Effects*: Equivalent to: return try_emplace(std​::​move(x)).first->second; [🔗](#lib:operator%5b%5d,map__) `template constexpr mapped_type& operator[](K&& x); ` [3](#map.access-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11837) *Constraints*: The [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Compare​::​is_transparent is valid and denotes a type[.](#map.access-3.sentence-1) [4](#map.access-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11842) *Effects*: Equivalent to: return try_emplace(std​::​forward(x)).first->second; [🔗](#lib:at,map) `constexpr mapped_type& at(const key_type& x); constexpr const mapped_type& at(const key_type& x) const; ` [5](#map.access-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11854) *Returns*: A reference to the mapped_type corresponding to x in *this[.](#map.access-5.sentence-1) [6](#map.access-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11858) *Throws*: An exception object of type out_of_range if no such element is present[.](#map.access-6.sentence-1) [7](#map.access-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11863) *Complexity*: Logarithmic[.](#map.access-7.sentence-1) [🔗](#lib:at,map_) `template constexpr mapped_type& at(const K& x); template constexpr const mapped_type& at(const K& x) const; ` [8](#map.access-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11875) *Constraints*: The [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Compare​::​is_transparent is valid and denotes a type[.](#map.access-8.sentence-1) [9](#map.access-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11880) *Preconditions*: The expression find(x) is well-formed and has well-defined behavior[.](#map.access-9.sentence-1) [10](#map.access-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11884) *Returns*: A reference to find(x)->second[.](#map.access-10.sentence-1) [11](#map.access-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11888) *Throws*: An exception object of type out_of_range iffind(x) == end() is true[.](#map.access-11.sentence-1) [12](#map.access-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11893) *Complexity*: Logarithmic[.](#map.access-12.sentence-1) #### [23.4.3.4](#map.modifiers) Modifiers [[map.modifiers]](map.modifiers) [🔗](#lib:insert,map) `template constexpr pair insert(P&& x); template constexpr iterator insert(const_iterator position, P&& x); ` [1](#map.modifiers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11909) *Constraints*: is_constructible_v is true[.](#map.modifiers-1.sentence-1) [2](#map.modifiers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11913) *Effects*: The first form is equivalent toreturn emplace(std​::​forward

(x))[.](#map.modifiers-2.sentence-1) The second form is equivalent to return emplace_hint(position, std​::​forward

(x))[.](#map.modifiers-2.sentence-2) [🔗](#lib:try_emplace,map) `template constexpr pair try_emplace(const key_type& k, Args&&... args); template constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); ` [3](#map.modifiers-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11929) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map from piecewise_construct, forward_as_tuple(k),forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-3.sentence-1) [4](#map.modifiers-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11935) *Effects*: If the map already contains an element whose key is equivalent to k, there is no effect[.](#map.modifiers-4.sentence-1) Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-4.sentence-2) [5](#map.modifiers-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11944) *Returns*: In the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-5.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-5.sentence-2) [6](#map.modifiers-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11952) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-6.sentence-1) [🔗](#lib:try_emplace,map_) `template constexpr pair try_emplace(key_type&& k, Args&&... args); template constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); ` [7](#map.modifiers-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11967) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map from piecewise_construct, forward_as_tuple(std​::​move(k)),forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-7.sentence-1) [8](#map.modifiers-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11973) *Effects*: If the map already contains an element whose key is equivalent to k, there is no effect[.](#map.modifiers-8.sentence-1) Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(std​::​move(k)),forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-8.sentence-2) [9](#map.modifiers-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11982) *Returns*: In the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-9.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-9.sentence-2) [10](#map.modifiers-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11990) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-10.sentence-1) [🔗](#lib:try_emplace,map__) `template constexpr pair try_emplace(K&& k, Args&&... args); template constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); ` [11](#map.modifiers-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12005) *Constraints*: The [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Compare​::​is_transparent is valid and denotes a type[.](#map.modifiers-11.sentence-1) For the first overload,is_convertible_v andis_convertible_v are both false[.](#map.modifiers-11.sentence-2) [12](#map.modifiers-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12014) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map frompiecewise_construct, forward_as_tuple(std​::​forward(k)), forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-12.sentence-1) [13](#map.modifiers-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12020) *Effects*: If the map already contains an element whose key is equivalent to k, there is no effect[.](#map.modifiers-13.sentence-1) Otherwise, let r be equal_range(k)[.](#map.modifiers-13.sentence-2) Constructs an object u of type value_type withpiecewise_construct, forward_as_tuple(std​::​forward(k)), forward_as_tuple(std​::​forward(args)...)[.](#map.modifiers-13.sentence-3) If equal_range(u.first) == r is false, the behavior is undefined[.](#map.modifiers-13.sentence-4) Inserts u into *this[.](#map.modifiers-13.sentence-5) [14](#map.modifiers-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12032) *Returns*: For the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-14.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-14.sentence-2) [15](#map.modifiers-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12040) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-15.sentence-1) [🔗](#lib:insert_or_assign,map) `template constexpr pair insert_or_assign(const key_type& k, M&& obj); template constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); ` [16](#map.modifiers-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12054) *Mandates*: is_assignable_v is true[.](#map.modifiers-16.sentence-1) [17](#map.modifiers-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12058) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map from k, std​::​forward(obj)[.](#map.modifiers-17.sentence-1) [18](#map.modifiers-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12063) *Effects*: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward(obj) to e.second[.](#map.modifiers-18.sentence-1) Otherwise inserts an object of type value_type constructed with k, std​::​forward(obj)[.](#map.modifiers-18.sentence-2) [19](#map.modifiers-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12071) *Returns*: In the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-19.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-19.sentence-2) [20](#map.modifiers-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12079) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-20.sentence-1) [🔗](#lib:insert_or_assign,map_) `template constexpr pair insert_or_assign(key_type&& k, M&& obj); template constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); ` [21](#map.modifiers-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12094) *Mandates*: is_assignable_v is true[.](#map.modifiers-21.sentence-1) [22](#map.modifiers-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12098) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map from std​::​move(k), std​::​forward(obj)[.](#map.modifiers-22.sentence-1) [23](#map.modifiers-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12103) *Effects*: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward(obj) to e.second[.](#map.modifiers-23.sentence-1) Otherwise inserts an object of type value_type constructed with std​::​​move(k), std​::​forward(obj)[.](#map.modifiers-23.sentence-2) [24](#map.modifiers-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12111) *Returns*: In the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-24.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-24.sentence-2) [25](#map.modifiers-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12119) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-25.sentence-1) [🔗](#lib:insert_or_assign,map__) `template constexpr pair insert_or_assign(K&& k, M&& obj); template constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); ` [26](#map.modifiers-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12134) *Constraints*: The [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Compare​::​is_transparent is valid and denotes a type[.](#map.modifiers-26.sentence-1) [27](#map.modifiers-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12139) *Mandates*: is_assignable_v is true[.](#map.modifiers-27.sentence-1) [28](#map.modifiers-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12143) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into map fromstd​::​forward(k), std​::​ forward(obj)[.](#map.modifiers-28.sentence-1) [29](#map.modifiers-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12148) *Effects*: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward (obj) to e.second[.](#map.modifiers-29.sentence-1) Otherwise, let r be equal_range(k)[.](#map.modifiers-29.sentence-2) Constructs an object u of type value_type with std​::​forward(k), std​::​forward(obj)[.](#map.modifiers-29.sentence-3) If equal_range(u.first) == r is false, the behavior is undefined[.](#map.modifiers-29.sentence-4) Inserts u into *this[.](#map.modifiers-29.sentence-5) [30](#map.modifiers-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12160) *Returns*: For the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#map.modifiers-30.sentence-1) The returned iterator points to the map element whose key is equivalent to k[.](#map.modifiers-30.sentence-2) [31](#map.modifiers-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12168) *Complexity*: The same as emplace and emplace_hint, respectively[.](#map.modifiers-31.sentence-1) #### [23.4.3.5](#map.erasure) Erasure [[map.erasure]](map.erasure) [🔗](#lib:erase_if,map) `template typename map::size_type constexpr erase_if(map& c, Predicate pred); ` [1](#map.erasure-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12183) *Effects*: Equivalent to:auto original_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {if (pred(*i)) { i = c.erase(i); } else {++i; }}return original_size - c.size(); ### [23.4.4](#multimap) Class template multimap [[multimap]](multimap) #### [23.4.4.1](#multimap.overview) Overview [[multimap.overview]](multimap.overview) [1](#multimap.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12203) Amultimap is an associative container that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another typeT based on the keys[.](#multimap.overview-1.sentence-1) Themultimap class supports bidirectional iterators[.](#multimap.overview-1.sentence-2) [2](#multimap.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12216) A multimap meets all of the requirements of a container ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements")), of a reversible container ([[container.rev.reqmts]](container.rev.reqmts "23.2.2.3 Reversible container requirements")), of an allocator-aware container ([[container.alloc.reqmts]](container.alloc.reqmts "23.2.2.5 Allocator-aware containers")), and of an associative container ([[associative.reqmts]](associative.reqmts "23.2.7 Associative containers"))[.](#multimap.overview-2.sentence-1) Amultimap also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") for equal keys[.](#multimap.overview-2.sentence-2) This means that amultimap supports thea_eq operations in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") but not thea_uniq operations[.](#multimap.overview-2.sentence-3) For amultimap thekey_type isKey and thevalue_type ispair[.](#multimap.overview-2.sentence-4) Descriptions are provided here only for operations onmultimap that are not described in one of those tables or for operations where there is additional semantic information[.](#multimap.overview-2.sentence-5) [3](#multimap.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12249) The types iterator and const_iterator meet the constexpr iterator requirements ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General"))[.](#multimap.overview-3.sentence-1) [🔗](#lib:comp,multimap::value_compare) namespace std {template, class Allocator = allocator>>class multimap {public:// typesusing key_type = Key; using mapped_type = T; using value_type = pair; using key_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits::pointer; using const_pointer = typename allocator_traits::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using difference_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using node_type = *unspecified*; class value_compare {protected: Compare comp; constexpr value_compare(Compare c) : comp(c) { }public:constexpr bool operator()(const value_type& x, const value_type& y) const {return comp(x.first, y.first); }}; // [[multimap.cons]](#multimap.cons "23.4.4.2 Constructors"), construct/copy/destroyconstexpr multimap() : multimap(Compare()) { }constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator()); templateconstexpr multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); constexpr multimap(const multimap& x); constexpr multimap(multimap&& x); constexpr explicit multimap(const Allocator&); constexpr multimap(const multimap&, const type_identity_t&); constexpr multimap(multimap&&, const type_identity_t&); constexpr multimap(initializer_list, const Compare& = Compare(), const Allocator& = Allocator()); templateconstexpr multimap(InputIterator first, InputIterator last, const Allocator& a): multimap(first, last, Compare(), a) { }template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr multimap(from_range_t, R&& rg, const Allocator& a)): multimap(from_range, std::forward(rg), Compare(), a) { }constexpr multimap(initializer_list il, const Allocator& a): multimap(il, Compare(), a) { }constexpr ~multimap(); constexpr multimap& operator=(const multimap& x); constexpr multimap& operator=(multimap&& x)noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v); constexpr multimap& operator=(initializer_list); constexpr allocator_type get_allocator() const noexcept; // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [[multimap.modifiers]](#multimap.modifiers "23.4.4.3 Modifiers"), modifierstemplate constexpr iterator emplace(Args&&... args); templateconstexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr iterator insert(const value_type& x); constexpr iterator insert(value_type&& x); template constexpr iterator insert(P&& x); constexpr iterator insert(const_iterator position, const value_type& x); constexpr iterator insert(const_iterator position, value_type&& x); template constexpr iterator insert(const_iterator position, P&& x); templateconstexpr void insert(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list); constexpr node_type extract(const_iterator position); constexpr node_type extract(const key_type& x); template node_type extract(K&& x); constexpr iterator insert(node_type&& nh); constexpr iterator insert(const_iterator hint, node_type&& nh); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(multimap&)noexcept(allocator_traits::is_always_equal::value && is_nothrow_swappable_v); constexpr void clear() noexcept; templateconstexpr void merge(multimap& source); templateconstexpr void merge(multimap&& source); templateconstexpr void merge(map& source); templateconstexpr void merge(map&& source); // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // map operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair equal_range(const key_type& x); constexpr pair equal_range(const key_type& x) const; templateconstexpr pair equal_range(const K& x); templateconstexpr pair equal_range(const K& x) const; }; template>, class Allocator = allocator<*iter-to-alloc-type*>> multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())-> multimap<*iter-key-type*, *iter-mapped-type*, Compare, Allocator>; template>, class Allocator = allocator<*range-to-alloc-type*>> multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> multimap<*range-key-type*, *range-mapped-type*, Compare, Allocator>; template, class Allocator = allocator>> multimap(initializer_list>, Compare = Compare(), Allocator = Allocator())-> multimap; template multimap(InputIterator, InputIterator, Allocator)-> multimap<*iter-key-type*, *iter-mapped-type*, less<*iter-key-type*>, Allocator>; template multimap(from_range_t, R&&, Allocator)-> multimap<*range-key-type*, *range-mapped-type*, less<*range-key-type*>, Allocator>; template multimap(initializer_list>, Allocator)-> multimap, Allocator>;} #### [23.4.4.2](#multimap.cons) Constructors [[multimap.cons]](multimap.cons) [🔗](#lib:multimap,constructor) `constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator()); ` [1](#multimap.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12459) *Effects*: Constructs an emptymultimap using the specified comparison object and allocator[.](#multimap.cons-1.sentence-1) [2](#multimap.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12465) *Complexity*: Constant[.](#multimap.cons-2.sentence-1) [🔗](#lib:multimap,constructor_) `template constexpr multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [3](#multimap.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12478) *Effects*: Constructs an emptymultimap using the specified comparison object and allocator, and inserts elements from the range [first, last)[.](#multimap.cons-3.sentence-1) [4](#multimap.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12486) *Complexity*: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise NlogN, where N islast - first[.](#multimap.cons-4.sentence-1) [🔗](#lib:multimap,constructor__) `template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R> constexpr multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [5](#multimap.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12504) *Effects*: Constructs an empty multimap using the specified comparison object and allocator, and inserts elements from the range rg[.](#multimap.cons-5.sentence-1) [6](#multimap.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12510) *Complexity*: Linear in N if rg is already sorted with respect to comp and otherwise NlogN, where N is ranges​::​distance(rg)[.](#multimap.cons-6.sentence-1) #### [23.4.4.3](#multimap.modifiers) Modifiers [[multimap.modifiers]](multimap.modifiers) [🔗](#lib:insert,multimap) `template constexpr iterator insert(P&& x); template constexpr iterator insert(const_iterator position, P&& x); ` [1](#multimap.modifiers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12525) *Constraints*: is_constructible_v is true[.](#multimap.modifiers-1.sentence-1) [2](#multimap.modifiers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12529) *Effects*: The first form is equivalent toreturn emplace(std​::​forward

(x))[.](#multimap.modifiers-2.sentence-1) The second form is equivalent to return emplace_hint(position, std​::​forward

(x))[.](#multimap.modifiers-2.sentence-2) #### [23.4.4.4](#multimap.erasure) Erasure [[multimap.erasure]](multimap.erasure) [🔗](#lib:erase_if,multimap) `template typename multimap::size_type constexpr erase_if(multimap& c, Predicate pred); ` [1](#multimap.erasure-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12546) *Effects*: Equivalent to:auto original_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {if (pred(*i)) { i = c.erase(i); } else {++i; }}return original_size - c.size(); ### [23.4.5](#set.syn) Header synopsis [[associative.set.syn]](associative.set.syn) [🔗](#header:%3cset%3e) #include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")#include // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header synopsis")namespace std {// [[set]](#set "23.4.6 Class template set"), class template settemplate, class Allocator = allocator>class set; templateconstexpr bool operator==(const set& x, const set& y); templateconstexpr *synth-three-way-result* operator<=>(const set& x, const set& y); templateconstexpr void swap(set& x, set& y)noexcept(noexcept(x.swap(y))); // [[set.erasure]](#set.erasure "23.4.6.3 Erasure"), erasure for settemplateconstexpr typename set::size_type erase_if(set& c, Predicate pred); // [[multiset]](#multiset "23.4.7 Class template multiset"), class template multisettemplate, class Allocator = allocator>class multiset; templateconstexpr bool operator==(const multiset& x, const multiset& y); templateconstexpr *synth-three-way-result*operator<=>(const multiset& x, const multiset& y); templateconstexpr void swap(multiset& x, multiset& y)noexcept(noexcept(x.swap(y))); // [[multiset.erasure]](#multiset.erasure "23.4.7.3 Erasure"), erasure for multisettemplateconstexpr typename multiset::size_type erase_if(multiset& c, Predicate pred); namespace pmr {template>using set = std::set>; template>using multiset = std::multiset>; }} ### [23.4.6](#set) Class template set [[set]](set) #### [23.4.6.1](#set.overview) Overview [[set.overview]](set.overview) [1](#set.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12627) Aset is an associative container that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of the keys themselves[.](#set.overview-1.sentence-1) Theset class supports bidirectional iterators[.](#set.overview-1.sentence-2) [2](#set.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12637) A set meets all of the requirements of a container ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements")), of a reversible container ([[container.rev.reqmts]](container.rev.reqmts "23.2.2.3 Reversible container requirements")), of an allocator-aware container ([[container.alloc.reqmts]](container.alloc.reqmts "23.2.2.5 Allocator-aware containers")), and of an associative container ([[associative.reqmts]](associative.reqmts "23.2.7 Associative containers"))[.](#set.overview-2.sentence-1) Aset also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") for unique keys[.](#set.overview-2.sentence-2) This means that aset supports thea_uniq operations in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") but not thea_eq operations[.](#set.overview-2.sentence-3) For aset both thekey_type andvalue_type areKey[.](#set.overview-2.sentence-4) Descriptions are provided here only for operations onset that are not described in one of these tables and for operations where there is additional semantic information[.](#set.overview-2.sentence-5) [3](#set.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12668) The types iterator and const_iterator meet the constexpr iterator requirements ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General"))[.](#set.overview-3.sentence-1) namespace std {template, class Allocator = allocator>class set {public:// typesusing key_type = Key; using key_compare = Compare; using value_type = Key; using value_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits::pointer; using const_pointer = typename allocator_traits::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using difference_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using node_type = *unspecified*; using insert_return_type = *insert-return-type*; // [[set.cons]](#set.cons "23.4.6.2 Constructors, copy, and assignment"), construct/copy/destroyconstexpr set() : set(Compare()) { }constexpr explicit set(const Compare& comp, const Allocator& = Allocator()); templateconstexpr set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); constexpr set(const set& x); constexpr set(set&& x); constexpr explicit set(const Allocator&); constexpr set(const set&, const type_identity_t&); constexpr set(set&&, const type_identity_t&); constexpr set(initializer_list, const Compare& = Compare(), const Allocator& = Allocator()); templateconstexpr set(InputIterator first, InputIterator last, const Allocator& a): set(first, last, Compare(), a) { }template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr set(from_range_t, R&& rg, const Allocator& a)): set(from_range, std::forward(rg), Compare(), a) { }constexpr set(initializer_list il, const Allocator& a): set(il, Compare(), a) { }constexpr ~set(); constexpr set& operator=(const set& x); constexpr set& operator=(set&& x)noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v); constexpr set& operator=(initializer_list); constexpr allocator_type get_allocator() const noexcept; // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [[set.modifiers]](#set.modifiers "23.4.6.4 Modifiers"), modifierstemplate constexpr pair emplace(Args&&... args); templateconstexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr pair insert(const value_type& x); constexpr pair insert(value_type&& x); template constexpr pair insert(K&& x); constexpr iterator insert(const_iterator position, const value_type& x); constexpr iterator insert(const_iterator position, value_type&& x); template constexpr iterator insert(const_iterator position, K&& x); templateconstexpr void insert(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list); constexpr node_type extract(const_iterator position); constexpr node_type extract(const key_type& x); template constexpr node_type extract(K&& x); constexpr insert_return_type insert(node_type&& nh); constexpr iterator insert(const_iterator hint, node_type&& nh); constexpr iterator erase(iterator position)requires (![same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(set&)noexcept(allocator_traits::is_always_equal::value && is_nothrow_swappable_v); constexpr void clear() noexcept; templateconstexpr void merge(set& source); templateconstexpr void merge(set&& source); templateconstexpr void merge(multiset& source); templateconstexpr void merge(multiset&& source); // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // set operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair equal_range(const key_type& x); constexpr pair equal_range(const key_type& x) const; templateconstexpr pair equal_range(const K& x); templateconstexpr pair equal_range(const K& x) const; }; template>, class Allocator = allocator<*iter-value-type*>> set(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())-> set<*iter-value-type*, Compare, Allocator>; template>, class Allocator = allocator>> set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> set, Compare, Allocator>; template, class Allocator = allocator> set(initializer_list, Compare = Compare(), Allocator = Allocator())-> set; template set(InputIterator, InputIterator, Allocator)-> set<*iter-value-type*, less<*iter-value-type*>, Allocator>; template set(from_range_t, R&&, Allocator)-> set, less>, Allocator>; template set(initializer_list, Allocator) -> set, Allocator>;} #### [23.4.6.2](#set.cons) Constructors, copy, and assignment [[set.cons]](set.cons) [🔗](#lib:set,constructor) `constexpr explicit set(const Compare& comp, const Allocator& = Allocator()); ` [1](#set.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12866) *Effects*: Constructs an empty set using the specified comparison object and allocator[.](#set.cons-1.sentence-1) [2](#set.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12870) *Complexity*: Constant[.](#set.cons-2.sentence-1) [🔗](#lib:set,constructor_) `template constexpr set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [3](#set.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12883) *Effects*: Constructs an emptyset using the specified comparison object and allocator, and inserts elements from the range [first, last)[.](#set.cons-3.sentence-1) [4](#set.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12891) *Complexity*: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise NlogN, where N islast - first[.](#set.cons-4.sentence-1) [🔗](#lib:set,constructor__) `template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R> constexpr set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [5](#set.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12909) *Effects*: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range rg[.](#set.cons-5.sentence-1) [6](#set.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12914) *Complexity*: Linear in N if rg is already sorted with respect to comp and otherwise NlogN, where N is ranges​::​distance(rg)[.](#set.cons-6.sentence-1) #### [23.4.6.3](#set.erasure) Erasure [[set.erasure]](set.erasure) [🔗](#lib:erase_if,set) `template constexpr typename set::size_type erase_if(set& c, Predicate pred); ` [1](#set.erasure-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12930) *Effects*: Equivalent to:auto original_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {if (pred(*i)) { i = c.erase(i); } else {++i; }}return original_size - c.size(); #### [23.4.6.4](#set.modifiers) Modifiers [[set.modifiers]](set.modifiers) [🔗](#lib:insert,set) `template constexpr pair insert(K&& x); template constexpr iterator insert(const_iterator hint, K&& x); ` [1](#set.modifiers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12955) *Constraints*: The [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Compare​::​is_transparent is valid and denotes a type[.](#set.modifiers-1.sentence-1) For the second overload,is_convertible_v andis_convertible_v are both false[.](#set.modifiers-1.sentence-2) [2](#set.modifiers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12963) *Preconditions*: value_type is *Cpp17EmplaceConstructible* into set fromstd​::​forward(x)[.](#set.modifiers-2.sentence-1) [3](#set.modifiers-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12968) *Effects*: If the set already contains an element that is equivalent to x, there is no effect[.](#set.modifiers-3.sentence-1) Otherwise, let r be equal_range(x)[.](#set.modifiers-3.sentence-2) Constructs an object u of type value_type with std​::​forward(x)[.](#set.modifiers-3.sentence-3) If equal_range(u) == r is false, the behavior is undefined[.](#set.modifiers-3.sentence-4) Inserts u into *this[.](#set.modifiers-3.sentence-5) [4](#set.modifiers-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12978) *Returns*: For the first overload, the bool component of the returned pair is true if and only if the insertion took place[.](#set.modifiers-4.sentence-1) The returned iterator points to the set element that is equivalent to x[.](#set.modifiers-4.sentence-2) [5](#set.modifiers-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12985) *Complexity*: Logarithmic[.](#set.modifiers-5.sentence-1) ### [23.4.7](#multiset) Class template multiset [[multiset]](multiset) #### [23.4.7.1](#multiset.overview) Overview [[multiset.overview]](multiset.overview) [1](#multiset.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12994) Amultiset is an associative container that supports equivalent keys (i.e., possibly contains multiple copies of the same key value) and provides for fast retrieval of the keys themselves[.](#multiset.overview-1.sentence-1) Themultiset class supports bidirectional iterators[.](#multiset.overview-1.sentence-2) [2](#multiset.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13004) A multiset meets all of the requirements of a container ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements")), of a reversible container ([[container.rev.reqmts]](container.rev.reqmts "23.2.2.3 Reversible container requirements")), of an allocator-aware container ([[container.alloc.reqmts]](container.alloc.reqmts "23.2.2.5 Allocator-aware containers")), and of an associative container ([[associative.reqmts]](associative.reqmts "23.2.7 Associative containers"))[.](#multiset.overview-2.sentence-1) multiset also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") for duplicate keys[.](#multiset.overview-2.sentence-2) This means that amultiset supports thea_eq operations in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") but not thea_uniq operations[.](#multiset.overview-2.sentence-3) For amultiset both thekey_type andvalue_type areKey[.](#multiset.overview-2.sentence-4) Descriptions are provided here only for operations onmultiset that are not described in one of these tables and for operations where there is additional semantic information[.](#multiset.overview-2.sentence-5) [3](#multiset.overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13034) The types iterator and const_iterator meet the constexpr iterator requirements ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General"))[.](#multiset.overview-3.sentence-1) namespace std {template, class Allocator = allocator>class multiset {public:// typesusing key_type = Key; using key_compare = Compare; using value_type = Key; using value_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits::pointer; using const_pointer = typename allocator_traits::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using difference_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using node_type = *unspecified*; // [[multiset.cons]](#multiset.cons "23.4.7.2 Constructors"), construct/copy/destroyconstexpr multiset() : multiset(Compare()) { }constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator()); templateconstexpr multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); constexpr multiset(const multiset& x); constexpr multiset(multiset&& x); constexpr explicit multiset(const Allocator&); constexpr multiset(const multiset&, const type_identity_t&); constexpr multiset(multiset&&, const type_identity_t&); constexpr multiset(initializer_list, const Compare& = Compare(), const Allocator& = Allocator()); templateconstexpr multiset(InputIterator first, InputIterator last, const Allocator& a): multiset(first, last, Compare(), a) { }template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr multiset(from_range_t, R&& rg, const Allocator& a)): multiset(from_range, std::forward(rg), Compare(), a) { }constexpr multiset(initializer_list il, const Allocator& a): multiset(il, Compare(), a) { }constexpr ~multiset(); constexpr multiset& operator=(const multiset& x); constexpr multiset& operator=(multiset&& x)noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v); constexpr multiset& operator=(initializer_list); constexpr allocator_type get_allocator() const noexcept; // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // modifierstemplate constexpr iterator emplace(Args&&... args); templateconstexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr iterator insert(const value_type& x); constexpr iterator insert(value_type&& x); constexpr iterator insert(const_iterator position, const value_type& x); constexpr iterator insert(const_iterator position, value_type&& x); templateconstexpr void insert(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list); constexpr node_type extract(const_iterator position); constexpr node_type extract(const key_type& x); template constexpr node_type extract(K&& x); constexpr iterator insert(node_type&& nh); constexpr iterator insert(const_iterator hint, node_type&& nh); constexpr iterator erase(iterator position)requires (![same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(multiset&)noexcept(allocator_traits::is_always_equal::value && is_nothrow_swappable_v); constexpr void clear() noexcept; templateconstexpr void merge(multiset& source); templateconstexpr void merge(multiset&& source); templateconstexpr void merge(set& source); templateconstexpr void merge(set&& source); // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // set operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair equal_range(const key_type& x); constexpr pair equal_range(const key_type& x) const; templateconstexpr pair equal_range(const K& x); templateconstexpr pair equal_range(const K& x) const; }; template>, class Allocator = allocator<*iter-value-type*>> multiset(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())-> multiset<*iter-value-type*, Compare, Allocator>; template>, class Allocator = allocator>> multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> multiset, Compare, Allocator>; template, class Allocator = allocator> multiset(initializer_list, Compare = Compare(), Allocator = Allocator())-> multiset; template multiset(InputIterator, InputIterator, Allocator)-> multiset<*iter-value-type*, less<*iter-value-type*>, Allocator>; template multiset(from_range_t, R&&, Allocator)-> multiset, less>, Allocator>; template multiset(initializer_list, Allocator) -> multiset, Allocator>;} #### [23.4.7.2](#multiset.cons) Constructors [[multiset.cons]](multiset.cons) [🔗](#lib:multiset,constructor) `constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator()); ` [1](#multiset.cons-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13229) *Effects*: Constructs an empty multiset using the specified comparison object and allocator[.](#multiset.cons-1.sentence-1) [2](#multiset.cons-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13233) *Complexity*: Constant[.](#multiset.cons-2.sentence-1) [🔗](#lib:multiset,constructor_) `template constexpr multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [3](#multiset.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13246) *Effects*: Constructs an emptymultiset using the specified comparison object and allocator, and inserts elements from the range [first, last)[.](#multiset.cons-3.sentence-1) [4](#multiset.cons-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13254) *Complexity*: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise NlogN, where N islast - first[.](#multiset.cons-4.sentence-1) [🔗](#lib:multiset,constructor__) `template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]") R> constexpr multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); ` [5](#multiset.cons-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13272) *Effects*: Constructs an empty multiset using the specified comparison object and allocator, and inserts elements from the range rg[.](#multiset.cons-5.sentence-1) [6](#multiset.cons-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13278) *Complexity*: Linear in N if rg is already sorted with respect to comp and otherwise NlogN, where N is ranges​::​distance(rg)[.](#multiset.cons-6.sentence-1) #### [23.4.7.3](#multiset.erasure) Erasure [[multiset.erasure]](multiset.erasure) [🔗](#lib:erase_if,multiset) `template constexpr typename multiset::size_type erase_if(multiset& c, Predicate pred); ` [1](#multiset.erasure-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L13294) *Effects*: Equivalent to:auto original_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {if (pred(*i)) { i = c.erase(i); } else {++i; }}return original_size - c.size();