[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.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"))[.](#overview-2.sentence-1)

Amap also provides most operations described in [[associative.reqmts]](associative.reqmts "23.2.7 Associative containers") for unique keys[.](#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[.](#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.1 General"))[.](#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.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<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.2 Constructors, 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.1 Introduction [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.1 Introduction [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.3 Element 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.4 Modifiers"), 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.1 Introduction [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.6 Other 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.6 Other 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.1 Introduction [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.3 Qualified 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.3 Qualified 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.3 Qualified 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.3 Qualified 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();
