[flat.map.modifiers]

# 23 Containers library [[containers]](./#containers)

## 23.6 Container adaptors [[container.adaptors]](container.adaptors#flat.map.modifiers)

### 23.6.8 Class template flat_map [[flat.map]](flat.map#modifiers)

#### 23.6.8.7 Modifiers [flat.map.modifiers]

[ð](#lib:emplace,flat_map)

`template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
`

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17690)

*Constraints*: is_constructible_v<pair<key_type, mapped_type>, Args...> is true[.](#1.sentence-1)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17694)

*Effects*: Initializes an object t of type pair<key_type, mapped_type> with std​::​forward<Args>(args)...;
if the map already contains an element
whose key is equivalent to t.first,*this is unchanged[.](#2.sentence-1)

Otherwise, equivalent to:auto key_it = ranges::upper_bound(*c*.keys, t.first, *compare*);auto value_it = *c*.values.begin() + distance(*c*.keys.begin(), key_it);*c*.keys.insert(key_it, std::move(t.first));*c*.values.insert(value_it, std::move(t.second));

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17709)

*Returns*: The bool component of the returned pair is true if and only if the insertion took place, and
the iterator component of the pair points to
the element with key equivalent to t.first[.](#3.sentence-1)

[ð](#lib:insert,flat_map)

`template<class P> constexpr pair<iterator, bool> insert(P&& x);
template<class P> constexpr iterator insert(const_iterator position, P&& x);
`

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17724)

*Constraints*: is_constructible_v<pair<key_type, mapped_type>, P> is true[.](#4.sentence-1)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17728)

*Effects*: The first form is equivalent to return emplace(std​::​forward<P>(x));[.](#5.sentence-1)

The second form is equivalent toreturn emplace_hint(position, std​::​forward<P>(x));[.](#5.sentence-2)

[ð](#lib:insert,flat_map_)

`template<class InputIterator>
  constexpr void insert(InputIterator first, InputIterator last);
`

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17742)

*Effects*: Adds elements to *c* as if by:for (; first != last; ++first) { value_type value = *first; *c*.keys.insert(*c*.keys.end(), std::move(value.first)); *c*.values.insert(*c*.values.end(), std::move(value.second));}

Then, sorts the range of newly inserted elements
with respect to value_comp();
merges the resulting sorted range and
the sorted range of pre-existing elements into a single sorted range; and
finally erases the duplicate elements as if by:auto zv = views::zip(*c*.keys, *c*.values);auto it = ranges::unique(zv, *key-equiv*(*compare*)).begin();auto dist = distance(zv.begin(), it);*c*.keys.erase(*c*.keys.begin() + dist, *c*.keys.end());*c*.values.erase(*c*.values.begin() + dist, *c*.values.end());

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17765)

*Complexity*: N + MlogM,
where N is size() before the operation andM is distance(first, last)[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17771)

*Remarks*: Since this operation performs an in-place merge, it may allocate memory[.](#8.sentence-1)

[ð](#lib:insert,flat_map__)

`template<class InputIterator>
  constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
`

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17783)

*Effects*: Adds elements to *c* as if by:for (; first != last; ++first) { value_type value = *first; *c*.keys.insert(*c*.keys.end(), std::move(value.first)); *c*.values.insert(*c*.values.end(), std::move(value.second));}

Then, merges the sorted range of newly added elements and
the sorted range of pre-existing elements into a single sorted range; and
finally erases the duplicate elements as if by:auto zv = views::zip(*c*.keys, *c*.values);auto it = ranges::unique(zv, *key-equiv*(*compare*)).begin();auto dist = distance(zv.begin(), it);*c*.keys.erase(*c*.keys.begin() + dist, *c*.keys.end());*c*.values.erase(*c*.values.begin() + dist, *c*.values.end());

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17804)

*Complexity*: Linear in N, where N is size() after the operation[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17808)

*Remarks*: Since this operation performs an in-place merge, it may allocate memory[.](#11.sentence-1)

[ð](#lib:insert_range,flat_map)

`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);
`

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17820)

*Effects*: Adds elements to *c* as if by:for (const auto& e : rg) {*c*.keys.insert(*c*.keys.end(), e.first); *c*.values.insert(*c*.values.end(), e.second);}

Then, sorts the range of newly inserted elements
with respect to value_comp();
merges the resulting sorted range and
the sorted range of pre-existing elements into a single sorted range; and
finally erases the duplicate elements as if by:auto zv = views::zip(*c*.keys, *c*.values);auto it = ranges::unique(zv, *key-equiv*(*compare*)).begin();auto dist = distance(zv.begin(), it);*c*.keys.erase(*c*.keys.begin() + dist, *c*.keys.end());*c*.values.erase(*c*.values.begin() + dist, *c*.values.end());

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17842)

*Complexity*: N + MlogM,
where N is size() before the operation andM is ranges​::​distance(rg)[.](#13.sentence-1)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17848)

*Remarks*: Since this operation performs an in-place merge, it may allocate memory[.](#14.sentence-1)

[ð](#lib:try_emplace,flat_map)

`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... 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);
`

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17866)

*Constraints*: is_constructible_v<mapped_type, Args...> is true[.](#15.sentence-1)

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17870)

*Effects*: If the map already contains an element whose key is equivalent to k,*this and args... are unchanged[.](#16.sentence-1)

Otherwise equivalent to:auto key_it = ranges::upper_bound(*c*.keys, k, *compare*);auto value_it = *c*.values.begin() + distance(*c*.keys.begin(), key_it);*c*.keys.insert(key_it, std::forward<decltype(k)>(k));*c*.values.emplace(value_it, std::forward<Args>(args)...);

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17882)

*Returns*: In the first two overloads,
the bool component of the returned pair is true if and only if the insertion took place[.](#17.sentence-1)

The returned iterator points to the map element
whose key is equivalent to k[.](#17.sentence-2)

[18](#18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17890)

*Complexity*: The same as emplace for the first two overloads, and
the same as emplace_hint for the last two overloads[.](#18.sentence-1)

[ð](#lib:try_emplace,flat_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);
`

[19](#19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17905)

*Constraints*: 

- [(19.1)](#19.1)

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

- [(19.2)](#19.2)

  is_constructible_v<key_type, K> is true[.](#19.2.sentence-1)

- [(19.3)](#19.3)

  is_constructible_v<mapped_type, Args...> is true[.](#19.3.sentence-1)

- [(19.4)](#19.4)

  For the first overload,is_convertible_v<K&&, const_iterator> andis_convertible_v<K&&, iterator> are both false[.](#19.4.sentence-1)

[20](#20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17921)

*Preconditions*: The conversion from k into key_type constructs
an object u,
for which find(k) == find(u) is true[.](#20.sentence-1)

[21](#21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17927)

*Effects*: If the map already contains an element whose key is equivalent to k,*this and args... are unchanged[.](#21.sentence-1)

Otherwise equivalent to:auto key_it = upper_bound(*c*.keys.begin(), *c*.keys.end(), k, *compare*);auto value_it = *c*.values.begin() + distance(*c*.keys.begin(), key_it);*c*.keys.emplace(key_it, std::forward<K>(k));*c*.values.emplace(value_it, std::forward<Args>(args)...);

[22](#22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17939)

*Returns*: In the first overload,
the bool component of the returned pair is true if and only if the insertion took place[.](#22.sentence-1)

The returned iterator points to the map element
whose key is equivalent to k[.](#22.sentence-2)

[23](#23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17947)

*Complexity*: The same as emplace and emplace_hint, respectively[.](#23.sentence-1)

[ð](#lib:insert_or_assign,flat_map)

`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 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);
`

[24](#24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17965)

*Constraints*: is_assignable_v<mapped_type&, M> is true andis_constructible_v<mapped_type, M> is true[.](#24.sentence-1)

[25](#25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17970)

*Effects*: If the map already contains an element e whose key is equivalent to k,
assigns std​::​forward<M>(obj) to e.second[.](#25.sentence-1)

Otherwise, equivalent totry_emplace(std::forward<decltype(k)>(k), std::forward<M>(obj)) for the first two overloads ortry_emplace(hint, std::forward<decltype(k)>(k), std::forward<M>(obj)) for the last two overloads[.](#25.sentence-2)

[26](#26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17985)

*Returns*: In the first two overloads, the bool component of the returned pair
is true if and only if the insertion took place[.](#26.sentence-1)

The returned
iterator points to the map element whose key is equivalent to k[.](#26.sentence-2)

[27](#27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L17991)

*Complexity*: The same as emplace for the first two overloads and
the same as emplace_hint for the last two overloads[.](#27.sentence-1)

[ð](#lib:insert_or_assign,flat_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);
`

[28](#28)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18006)

*Constraints*: 

- [(28.1)](#28.1)

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

- [(28.2)](#28.2)

  is_constructible_v<key_type, K> is true[.](#28.2.sentence-1)

- [(28.3)](#28.3)

  is_assignable_v<mapped_type&, M> is true[.](#28.3.sentence-1)

- [(28.4)](#28.4)

  is_constructible_v<mapped_type, M> is true[.](#28.4.sentence-1)

[29](#29)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18020)

*Preconditions*: The conversion from k into key_type constructs
an object u, for which find(k) == find(u) is true[.](#29.sentence-1)

[30](#30)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18025)

*Effects*: If the map already contains an element e whose key is equivalent to k,
assigns std​::​forward<M>(obj) to e.second[.](#30.sentence-1)

Otherwise, equivalent totry_emplace(std::forward<K>(k), std::forward<M>(obj)) for the first overload ortry_emplace(hint, std::forward<K>(k), std::forward<M>(obj)) for the second overload[.](#30.sentence-2)

[31](#31)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18040)

*Returns*: In the first overload,
the bool component of the returned pair is true if and only if the insertion took place[.](#31.sentence-1)

The returned iterator points to the map element
whose key is equivalent to k[.](#31.sentence-2)

[32](#32)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18048)

*Complexity*: The same as emplace and emplace_hint, respectively[.](#32.sentence-1)

[ð](#lib:swap,flat_map)

`constexpr void swap(flat_map& y) noexcept;
`

[33](#33)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18059)

*Effects*: Equivalent to:ranges::swap(*compare*, y.*compare*);
ranges::swap(*c*.keys, y.*c*.keys);
ranges::swap(*c*.values, y.*c*.values);

[ð](#lib:extract,flat_map)

`constexpr containers extract() &&;
`

[34](#34)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18075)

*Postconditions*: *this is emptied, even if the function exits via an exception[.](#34.sentence-1)

[35](#35)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18079)

*Returns*: std​::​move(*c*)[.](#35.sentence-1)

[ð](#lib:replace,flat_map)

`constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
`

[36](#36)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18090)

*Preconditions*: key_cont.size() == mapped_cont.size() is true,
the elements of key_cont are sorted with respect to *compare*, andkey_cont contains no equal elements[.](#36.sentence-1)

[37](#37)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L18096)

*Effects*: Equivalent to:*c*.keys = std::move(key_cont);*c*.values = std::move(mapped_cont);
