Files
2025-10-25 03:02:53 +03:00

547 lines
31 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[map]
# 23 Containers library [[containers]](./#containers)
## 23.4 Associative containers [[associative]](associative#map)
### 23.4.3 Class template map [map]
#### [23.4.3.1](#overview) Overview [[map.overview]](map.overview)
[1](#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[.](#overview-1.sentence-1)
The map class supports bidirectional iterators[.](#overview-1.sentence-2)
[2](#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.2Container requirements")),
of a reversible container ([[container.rev.reqmts]](container.rev.reqmts "23.2.2.3Reversible container requirements")),
of an allocator-aware container ([[container.alloc.reqmts]](container.alloc.reqmts "23.2.2.5Allocator-aware containers")), and
of an associative container ([[associative.reqmts]](associative.reqmts "23.2.7Associative containers"))[.](#overview-2.sentence-1)
Amap also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7Associative containers") for unique keys[.](#overview-2.sentence-2)
This means that amap supports thea_uniq operations in [[associative.reqmts]](associative.reqmts "23.2.7Associative containers") but not thea_eq operations[.](#overview-2.sentence-3)
For amap<Key,T> thekey_type isKey and thevalue_type ispair<const Key,T>[.](#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[.](#overview-2.sentence-5)
[3](#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.1General"))[.](#overview-3.sentence-1)
[🔗](#lib:comp,map::value_compare)
namespace std {template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>class map {public:// typesusing key_type = Key; using mapped_type = T; using value_type = pair<const Key, T>; using key_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2Requirements")using difference_type = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2Requirements")using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2Requirements")using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = *unspecified*; using insert_return_type = *insert-return-type*<iterator, node_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]](#cons "23.4.3.2Constructors, copy, and assignment"), construct/copy/destroyconstexpr map() : map(Compare()) { }constexpr explicit map(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator>constexpr 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.1Introduction[container.intro.reqmts]")<value_type> 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<Allocator>&); constexpr map(map&&, const type_identity_t<Allocator>&); constexpr map(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator>constexpr 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.1Introduction[container.intro.reqmts]")<value_type> R>constexpr map(from_range_t, R&& rg, const Allocator& a): map(from_range, std::forward<R>(rg), Compare(), a) { }constexpr map(initializer_list<value_type> il, const Allocator& a): map(il, Compare(), a) { }constexpr ~map(); constexpr map& operator=(const map& x); constexpr map& operator=(map&& x)noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); constexpr map& operator=(initializer_list<value_type>); 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]](#access "23.4.3.3Element access"), element accessconstexpr mapped_type& operator[](const key_type& x); constexpr mapped_type& operator[](key_type&& x); template<class K> 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<class K> constexpr mapped_type& at(const K& x); template<class K> constexpr const mapped_type& at(const K& x) const; // [[map.modifiers]](#modifiers "23.4.3.4Modifiers"), modifierstemplate<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args); template<class... Args>constexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr pair<iterator, bool> insert(const value_type& x); constexpr pair<iterator, bool> insert(value_type&& x); template<class P> constexpr pair<iterator, bool> insert(P&& x); constexpr iterator insert(const_iterator position, const value_type& x); constexpr iterator insert(const_iterator position, value_type&& x); template<class P>constexpr iterator insert(const_iterator position, P&&); template<class InputIterator>constexpr void insert(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1Introduction[container.intro.reqmts]")<value_type> R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list<value_type>); constexpr node_type extract(const_iterator position); constexpr node_type extract(const key_type& x); template<class K> constexpr node_type extract(K&& x); constexpr insert_return_type insert(node_type&& nh); constexpr iterator insert(const_iterator hint, node_type&& nh); template<class... Args>constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args>constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args>constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args>constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args>constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args>constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); template<class M>constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M>constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M>constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class M>constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M>constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M>constexpr 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<class K> constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(map&)noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); constexpr void clear() noexcept; template<class C2>constexpr void merge(map<Key, T, C2, Allocator>& source); template<class C2>constexpr void merge(map<Key, T, C2, Allocator>&& source); template<class C2>constexpr void merge(multimap<Key, T, C2, Allocator>& source); template<class C2>constexpr void merge(multimap<Key, T, C2, Allocator>&& 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<class K> constexpr iterator find(const K& x); template<class K> constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template<class K> constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template<class K> 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<class K> constexpr iterator lower_bound(const K& x); template<class K> 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<class K> constexpr iterator upper_bound(const K& x); template<class K> constexpr const_iterator upper_bound(const K& x) const; constexpr pair<iterator, iterator> equal_range(const key_type& x); constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K>constexpr pair<iterator, iterator> equal_range(const K& x); template<class K>constexpr pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<*iter-key-type*<InputIterator>>, class Allocator = allocator<*iter-to-alloc-type*<InputIterator>>> map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())-> map<*iter-key-type*<InputIterator>, *iter-mapped-type*<InputIterator>, Compare, Allocator>; template<ranges::[input_range](range.refinements#concept:input_range "25.4.6Other range refinements[range.refinements]") R, class Compare = less<*range-key-type*<R>, class Allocator = allocator<*range-to-alloc-type*<R>>> map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> map<*range-key-type*<R>, *range-mapped-type*<R>, Compare, Allocator>; template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())-> map<Key, T, Compare, Allocator>; template<class InputIterator, class Allocator> map(InputIterator, InputIterator, Allocator)-> map<*iter-key-type*<InputIterator>, *iter-mapped-type*<InputIterator>,
less<*iter-key-type*<InputIterator>>, Allocator>; template<ranges::[input_range](range.refinements#concept:input_range "25.4.6Other range refinements[range.refinements]") R, class Allocator> map(from_range_t, R&&, Allocator)-> map<*range-key-type*<R>, *range-mapped-type*<R>, less<*range-key-type*<R>>, Allocator>; template<class Key, class T, class Allocator> map(initializer_list<pair<Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;}
#### [23.4.3.2](#cons) Constructors, copy, and assignment [[map.cons]](map.cons)
[🔗](#lib:map,constructor)
`constexpr explicit map(const Compare& comp, const Allocator& = Allocator());
`
[1](#cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11751)
*Effects*: Constructs an emptymap using the specified comparison object and allocator[.](#cons-1.sentence-1)
[2](#cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11757)
*Complexity*: Constant[.](#cons-2.sentence-1)
[🔗](#lib:map,constructor_)
`template<class InputIterator>
constexpr map(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& = Allocator());
`
[3](#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)[.](#cons-3.sentence-1)
[4](#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[.](#cons-4.sentence-1)
[🔗](#lib:map,constructor__)
`template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1Introduction[container.intro.reqmts]")<value_type> R>
constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(),
const Allocator& = Allocator());
`
[5](#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[.](#cons-5.sentence-1)
[6](#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)[.](#cons-6.sentence-1)
#### [23.4.3.3](#access) Element access [[map.access]](map.access)
[🔗](#lib:operator%5b%5d,map)
`constexpr mapped_type& operator[](const key_type& x);
`
[1](#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](#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<class K> constexpr mapped_type& operator[](K&& x);
`
[3](#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.3Qualified names[expr.prim.id.qual]") Compare::is_transparent is valid and denotes a type[.](#access-3.sentence-1)
[4](#access-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11842)
*Effects*: Equivalent to: return try_emplace(std::forward<K>(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](#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[.](#access-5.sentence-1)
[6](#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[.](#access-6.sentence-1)
[7](#access-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11863)
*Complexity*: Logarithmic[.](#access-7.sentence-1)
[🔗](#lib:at,map_)
`template<class K> constexpr mapped_type& at(const K& x);
template<class K> constexpr const mapped_type& at(const K& x) const;
`
[8](#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.3Qualified names[expr.prim.id.qual]") Compare::is_transparent is valid and denotes a type[.](#access-8.sentence-1)
[9](#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[.](#access-9.sentence-1)
[10](#access-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11884)
*Returns*: A reference to find(x)->second[.](#access-10.sentence-1)
[11](#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[.](#access-11.sentence-1)
[12](#access-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11893)
*Complexity*: Logarithmic[.](#access-12.sentence-1)
#### [23.4.3.4](#modifiers) Modifiers [[map.modifiers]](map.modifiers)
[🔗](#lib:insert,map)
`template<class P>
constexpr pair<iterator, bool> insert(P&& x);
template<class P>
constexpr iterator insert(const_iterator position, P&& x);
`
[1](#modifiers-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11909)
*Constraints*: is_constructible_v<value_type, P&&> is true[.](#modifiers-1.sentence-1)
[2](#modifiers-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11913)
*Effects*: The first form is equivalent toreturn emplace(std::forward<P>(x))[.](#modifiers-2.sentence-1)
The second form is
equivalent to return emplace_hint(position, std::forward<P>(x))[.](#modifiers-2.sentence-2)
[🔗](#lib:try_emplace,map)
`template<class... Args>
constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
`
[3](#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>(args)...)[.](#modifiers-3.sentence-1)
[4](#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[.](#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>(args)...)[.](#modifiers-4.sentence-2)
[5](#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[.](#modifiers-5.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-5.sentence-2)
[6](#modifiers-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11952)
*Complexity*: The same as emplace and emplace_hint,
respectively[.](#modifiers-6.sentence-1)
[🔗](#lib:try_emplace,map_)
`template<class... Args>
constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
`
[7](#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>(args)...)[.](#modifiers-7.sentence-1)
[8](#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[.](#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>(args)...)[.](#modifiers-8.sentence-2)
[9](#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[.](#modifiers-9.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-9.sentence-2)
[10](#modifiers-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L11990)
*Complexity*: The same as emplace and emplace_hint,
respectively[.](#modifiers-10.sentence-1)
[🔗](#lib:try_emplace,map__)
`template<class K, class... Args>
constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args);
template<class K, class... Args>
constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
`
[11](#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.3Qualified names[expr.prim.id.qual]") Compare::is_transparent is valid and denotes a type[.](#modifiers-11.sentence-1)
For the first overload,is_convertible_v<K&&, const_iterator> andis_convertible_v<K&&, iterator> are both false[.](#modifiers-11.sentence-2)
[12](#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>(k)),
forward_as_tuple(std::forward<Args>(args)...)[.](#modifiers-12.sentence-1)
[13](#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[.](#modifiers-13.sentence-1)
Otherwise, let r be equal_range(k)[.](#modifiers-13.sentence-2)
Constructs an object u of type value_type withpiecewise_construct, forward_as_tuple(std::forward<K>(k)),
forward_as_tuple(std::forward<Args>(args)...)[.](#modifiers-13.sentence-3)
If equal_range(u.first) == r is false,
the behavior is undefined[.](#modifiers-13.sentence-4)
Inserts u into *this[.](#modifiers-13.sentence-5)
[14](#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[.](#modifiers-14.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-14.sentence-2)
[15](#modifiers-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12040)
*Complexity*: The same as emplace and emplace_hint, respectively[.](#modifiers-15.sentence-1)
[🔗](#lib:insert_or_assign,map)
`template<class M>
constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
`
[16](#modifiers-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12054)
*Mandates*: is_assignable_v<mapped_type&, M&&> is true[.](#modifiers-16.sentence-1)
[17](#modifiers-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12058)
*Preconditions*: value_type is *Cpp17EmplaceConstructible* into map from k, std::forward<M>(obj)[.](#modifiers-17.sentence-1)
[18](#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<M>(obj) to e.second[.](#modifiers-18.sentence-1)
Otherwise inserts an object of type value_type constructed with k, std::forward<M>(obj)[.](#modifiers-18.sentence-2)
[19](#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[.](#modifiers-19.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-19.sentence-2)
[20](#modifiers-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12079)
*Complexity*: The same as emplace and emplace_hint,
respectively[.](#modifiers-20.sentence-1)
[🔗](#lib:insert_or_assign,map_)
`template<class M>
constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
`
[21](#modifiers-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12094)
*Mandates*: is_assignable_v<mapped_type&, M&&> is true[.](#modifiers-21.sentence-1)
[22](#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<M>(obj)[.](#modifiers-22.sentence-1)
[23](#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<M>(obj) to e.second[.](#modifiers-23.sentence-1)
Otherwise inserts an object of type value_type constructed with std::move(k), std::forward<M>(obj)[.](#modifiers-23.sentence-2)
[24](#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[.](#modifiers-24.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-24.sentence-2)
[25](#modifiers-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12119)
*Complexity*: The same as emplace and emplace_hint,
respectively[.](#modifiers-25.sentence-1)
[🔗](#lib:insert_or_assign,map__)
`template<class K, class M>
constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
template<class K, class M>
constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
`
[26](#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.3Qualified names[expr.prim.id.qual]") Compare::is_transparent is valid and denotes a type[.](#modifiers-26.sentence-1)
[27](#modifiers-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12139)
*Mandates*: is_assignable_v<mapped_type&, M&&> is true[.](#modifiers-27.sentence-1)
[28](#modifiers-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12143)
*Preconditions*: value_type is *Cpp17EmplaceConstructible* into map fromstd::forward<K>(k), std::
forward<M>(obj)[.](#modifiers-28.sentence-1)
[29](#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<M>
(obj) to e.second[.](#modifiers-29.sentence-1)
Otherwise, let r be equal_range(k)[.](#modifiers-29.sentence-2)
Constructs an object u of type value_type with std::forward<K>(k), std::forward<M>(obj)[.](#modifiers-29.sentence-3)
If equal_range(u.first) == r is false,
the behavior is undefined[.](#modifiers-29.sentence-4)
Inserts u into *this[.](#modifiers-29.sentence-5)
[30](#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[.](#modifiers-30.sentence-1)
The returned iterator points to the map element
whose key is equivalent to k[.](#modifiers-30.sentence-2)
[31](#modifiers-31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L12168)
*Complexity*: The same as emplace and emplace_hint, respectively[.](#modifiers-31.sentence-1)
#### [23.4.3.5](#erasure) Erasure [[map.erasure]](map.erasure)
[🔗](#lib:erase_if,map)
`template<class Key, class T, class Compare, class Allocator, class Predicate>
typename map<Key, T, Compare, Allocator>::size_type
constexpr erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);
`
[1](#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();